about summary refs log tree commit diff
path: root/MatrixRoomUtils.Core
diff options
context:
space:
mode:
authorTheArcaneBrony <myrainbowdash949@gmail.com>2023-05-23 17:19:17 +0200
committerTheArcaneBrony <myrainbowdash949@gmail.com>2023-05-23 17:19:17 +0200
commitf143c8cd3adc23a8f4473fc7cea7d1c58322233b (patch)
tree0aca8c6b5c694e46d3b713b965e35f7d9e89c322 /MatrixRoomUtils.Core
parentPrevent deploy without commit (diff)
downloadMatrixUtils-f143c8cd3adc23a8f4473fc7cea7d1c58322233b.tar.xz
idk
Diffstat (limited to 'MatrixRoomUtils.Core')
-rw-r--r--MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs22
-rw-r--r--MatrixRoomUtils.Core/Room.cs144
-rw-r--r--MatrixRoomUtils.Core/RuntimeCache.cs23
3 files changed, 169 insertions, 20 deletions
diff --git a/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs b/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs
new file mode 100644
index 0000000..725c832
--- /dev/null
+++ b/MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs
@@ -0,0 +1,22 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace MatrixRoomUtils.Core.Extensions;
+
+public static class JsonElementExtensions
+{
+    public static void FindExtraJsonFields([DisallowNull] this JsonElement? res, Type t)
+    {
+        var props = t.GetProperties();
+        var unknownPropertyFound = false;
+        foreach (var field in res.Value.EnumerateObject())
+        {
+            if (props.Any(x => x.GetCustomAttribute<JsonPropertyNameAttribute>()?.Name == field.Name)) continue;
+            Console.WriteLine($"[!!] Unknown property {field.Name} in {t.Name}!");
+            unknownPropertyFound = true;
+        }
+        if(unknownPropertyFound) Console.WriteLine(res.Value.ToJson());
+    }
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/Room.cs b/MatrixRoomUtils.Core/Room.cs
index 6798d5b..362abf4 100644
--- a/MatrixRoomUtils.Core/Room.cs
+++ b/MatrixRoomUtils.Core/Room.cs
@@ -1,6 +1,10 @@
+using System.Diagnostics.CodeAnalysis;
 using System.Net.Http.Json;
+using System.Reflection;
 using System.Text.Json;
+using System.Text.Json.Serialization;
 using System.Web;
+using MatrixRoomUtils.Core.Extensions;
 
 namespace MatrixRoomUtils.Core;
 
@@ -21,16 +25,22 @@ public class Room
     {
         await _semaphore.WaitAsync();
         var url = $"/_matrix/client/v3/rooms/{RoomId}/state";
-        if (!string.IsNullOrEmpty(state_key)) url += $"/{type}/{state_key}";
-        else if (!string.IsNullOrEmpty(type)) url += $"/{type}";
-        var cache_key = "room_states:" + type;
+        var stateCombo = "";
+        if (!string.IsNullOrEmpty(state_key)) stateCombo += $"{type}/{state_key}";
+        else if (!string.IsNullOrEmpty(type)) stateCombo += $"{type}";
+        if (!string.IsNullOrEmpty(stateCombo)) url += $"/{stateCombo}";
+        var cache_key = "room_states#" + RoomId;
         if (!RuntimeCache.GenericResponseCache.ContainsKey(cache_key))
         {
             Console.WriteLine($"[!!] No cache for {cache_key}, creating...");
-            RuntimeCache.GenericResponseCache.Add(cache_key, new ObjectCache<object?>());
+            RuntimeCache.GenericResponseCache.Add(cache_key, new ObjectCache<object?>()
+            {
+                Name = cache_key
+            });
         }
+        var cache = RuntimeCache.GenericResponseCache[cache_key];
 
-        RuntimeCache.GenericResponseCache[cache_key].DefaultExpiry = type switch
+        cache.DefaultExpiry = type switch
         {
             "m.room.name" => TimeSpan.FromMinutes(30),
             "org.matrix.mjolnir.shortcode" => TimeSpan.FromHours(4),
@@ -38,17 +48,18 @@ public class Room
             _ => TimeSpan.FromMinutes(15)
         };
 
-        if (RuntimeCache.GenericResponseCache[cache_key].Cache.ContainsKey(url) && RuntimeCache.GenericResponseCache[cache_key][url] != null)
+        if (cache.ContainsKey(stateCombo))
         {
-            if (RuntimeCache.GenericResponseCache[cache_key][url].ExpiryTime > DateTime.Now)
+            if (cache[stateCombo].ExpiryTime > DateTime.Now)
             {
                 // Console.WriteLine($"[:3] Found cached state: {RuntimeCache.GenericResponseCache[cache_key][url].Result}");
                 _semaphore.Release();
-                return (JsonElement?)RuntimeCache.GenericResponseCache[cache_key][url].Result;
+                return (JsonElement?) cache[stateCombo].Result;
             }
             else
             {
-                Console.WriteLine($"[!!] Cached state expired at {RuntimeCache.GenericResponseCache[cache_key][url].ExpiryTime}: {RuntimeCache.GenericResponseCache[cache_key][url].Result}");
+                Console.WriteLine($"[!!] Cached state expired at {cache[stateCombo].ExpiryTime}: {cache[stateCombo].Result}");
+                if(cache[stateCombo].ExpiryTime == null)Console.WriteLine("Exiryt time was null");
             }
         }
         // else
@@ -66,13 +77,7 @@ public class Room
 
         var result = await res.Content.ReadFromJsonAsync<JsonElement>();
 
-        if (!RuntimeCache.GenericResponseCache.ContainsKey(cache_key) && type != "")
-        {
-            Console.WriteLine($"[!!] No cache for {cache_key}, creating...");
-            RuntimeCache.GenericResponseCache.Add(cache_key, new ObjectCache<object?>());
-        }
-
-        RuntimeCache.GenericResponseCache[cache_key][url] = new GenericResult<object>()
+        cache[stateCombo] = new GenericResult<object>()
         {
             Result = result
         };
@@ -102,4 +107,111 @@ public class Room
         var full_join_url = $"{join_url}?server_name=" + string.Join("&server_name=", homeservers);
         var res = await _httpClient.PostAsync(full_join_url, null);
     }
+    
+    public async Task<List<string>> GetMembersAsync()
+    {
+        var res = await GetStateAsync("");
+        if (!res.HasValue) return new List<string>();
+        var members = new List<string>();
+        foreach (var member in res.Value.EnumerateArray())
+        {
+            if(member.GetProperty("type").GetString() != "m.room.member") continue;
+            var member_id = member.GetProperty("state_key").GetString();
+            members.Add(member_id);
+        }
+
+        return members;
+    }
+    
+    public async Task<List<string>> GetAliasesAsync()
+    {
+        var res = await GetStateAsync("m.room.aliases");
+        if (!res.HasValue) return new List<string>();
+        var aliases = new List<string>();
+        foreach (var alias in res.Value.GetProperty("aliases").EnumerateArray())
+        {
+            aliases.Add(alias.GetString() ?? "");
+        }
+
+        return aliases;
+    }
+    
+    public async Task<string> GetCanonicalAliasAsync()
+    {
+        var res = await GetStateAsync("m.room.canonical_alias");
+        if (!res.HasValue) return "";
+        return res.Value.GetProperty("alias").GetString() ?? "";
+    }
+    
+    public async Task<string> GetTopicAsync()
+    {
+        var res = await GetStateAsync("m.room.topic");
+        if (!res.HasValue) return "";
+        return res.Value.GetProperty("topic").GetString() ?? "";
+    }
+    
+    public async Task<string> GetAvatarUrlAsync()
+    {
+        var res = await GetStateAsync("m.room.avatar");
+        if (!res.HasValue) return "";
+        return res.Value.GetProperty("url").GetString() ?? "";
+    }
+    
+    public async Task<JoinRules> GetJoinRuleAsync()
+    {
+        var res = await GetStateAsync("m.room.join_rules");
+        if (!res.HasValue) return new JoinRules();
+        return res.Value.Deserialize<JoinRules>() ?? new JoinRules();
+    }
+    
+    public async Task<string> GetHistoryVisibilityAsync()
+    {
+        var res = await GetStateAsync("m.room.history_visibility");
+        if (!res.HasValue) return "";
+        return res.Value.GetProperty("history_visibility").GetString() ?? "";
+    }
+    
+    public async Task<string> GetGuestAccessAsync()
+    {
+        var res = await GetStateAsync("m.room.guest_access");
+        if (!res.HasValue) return "";
+        return res.Value.GetProperty("guest_access").GetString() ?? "";
+    }
+    
+    public async Task<CreateEvent> GetCreateEventAsync()
+    {
+        var res = await GetStateAsync("m.room.create");
+        if (!res.HasValue) return new CreateEvent();
+        
+        res.FindExtraJsonFields(typeof(CreateEvent));
+
+        return res.Value.Deserialize<CreateEvent>() ?? new CreateEvent();
+    }
+}
+
+public class CreateEvent
+{
+    [JsonPropertyName("creator")]
+    public string Creator { get; set; }
+    [JsonPropertyName("room_version")]
+    public string RoomVersion { get; set; }
+    [JsonPropertyName("type")]
+    public string Type { get; set; }
+    [JsonPropertyName("predecessor")]
+    public object? Predecessor { get; set; }
+    
+    [JsonPropertyName("m.federate")]
+    public bool Federate { get; set; }
+}
+
+public class JoinRules
+{
+    private const string Public = "public";
+    private const string Invite = "invite";
+    private const string Knock = "knock";
+    
+    [JsonPropertyName("join_rule")]
+    public string JoinRule { get; set; }
+    [JsonPropertyName("allow")]
+    public List<string> Allow { get; set; }
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/RuntimeCache.cs b/MatrixRoomUtils.Core/RuntimeCache.cs
index 4a96f50..4e756a7 100644
--- a/MatrixRoomUtils.Core/RuntimeCache.cs
+++ b/MatrixRoomUtils.Core/RuntimeCache.cs
@@ -14,6 +14,15 @@ public class RuntimeCache
     // public static Dictionary<string, (DateTime cachedAt, ProfileResponse response)> ProfileCache { get; set; } = new();
 
     public static Dictionary<string, ObjectCache<object>> GenericResponseCache { get; set; } = new();
+    
+    public static Action Save { get; set; } = () =>
+    {
+        Console.WriteLine("RuntimeCache.Save() was called, but no callback was set!");
+    };
+    public static Action<string, object> SaveObject { get; set; } = (key, value) =>
+    {
+        Console.WriteLine($"RuntimeCache.SaveObject({key}, {value}) was called, but no callback was set!");
+    };
 }
 
 
@@ -32,17 +41,18 @@ public class HomeServerResolutionResult
 public class ObjectCache<T> where T : class
 {
     public Dictionary<string, GenericResult<T>> Cache { get; set; } = new();
-    public TimeSpan DefaultExpiry { get; set; } = new(0, 5, 0);
+    public TimeSpan DefaultExpiry { get; set; } = new(0, 0, 0);
+    public string Name { get; set; } = null!;
     public GenericResult<T> this[string key]
     {
         get
         {
             if (Cache.ContainsKey(key))
             {
+                Console.WriteLine($"cache.get({key}): hit");
                 // Console.WriteLine($"Found item in cache: {key} - {Cache[key].Result.ToJson(indent: false)}");
                 if(Cache[key].ExpiryTime > DateTime.Now)
                     return Cache[key];
-                
                 Console.WriteLine($"Expired item in cache: {key} - {Cache[key].Result.ToJson(indent: false)}");
                 try
                 {
@@ -53,13 +63,15 @@ public class ObjectCache<T> where T : class
                     Console.WriteLine($"Failed to remove {key} from cache: {e.Message}");
                 }
             }
-            Console.WriteLine($"No item in cache: {key}");
+            Console.WriteLine($"cache.get({key}): miss");
             return null;
         }
         set
         {
             Cache[key] = value;
             if(Cache[key].ExpiryTime == null) Cache[key].ExpiryTime = DateTime.Now.Add(DefaultExpiry);
+            Console.WriteLine($"set({key}) = {Cache[key].Result.ToJson(indent:false)}");
+            Console.WriteLine($"new_state: {this.ToJson(indent:false)}");
             // Console.WriteLine($"New item in cache: {key} - {Cache[key].Result.ToJson(indent: false)}");
             // Console.Error.WriteLine("Full cache: " + Cache.ToJson());
         }
@@ -78,14 +90,17 @@ public class ObjectCache<T> where T : class
                     // Console.WriteLine($"Removing {x.Key} from cache");
                     Cache.Remove(x.Key);   
                 }
+                RuntimeCache.SaveObject("rory.matrixroomutils.generic_cache:" + Name, this);
             }
         });
     }
+
+    public bool ContainsKey(string key) => Cache.ContainsKey(key);
 }
 public class GenericResult<T>
 {
     public T? Result { get; set; }
-    public DateTime? ExpiryTime { get; set; }
+    public DateTime? ExpiryTime { get; set; } = DateTime.Now;
     
     public GenericResult()
     {