about summary refs log tree commit diff
path: root/MatrixUtils.Abstractions
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2024-01-24 02:31:56 +0100
committerRory& <root@rory.gay>2024-01-24 17:05:25 +0100
commit03313562d21d5db9bf6a14ebbeab80e06c883d3a (patch)
treee000546a2ee8e6a886a7ed9fd01ad674178fb7cb /MatrixUtils.Abstractions
parentMake RMU installable (diff)
downloadMatrixUtils-03313562d21d5db9bf6a14ebbeab80e06c883d3a.tar.xz
MRU->RMU, fixes, cleanup
Diffstat (limited to 'MatrixUtils.Abstractions')
-rw-r--r--MatrixUtils.Abstractions/FileStorageProvider.cs49
-rw-r--r--MatrixUtils.Abstractions/MatrixUtils.Abstractions.csproj12
-rw-r--r--MatrixUtils.Abstractions/RoomInfo.cs100
3 files changed, 161 insertions, 0 deletions
diff --git a/MatrixUtils.Abstractions/FileStorageProvider.cs b/MatrixUtils.Abstractions/FileStorageProvider.cs
new file mode 100644
index 0000000..fbe068d
--- /dev/null
+++ b/MatrixUtils.Abstractions/FileStorageProvider.cs
@@ -0,0 +1,49 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Text.Json;
+using ArcaneLibs.Extensions;
+using LibMatrix.Extensions;
+using LibMatrix.Interfaces.Services;
+using Microsoft.Extensions.Logging;
+
+namespace MatrixUtils.Abstractions;
+
+public class FileStorageProvider : IStorageProvider {
+    private readonly ILogger<FileStorageProvider> _logger;
+
+    public string TargetPath { get; }
+
+    /// <summary>
+    /// Creates a new instance of <see cref="FileStorageProvider" />.
+    /// </summary>
+    /// <param name="targetPath"></param>
+    public FileStorageProvider(string targetPath) {
+        // new Logger<FileStorageProvider>(new LoggerFactory()).LogInformation("test");
+        Console.WriteLine($"Initialised FileStorageProvider with path {targetPath}");
+        TargetPath = targetPath;
+        if (!Directory.Exists(targetPath)) {
+            Directory.CreateDirectory(targetPath);
+        }
+    }
+
+    public async Task SaveObjectAsync<T>(string key, T value) => await File.WriteAllTextAsync(Path.Join(TargetPath, key), value?.ToJson());
+
+    [RequiresUnreferencedCode("This API uses reflection to deserialize JSON")]
+    public async Task<T?> LoadObjectAsync<T>(string key) => JsonSerializer.Deserialize<T>(await File.ReadAllTextAsync(Path.Join(TargetPath, key)));
+
+    public Task<bool> ObjectExistsAsync(string key) => Task.FromResult(File.Exists(Path.Join(TargetPath, key)));
+
+    public Task<List<string>> GetAllKeysAsync() => Task.FromResult(Directory.GetFiles(TargetPath).Select(Path.GetFileName).ToList());
+
+    public Task DeleteObjectAsync(string key) {
+        File.Delete(Path.Join(TargetPath, key));
+        return Task.CompletedTask;
+    }
+
+    public async Task SaveStreamAsync(string key, Stream stream) {
+        Directory.CreateDirectory(Path.GetDirectoryName(Path.Join(TargetPath, key)) ?? throw new InvalidOperationException());
+        await using var fileStream = File.Create(Path.Join(TargetPath, key));
+        await stream.CopyToAsync(fileStream);
+    }
+
+    public Task<Stream?> LoadStreamAsync(string key) => Task.FromResult<Stream?>(File.Exists(Path.Join(TargetPath, key)) ? File.OpenRead(Path.Join(TargetPath, key)) : null);
+}
diff --git a/MatrixUtils.Abstractions/MatrixUtils.Abstractions.csproj b/MatrixUtils.Abstractions/MatrixUtils.Abstractions.csproj
new file mode 100644
index 0000000..1665ff0
--- /dev/null
+++ b/MatrixUtils.Abstractions/MatrixUtils.Abstractions.csproj
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+    <PropertyGroup>
+        <TargetFramework>net8.0</TargetFramework>
+        <ImplicitUsings>enable</ImplicitUsings>
+        <Nullable>enable</Nullable>
+    </PropertyGroup>
+    
+    <ItemGroup>
+        <ProjectReference Include="..\LibMatrix\LibMatrix\LibMatrix.csproj" />
+    </ItemGroup>
+</Project>
diff --git a/MatrixUtils.Abstractions/RoomInfo.cs b/MatrixUtils.Abstractions/RoomInfo.cs
new file mode 100644
index 0000000..84a5940
--- /dev/null
+++ b/MatrixUtils.Abstractions/RoomInfo.cs
@@ -0,0 +1,100 @@
+using System.Collections.ObjectModel;
+using System.Text.Json.Nodes;
+using ArcaneLibs;
+using LibMatrix;
+using LibMatrix.EventTypes.Spec.State;
+using LibMatrix.EventTypes.Spec.State.RoomInfo;
+using LibMatrix.RoomTypes;
+
+namespace MatrixUtils.Abstractions;
+
+public class RoomInfo : NotifyPropertyChanged {
+    public required GenericRoom Room { get; set; }
+    public ObservableCollection<StateEventResponse?> StateEvents { get; } = new();
+
+    public async Task<StateEventResponse?> GetStateEvent(string type, string stateKey = "") {
+        var @event = StateEvents.FirstOrDefault(x => x.Type == type && x.StateKey == stateKey);
+        if (@event is not null) return @event;
+        @event = new StateEventResponse {
+            RoomId = Room.RoomId,
+            Type = type,
+            StateKey = stateKey,
+            Sender = null, //TODO implement
+            EventId = null
+        };
+        // if (Room is null) return null;
+        try {
+            @event.RawContent = await Room.GetStateAsync<JsonObject>(type, stateKey);
+        }
+        catch (MatrixException e) {
+            if (e is { ErrorCode: "M_NOT_FOUND" }) {
+                if (type == "m.room.name")
+                    @event = new() {
+                        Type = type,
+                        StateKey = stateKey,
+                        TypedContent = new RoomNameEventContent() {
+                            Name = await Room.GetNameOrFallbackAsync()
+                        },
+                        //TODO implement
+                        RoomId = null,
+                        Sender = null,
+                        EventId = null
+                    };
+                else
+                    @event.RawContent = default!;
+            }
+            else {
+                throw;
+            }
+        }
+
+        StateEvents.Add(@event);
+        return @event;
+    }
+
+    public string? RoomIcon {
+        get => _roomIcon ?? "https://api.dicebear.com/6.x/identicon/svg?seed=" + Room.RoomId;
+        set => SetField(ref _roomIcon, value);
+    }
+
+    public string? RoomName {
+        get => _roomName ?? DefaultRoomName ?? Room.RoomId;
+        set => SetField(ref _roomName, value);
+    }
+
+    public RoomCreateEventContent? CreationEventContent {
+        get => _creationEventContent;
+        set => SetField(ref _creationEventContent, value);
+    }
+
+    public string? RoomCreator {
+        get => _roomCreator;
+        set => SetField(ref _roomCreator, value);
+    }
+
+    // public string? GetRoomIcon() => (StateEvents.FirstOrDefault(x => x?.Type == RoomAvatarEventContent.EventId)?.TypedContent as RoomAvatarEventContent)?.Url ??
+    // "mxc://rory.gay/dgP0YPjJEWaBwzhnbyLLwGGv";
+
+    private string? _roomIcon;
+    private string? _roomName;
+    private RoomCreateEventContent? _creationEventContent;
+    private string? _roomCreator;
+
+    public string? DefaultRoomName { get; set; }
+
+    public RoomInfo() {
+        StateEvents.CollectionChanged += (_, args) => {
+            if (args.NewItems is { Count: > 0 })
+                foreach (StateEventResponse newState in args.NewItems) { // TODO: switch statement benchmark?
+                    if (newState.Type == RoomNameEventContent.EventId && newState.TypedContent is RoomNameEventContent roomNameContent)
+                        RoomName = roomNameContent.Name;
+                    else if (newState is { Type: RoomAvatarEventContent.EventId, TypedContent: RoomAvatarEventContent roomAvatarContent })
+                        RoomIcon = roomAvatarContent.Url;
+                    else if (newState is { Type: RoomCreateEventContent.EventId, TypedContent: RoomCreateEventContent roomCreateContent }) {
+                        CreationEventContent = roomCreateContent;
+                        RoomCreator = newState.Sender;
+                    }
+                }
+        };
+    }
+}