diff options
author | TheArcaneBrony <myrainbowdash949@gmail.com> | 2023-05-23 17:19:17 +0200 |
---|---|---|
committer | TheArcaneBrony <myrainbowdash949@gmail.com> | 2023-05-23 17:19:17 +0200 |
commit | f143c8cd3adc23a8f4473fc7cea7d1c58322233b (patch) | |
tree | 0aca8c6b5c694e46d3b713b965e35f7d9e89c322 /MatrixRoomUtils.Core | |
parent | Prevent deploy without commit (diff) | |
download | MatrixUtils-f143c8cd3adc23a8f4473fc7cea7d1c58322233b.tar.xz |
idk
Diffstat (limited to 'MatrixRoomUtils.Core')
-rw-r--r-- | MatrixRoomUtils.Core/Extensions/JsonElementExtensions.cs | 22 | ||||
-rw-r--r-- | MatrixRoomUtils.Core/Room.cs | 144 | ||||
-rw-r--r-- | MatrixRoomUtils.Core/RuntimeCache.cs | 23 |
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() { |