about summary refs log tree commit diff
path: root/LibMatrix
diff options
context:
space:
mode:
Diffstat (limited to 'LibMatrix')
-rw-r--r--LibMatrix/Extensions/HttpClientExtensions.cs21
-rw-r--r--LibMatrix/Helpers/SyncHelper.cs7
-rw-r--r--LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs38
-rw-r--r--LibMatrix/Homeservers/RemoteHomeServer.cs4
-rw-r--r--LibMatrix/Responses/SyncResponse.cs6
-rw-r--r--LibMatrix/RoomTypes/GenericRoom.cs6
-rw-r--r--LibMatrix/Services/HomeserverProviderService.cs38
-rw-r--r--LibMatrix/Services/ServiceInstaller.cs14
-rw-r--r--LibMatrix/StateEvent.cs5
9 files changed, 80 insertions, 59 deletions
diff --git a/LibMatrix/Extensions/HttpClientExtensions.cs b/LibMatrix/Extensions/HttpClientExtensions.cs
index 17cc31d..71bb0e5 100644
--- a/LibMatrix/Extensions/HttpClientExtensions.cs
+++ b/LibMatrix/Extensions/HttpClientExtensions.cs
@@ -37,7 +37,7 @@ public class MatrixHttpClient : HttpClient {
         return options;
     }
 
-    public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
+    public async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
         if (request.RequestUri is null) throw new NullReferenceException("RequestUri is null");
         if (!request.RequestUri.IsAbsoluteUri) request.RequestUri = new Uri(BaseAddress, request.RequestUri);
         // if (AssertedUserId is not null) request.RequestUri = request.RequestUri.AddQuery("user_id", AssertedUserId);
@@ -58,15 +58,18 @@ public class MatrixHttpClient : HttpClient {
         }
 
         HttpResponseMessage responseMessage;
-        try {
+        // try {
             responseMessage = await base.SendAsync(request, cancellationToken);
-        }
-        catch (Exception e) {
-            typeof(HttpRequestMessage).GetField("_sendStatus", BindingFlags.NonPublic | BindingFlags.Instance)
-                ?.SetValue(request, 0);
-            await Task.Delay(2500, cancellationToken);
-            return await SendAsync(request, cancellationToken);
-        }
+        // }
+        // catch (Exception e) {
+            // if (requestSettings is { Retries: 0 }) throw;
+            // typeof(HttpRequestMessage).GetField("_sendStatus", BindingFlags.NonPublic | BindingFlags.Instance)
+            // ?.SetValue(request, 0);
+            // await Task.Delay(requestSettings?.RetryDelay ?? 2500, cancellationToken);
+            // if(requestSettings is not null) requestSettings.Retries--;
+            // return await SendAsync(request, cancellationToken);
+            // throw;
+        // }
 
         if (responseMessage.IsSuccessStatusCode) return responseMessage;
 
diff --git a/LibMatrix/Helpers/SyncHelper.cs b/LibMatrix/Helpers/SyncHelper.cs
index ba42735..0a11849 100644
--- a/LibMatrix/Helpers/SyncHelper.cs
+++ b/LibMatrix/Helpers/SyncHelper.cs
@@ -1,5 +1,7 @@
 using System.Diagnostics;
 using System.Net.Http.Json;
+using System.Text.Json;
+using System.Text.Json.Serialization;
 using ArcaneLibs.Extensions;
 using LibMatrix.Filters;
 using LibMatrix.Homeservers;
@@ -28,8 +30,7 @@ public class SyncHelper(AuthenticatedHomeserverGeneric homeserver, ILogger? logg
             Console.WriteLine("Homeserver for SyncHelper is not properly configured!");
             throw new ArgumentNullException(nameof(homeserver.ClientHttpClient), "Null passed as homeserver for SyncHelper!");
         }
-
-
+        
         var sw = Stopwatch.StartNew();
 
         var url = $"/_matrix/client/v3/sync?timeout={Timeout}&set_presence={SetPresence}&full_state={(FullState ? "true" : "false")}";
@@ -42,7 +43,7 @@ public class SyncHelper(AuthenticatedHomeserverGeneric homeserver, ILogger? logg
             if (httpResp is null) throw new NullReferenceException("Failed to send HTTP request");
             logger?.LogInformation("Got sync response: {} bytes, {} elapsed", httpResp.Content.Headers.ContentLength ?? -1, sw.Elapsed);
             var deserializeSw = Stopwatch.StartNew();
-            var resp = await httpResp.Content.ReadFromJsonAsync<SyncResponse>(cancellationToken: cancellationToken ?? CancellationToken.None);
+            var resp = await httpResp.Content.ReadFromJsonAsync<SyncResponse>(cancellationToken: cancellationToken ?? CancellationToken.None, jsonTypeInfo: SyncResponseSerializerContext.Default.SyncResponse);
             logger?.LogInformation("Deserialized sync response: {} bytes, {} elapsed, {} total", httpResp.Content.Headers.ContentLength ?? -1, deserializeSw.Elapsed, sw.Elapsed);
             var timeToWait = MinimumDelay.Subtract(sw.Elapsed);
             if (timeToWait.TotalMilliseconds > 0)
diff --git a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
index c1d6461..6fcd8e8 100644
--- a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
+++ b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
@@ -16,37 +16,41 @@ using LibMatrix.Services;
 namespace LibMatrix.Homeservers;
 
 public class AuthenticatedHomeserverGeneric(string serverName, string accessToken) : RemoteHomeserver(serverName) {
-    public static async Task<T> Create<T>(string serverName, string accessToken, string? proxy = null) where T : AuthenticatedHomeserverGeneric {
-        var instance = Activator.CreateInstance(typeof(T), serverName, accessToken) as T
-                       ?? throw new InvalidOperationException($"Failed to create instance of {typeof(T).Name}");
-        HomeserverResolverService.WellKnownUris? urls = null;
-        if (proxy is null)
-            urls = await new HomeserverResolverService().ResolveHomeserverFromWellKnown(serverName);
-
+    public static async Task<T> Create<T>(string serverName, string accessToken, string? proxy = null) where T : AuthenticatedHomeserverGeneric =>
+        await Create(typeof(T), serverName, accessToken, proxy) as T ?? throw new InvalidOperationException($"Failed to create instance of {typeof(T).Name}");
+    public static async Task<AuthenticatedHomeserverGeneric> Create(Type type, string serverName, string accessToken, string? proxy = null) {
+        if(!type.IsAssignableTo(typeof(AuthenticatedHomeserverGeneric))) throw new ArgumentException("Type must be a subclass of AuthenticatedHomeserverGeneric", nameof(type));
+        var instance = Activator.CreateInstance(type, serverName, accessToken) as AuthenticatedHomeserverGeneric
+                       ?? throw new InvalidOperationException($"Failed to create instance of {type.Name}");
+        
         instance.ClientHttpClient = new() {
-            BaseAddress = new Uri(proxy ?? urls?.Client
-                ?? throw new InvalidOperationException("Failed to resolve homeserver")),
             Timeout = TimeSpan.FromMinutes(15),
             DefaultRequestHeaders = {
                 Authorization = new AuthenticationHeaderValue("Bearer", accessToken)
             }
         };
         instance.ServerHttpClient = new() {
-            BaseAddress = new Uri(proxy ?? urls?.Server
-                ?? throw new InvalidOperationException("Failed to resolve homeserver")),
             Timeout = TimeSpan.FromMinutes(15),
             DefaultRequestHeaders = {
                 Authorization = new AuthenticationHeaderValue("Bearer", accessToken)
             }
         };
 
-        instance.WhoAmI = await instance.ClientHttpClient.GetFromJsonAsync<WhoAmIResponse>("/_matrix/client/v3/account/whoami");
-
-        if (proxy is not null) {
+        if (string.IsNullOrWhiteSpace(proxy)) {
+            HomeserverResolverService.WellKnownUris? urls = await new HomeserverResolverService().ResolveHomeserverFromWellKnown(serverName);
+            instance.ClientHttpClient.BaseAddress = new Uri(urls?.Client ?? throw new InvalidOperationException("Failed to resolve homeserver"));
+            instance.ServerHttpClient.BaseAddress = new Uri(urls?.Server ?? throw new InvalidOperationException("Failed to resolve homeserver"));
+        }
+        else {
+            instance.ClientHttpClient.BaseAddress = new Uri(proxy);
+            instance.ServerHttpClient.BaseAddress = new Uri(proxy);
             instance.ClientHttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", serverName);
             instance.ServerHttpClient.DefaultRequestHeaders.Add("MXAE_UPSTREAM", serverName);
         }
 
+        instance.WhoAmI = await instance.ClientHttpClient.GetFromJsonAsync<WhoAmIResponse>("/_matrix/client/v3/account/whoami");
+
+
         return instance;
     }
 
@@ -55,12 +59,6 @@ public class AuthenticatedHomeserverGeneric(string serverName, string accessToke
     public string UserLocalpart => UserId.Split(":")[0][1..];
     public string ServerName => UserId.Split(":", 2)[1];
 
-    // public virtual async Task<WhoAmIResponse> WhoAmI() {
-    // if (_whoAmI is not null) return _whoAmI;
-    // _whoAmI = await _httpClient.GetFromJsonAsync<WhoAmIResponse>("/_matrix/client/v3/account/whoami");
-    // return _whoAmI;
-    // }
-
     public string AccessToken { get; set; } = accessToken;
 
     public GenericRoom GetRoom(string roomId) {
diff --git a/LibMatrix/Homeservers/RemoteHomeServer.cs b/LibMatrix/Homeservers/RemoteHomeServer.cs
index a47b731..a461d6e 100644
--- a/LibMatrix/Homeservers/RemoteHomeServer.cs
+++ b/LibMatrix/Homeservers/RemoteHomeServer.cs
@@ -37,9 +37,9 @@ public class RemoteHomeserver(string baseUrl) {
     public MatrixHttpClient ServerHttpClient { get; set; } = null!;
     public HomeserverResolverService.WellKnownUris WellKnownUris { get; set; } = null!;
 
-    public async Task<UserProfileResponse> GetProfileAsync(string mxid) {
+    public async Task<UserProfileResponse> GetProfileAsync(string mxid, bool useCache = false) {
         if (mxid is null) throw new ArgumentNullException(nameof(mxid));
-        if (_profileCache.TryGetValue(mxid, out var value)) {
+        if (useCache && _profileCache.TryGetValue(mxid, out var value)) {
             if (value is SemaphoreSlim s) await s.WaitAsync();
             if (value is UserProfileResponse p) return p;
         }
diff --git a/LibMatrix/Responses/SyncResponse.cs b/LibMatrix/Responses/SyncResponse.cs
index 42759ff..49259d0 100644
--- a/LibMatrix/Responses/SyncResponse.cs
+++ b/LibMatrix/Responses/SyncResponse.cs
@@ -2,6 +2,10 @@ using System.Text.Json.Serialization;
 
 namespace LibMatrix.Responses;
 
+[JsonSourceGenerationOptions(WriteIndented = true)]
+[JsonSerializable(typeof(SyncResponse))]
+internal partial class SyncResponseSerializerContext : JsonSerializerContext { }
+
 public class SyncResponse {
     [JsonPropertyName("next_batch")]
     public string NextBatch { get; set; } = null!;
@@ -114,4 +118,4 @@ public class SyncResponse {
             public EventList? InviteState { get; set; }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs
index 9e2cb67..bfb7f43 100644
--- a/LibMatrix/RoomTypes/GenericRoom.cs
+++ b/LibMatrix/RoomTypes/GenericRoom.cs
@@ -184,7 +184,7 @@ public class GenericRoom {
         else sw.Restart();
         foreach (var resp in result.Chunk) {
             if (resp?.Type != "m.room.member") continue;
-            if (joinedOnly && (resp.TypedContent as RoomMemberEventContent)?.Membership is not "join") continue;
+            if (joinedOnly && resp.RawContent?["membership"]?.GetValue<string>() != "join") continue;
             yield return resp;
         }
 
@@ -209,7 +209,7 @@ public class GenericRoom {
         var members = new List<StateEventResponse>();
         foreach (var resp in result.Chunk) {
             if (resp?.Type != "m.room.member") continue;
-            if (joinedOnly && (resp.TypedContent as RoomMemberEventContent)?.Membership is not "join") continue;
+            if (joinedOnly && resp.RawContent?["membership"]?.GetValue<string>() != "join") continue;
             members.Add(resp);
         }
 
@@ -267,7 +267,7 @@ public class GenericRoom {
                 var memberList = new List<string>();
                 int memberCount = 0;
                 await foreach (var member in members)
-                    memberList.Add((member.TypedContent is RoomMemberEventContent memberEvent ? memberEvent.DisplayName : "") ?? "");
+                    memberList.Add(member.RawContent?["displayname"]?.GetValue<string>() ?? "");
                 memberCount = memberList.Count;
                 memberList.RemoveAll(string.IsNullOrWhiteSpace);
                 memberList = memberList.OrderBy(x => x).ToList();
diff --git a/LibMatrix/Services/HomeserverProviderService.cs b/LibMatrix/Services/HomeserverProviderService.cs
index dc4acb1..577a706 100644
--- a/LibMatrix/Services/HomeserverProviderService.cs
+++ b/LibMatrix/Services/HomeserverProviderService.cs
@@ -25,22 +25,34 @@ public class HomeserverProviderService(ILogger<HomeserverProviderService> logger
             }
         }
 
-        // var domain = proxy ?? (await _homeserverResolverService.ResolveHomeserverFromWellKnown(homeserver)).client;
-
         var rhs = await RemoteHomeserver.Create(homeserver, proxy);
-        var clientVersions = await rhs.GetClientVersionsAsync();
+        ClientVersionsResponse clientVersions = new();
+        try {
+            clientVersions = await rhs.GetClientVersionsAsync();
+        }
+        catch (Exception e) {
+            logger.LogError(e, "Failed to get client versions for {homeserver}", homeserver);
+        }
+
         if (proxy is not null)
-            logger.LogInformation($"Homeserver {homeserver} proxied via {proxy}...");
-        logger.LogInformation($"{homeserver}: " + clientVersions.ToJson());
+            logger.LogInformation("Homeserver {homeserver} proxied via {proxy}...", homeserver, proxy);
+        logger.LogInformation("{homeserver}: {clientVersions}", homeserver, clientVersions.ToJson());
 
-        if (clientVersions.UnstableFeatures.TryGetValue("gay.rory.mxapiextensions.v0", out bool a) && a)
-            hs = await AuthenticatedHomeserverGeneric.Create<AuthenticatedHomeserverMxApiExtended>(homeserver, accessToken, proxy);
-        else {
-            var serverVersion = await rhs.GetServerVersionAsync();
-            if (serverVersion is { Server.Name: "Synapse" })
-                hs = await AuthenticatedHomeserverGeneric.Create<AuthenticatedHomeserverSynapse>(homeserver, accessToken, proxy);
-            else
-                hs = await AuthenticatedHomeserverGeneric.Create<AuthenticatedHomeserverGeneric>(homeserver, accessToken, proxy);
+        try {
+            if (clientVersions.UnstableFeatures.TryGetValue("gay.rory.mxapiextensions.v0", out bool a) && a)
+                hs = await AuthenticatedHomeserverGeneric.Create<AuthenticatedHomeserverMxApiExtended>(homeserver, accessToken, proxy);
+            else {
+                var serverVersion = await rhs.GetServerVersionAsync();
+                if (serverVersion is { Server.Name: "Synapse" })
+                    hs = await AuthenticatedHomeserverGeneric.Create<AuthenticatedHomeserverSynapse>(homeserver, accessToken, proxy);
+                else
+                    hs = await AuthenticatedHomeserverGeneric.Create<AuthenticatedHomeserverGeneric>(homeserver, accessToken, proxy);
+            }
+        }
+        catch (Exception e) {
+            logger.LogError(e, "Failed to create authenticated homeserver for {homeserver}", homeserver);
+            sem.Release();
+            throw;
         }
 
         if(impersonatedMxid is not null)
diff --git a/LibMatrix/Services/ServiceInstaller.cs b/LibMatrix/Services/ServiceInstaller.cs
index b1c98e1..ad5bedc 100644
--- a/LibMatrix/Services/ServiceInstaller.cs
+++ b/LibMatrix/Services/ServiceInstaller.cs
@@ -6,20 +6,20 @@ public static class ServiceInstaller {
 
     public static IServiceCollection AddRoryLibMatrixServices(this IServiceCollection services, RoryLibMatrixConfiguration? config = null) {
         //Check required services
-        if (!services.Any(x => x.ServiceType == typeof(TieredStorageService)))
-            throw new Exception("[MRUCore/DI] No TieredStorageService has been registered!");
+        // if (!services.Any(x => x.ServiceType == typeof(TieredStorageService)))
+            // throw new Exception("[MRUCore/DI] No TieredStorageService has been registered!");
         //Add config
         services.AddSingleton(config ?? new RoryLibMatrixConfiguration());
 
         //Add services
         services.AddSingleton<HomeserverResolverService>();
 
-        if (services.First(x => x.ServiceType == typeof(TieredStorageService)).Lifetime == ServiceLifetime.Singleton) {
+        // if (services.First(x => x.ServiceType == typeof(TieredStorageService)).Lifetime == ServiceLifetime.Singleton) {
             services.AddSingleton<HomeserverProviderService>();
-        }
-        else {
-            services.AddScoped<HomeserverProviderService>();
-        }
+        // }
+        // else {
+            // services.AddScoped<HomeserverProviderService>();
+        // }
 
         // services.AddScoped<MatrixHttpClient>();
         return services;
diff --git a/LibMatrix/StateEvent.cs b/LibMatrix/StateEvent.cs
index ad7605a..4a0adbd 100644
--- a/LibMatrix/StateEvent.cs
+++ b/LibMatrix/StateEvent.cs
@@ -26,8 +26,11 @@ public class StateEvent {
         }).ToFrozenDictionary();
 
     public static Type GetStateEventType(string type) => KnownStateEventTypesByName.GetValueOrDefault(type) ?? typeof(UnknownEventContent);
+    
+    [JsonIgnore]
+    public Type MappedType => GetStateEventType(Type);
 
-    private static readonly JsonSerializerOptions TypedContentSerializerOptions = new JsonSerializerOptions() {
+    private static readonly JsonSerializerOptions TypedContentSerializerOptions = new() {
         Converters = {
             new JsonFloatStringConverter(),
             new JsonDoubleStringConverter(),