about summary refs log tree commit diff
path: root/MatrixRoomUtils.Core
diff options
context:
space:
mode:
Diffstat (limited to 'MatrixRoomUtils.Core')
-rw-r--r--MatrixRoomUtils.Core/AuthenticatedHomeServer.cs26
-rw-r--r--MatrixRoomUtils.Core/Interfaces/IHomeServer.cs17
-rw-r--r--MatrixRoomUtils.Core/RemoteHomeServer.cs3
-rw-r--r--MatrixRoomUtils.Core/Room.cs70
-rw-r--r--MatrixRoomUtils.Core/RuntimeCache.cs45
5 files changed, 119 insertions, 42 deletions
diff --git a/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs b/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs
index 6f5df39..7a1f5de 100644
--- a/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs
+++ b/MatrixRoomUtils.Core/AuthenticatedHomeServer.cs
@@ -9,12 +9,14 @@ public class AuthenticatedHomeServer : IHomeServer
 {
     public string UserId { get; set; }
     public string AccessToken { get; set; }
+    public readonly HomeserverAdminApi Admin;
 
     public AuthenticatedHomeServer(string userId, string accessToken, string canonicalHomeServerDomain)
     {
         UserId = userId;
         AccessToken = accessToken;
         HomeServerDomain = canonicalHomeServerDomain;
+        Admin = new HomeserverAdminApi(this);
         _httpClient = new HttpClient();
     }
 
@@ -56,9 +58,25 @@ public class AuthenticatedHomeServer : IHomeServer
 
         return rooms;
     }
-
-    public async Task<string> ResolveMediaUri(string mxc)
+    
+    
+    
+    
+    
+    public class HomeserverAdminApi
     {
-        return mxc.Replace("mxc://", $"{FullHomeServerDomain}/_matrix/media/r0/download/");
+        private readonly AuthenticatedHomeServer _authenticatedHomeServer;
+
+        public HomeserverAdminApi(AuthenticatedHomeServer authenticatedHomeServer)
+        {
+            _authenticatedHomeServer = authenticatedHomeServer;
+        }
+    
+    
+        
+        
+        
+        
+        
     }
-}
\ No newline at end of file
+}
diff --git a/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs b/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs
index c6d788c..8fb8b2c 100644
--- a/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs
+++ b/MatrixRoomUtils.Core/Interfaces/IHomeServer.cs
@@ -15,6 +15,18 @@ public class IHomeServer
 
     public async Task<string> ResolveHomeserverFromWellKnown(string homeserver)
     {
+        var res = await _resolveHomeserverFromWellKnown(homeserver);
+        if(!res.StartsWith("http")) res = "https://" + res;
+        if(res.EndsWith(":443")) res = res.Substring(0, res.Length - 4);
+        return res;
+    }
+    private async Task<string> _resolveHomeserverFromWellKnown(string homeserver)
+    {
+        if (RuntimeCache.HomeserverResolutionCache.Count == 0)
+        {
+            Console.WriteLine("No cached homeservers, resolving...");
+            await Task.Delay(Random.Shared.Next(1000, 5000));
+        } 
         if (RuntimeCache.HomeserverResolutionCache.ContainsKey(homeserver))
         {
             if (RuntimeCache.HomeserverResolutionCache[homeserver].ResolutionTime < DateTime.Now.AddHours(1))
@@ -22,6 +34,7 @@ public class IHomeServer
                 Console.WriteLine($"Found cached homeserver: {RuntimeCache.HomeserverResolutionCache[homeserver].Result}");
                 return RuntimeCache.HomeserverResolutionCache[homeserver].Result;
             }
+            Console.WriteLine($"Cached homeserver expired, removing: {RuntimeCache.HomeserverResolutionCache[homeserver].Result}");
             RuntimeCache.HomeserverResolutionCache.Remove(homeserver);
         }
         //throw new NotImplementedException();
@@ -95,4 +108,8 @@ public class IHomeServer
         _profileCache[mxid] = profile;
         return profile;
     }
+    public async Task<string> ResolveMediaUri(string mxc)
+    {
+        return mxc.Replace("mxc://", $"{FullHomeServerDomain}/_matrix/media/r0/download/");
+    }
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/RemoteHomeServer.cs b/MatrixRoomUtils.Core/RemoteHomeServer.cs
index 9c096c8..942f873 100644
--- a/MatrixRoomUtils.Core/RemoteHomeServer.cs
+++ b/MatrixRoomUtils.Core/RemoteHomeServer.cs
@@ -1,7 +1,6 @@
 using System.Net.Http.Json;
 using System.Text.Json;
 using MatrixRoomUtils.Core.Interfaces;
-using MatrixRoomUtils.Core.Responses;
 
 namespace MatrixRoomUtils.Core;
 
@@ -13,12 +12,14 @@ public class RemoteHomeServer : IHomeServer
     {
         HomeServerDomain = canonicalHomeServerDomain;
         _httpClient = new HttpClient();
+        _httpClient.Timeout = TimeSpan.FromSeconds(5);
     }
     public async Task<RemoteHomeServer> Configure()
     {
         FullHomeServerDomain = await ResolveHomeserverFromWellKnown(HomeServerDomain);
         _httpClient.Dispose();
         _httpClient = new HttpClient { BaseAddress = new Uri(FullHomeServerDomain) };
+        _httpClient.Timeout = TimeSpan.FromSeconds(5);
         Console.WriteLine("[RHS] Finished setting up http client");
 
         return this;
diff --git a/MatrixRoomUtils.Core/Room.cs b/MatrixRoomUtils.Core/Room.cs
index 64db03d..6798d5b 100644
--- a/MatrixRoomUtils.Core/Room.cs
+++ b/MatrixRoomUtils.Core/Room.cs
@@ -1,10 +1,13 @@
 using System.Net.Http.Json;
 using System.Text.Json;
+using System.Web;
 
 namespace MatrixRoomUtils.Core;
 
 public class Room
 {
+    private static SemaphoreSlim _semaphore = new SemaphoreSlim(16, 16);
+
     private readonly HttpClient _httpClient;
     public string RoomId { get; set; }
 
@@ -13,31 +16,34 @@ public class Room
         _httpClient = httpClient;
         RoomId = roomId;
     }
-    
-    public async Task<JsonElement?> GetStateAsync(string type, string state_key="", bool logOnFailure = false)
+
+    public async Task<JsonElement?> GetStateAsync(string type, string state_key = "", bool logOnFailure = false)
     {
+        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 cache_key = "room_states:" + type;
         if (!RuntimeCache.GenericResponseCache.ContainsKey(cache_key))
         {
             Console.WriteLine($"[!!] No cache for {cache_key}, creating...");
-            RuntimeCache.GenericResponseCache.Add(cache_key, new ObjectCache<object?>()
-            {
-                DefaultExpiry = type switch
-                {
-                    "m.room.name" => TimeSpan.FromMinutes(15),
-                    _ => TimeSpan.FromMinutes(5)
-                }
-            });
+            RuntimeCache.GenericResponseCache.Add(cache_key, new ObjectCache<object?>());
         }
 
-        if (RuntimeCache.GenericResponseCache[cache_key][url] != null)
+        RuntimeCache.GenericResponseCache[cache_key].DefaultExpiry = type switch
+        {
+            "m.room.name" => TimeSpan.FromMinutes(30),
+            "org.matrix.mjolnir.shortcode" => TimeSpan.FromHours(4),
+            "" => TimeSpan.FromSeconds(0),
+            _ => TimeSpan.FromMinutes(15)
+        };
+
+        if (RuntimeCache.GenericResponseCache[cache_key].Cache.ContainsKey(url) && RuntimeCache.GenericResponseCache[cache_key][url] != null)
         {
-            if(RuntimeCache.GenericResponseCache[cache_key][url].ExpiryTime > DateTime.Now)
+            if (RuntimeCache.GenericResponseCache[cache_key][url].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;
             }
             else
@@ -45,35 +51,55 @@ public class Room
                 Console.WriteLine($"[!!] Cached state expired at {RuntimeCache.GenericResponseCache[cache_key][url].ExpiryTime}: {RuntimeCache.GenericResponseCache[cache_key][url].Result}");
             }
         }
-        else
-        {
-            Console.WriteLine($"[!!] No cached state for {url}");
-        }
+        // else
+        // {
+        //     Console.WriteLine($"[!!] No cached state for {url}");
+        // }
 
         var res = await _httpClient.GetAsync(url);
         if (!res.IsSuccessStatusCode)
         {
-            if(logOnFailure) Console.WriteLine($"{RoomId}/{state_key}/{type} - got status: {res.StatusCode}");
+            if (logOnFailure) Console.WriteLine($"{RoomId}/{state_key}/{type} - got status: {res.StatusCode}");
+            _semaphore.Release();
             return null;
         }
+
         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>()
         {
             Result = result
         };
+        _semaphore.Release();
         return result;
     }
-    public async Task<string?> GetNameAsync()
+
+    public async Task<string> GetNameAsync()
     {
         var res = await GetStateAsync("m.room.name");
         if (!res.HasValue)
         {
             Console.WriteLine($"Room {RoomId} has no name!");
-            return null;
+            return RoomId;
         }
-        var resn = res?.TryGetProperty("name", out var name) ?? false ? name.GetString() : null;
+
+        var resn = res?.TryGetProperty("name", out var name) ?? false ? name.GetString() ?? RoomId : RoomId;
         //Console.WriteLine($"Got name: {resn}");
         return resn;
     }
-    
+
+    public async Task JoinAsync(string[]? homeservers = null)
+    {
+        string join_url = $"/_matrix/client/r0/join/{HttpUtility.UrlEncode(RoomId)}";
+        Console.WriteLine($"Calling {join_url} with {(homeservers == null ? 0 : homeservers.Length)} via's...");
+        if(homeservers == null || homeservers.Length == 0) homeservers = new[] { RoomId.Split(':')[1] };
+        var full_join_url = $"{join_url}?server_name=" + string.Join("&server_name=", homeservers);
+        var res = await _httpClient.PostAsync(full_join_url, null);
+    }
 }
\ No newline at end of file
diff --git a/MatrixRoomUtils.Core/RuntimeCache.cs b/MatrixRoomUtils.Core/RuntimeCache.cs
index affbd94..4a96f50 100644
--- a/MatrixRoomUtils.Core/RuntimeCache.cs
+++ b/MatrixRoomUtils.Core/RuntimeCache.cs
@@ -1,6 +1,3 @@
-using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.JavaScript;
-using System.Xml.Schema;
 using MatrixRoomUtils.Core.Extensions;
 using MatrixRoomUtils.Core.Responses;
 
@@ -40,17 +37,6 @@ public class ObjectCache<T> where T : class
     {
         get
         {
-            if (Random.Shared.Next(100) == 1)
-            {
-                // Console.WriteLine("Cleaning cache...");
-                // foreach (var x in Cache.Where(x => x.Value.ExpiryTime < DateTime.Now).OrderBy(x => x.Value.ExpiryTime).Take(3).ToList())
-                // {
-                    // Console.WriteLine($"Removing {x.Key} from cache");
-                    // Cache.Remove(x.Key);   
-                // }
-            }
-
-            
             if (Cache.ContainsKey(key))
             {
                 // Console.WriteLine($"Found item in cache: {key} - {Cache[key].Result.ToJson(indent: false)}");
@@ -67,19 +53,48 @@ public class ObjectCache<T> where T : class
                     Console.WriteLine($"Failed to remove {key} from cache: {e.Message}");
                 }
             }
+            Console.WriteLine($"No item in cache: {key}");
             return null;
         }
         set
         {
             Cache[key] = value;
             if(Cache[key].ExpiryTime == null) Cache[key].ExpiryTime = DateTime.Now.Add(DefaultExpiry);
-            Console.WriteLine($"New item in cache: {key} - {Cache[key].Result.ToJson(indent: false)}");
+            // Console.WriteLine($"New item in cache: {key} - {Cache[key].Result.ToJson(indent: false)}");
             // Console.Error.WriteLine("Full cache: " + Cache.ToJson());
         }
     }
+    
+    public ObjectCache()
+    {
+        //expiry timer
+        Task.Run(async () =>
+        {
+            while (true)
+            {
+                await Task.Delay(1000);
+                foreach (var x in Cache.Where(x => x.Value.ExpiryTime < DateTime.Now).OrderBy(x => x.Value.ExpiryTime).Take(15).ToList())
+                {
+                    // Console.WriteLine($"Removing {x.Key} from cache");
+                    Cache.Remove(x.Key);   
+                }
+            }
+        });
+    }
 }
 public class GenericResult<T>
 {
     public T? Result { get; set; }
     public DateTime? ExpiryTime { get; set; }
+    
+    public GenericResult()
+    {
+        //expiry timer
+        
+    }
+    public GenericResult(T? result, DateTime? expiryTime = null) : this()
+    {
+        Result = result;
+        ExpiryTime = expiryTime;
+    }
 }