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(),
|