about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTheArcaneBrony <myrainbowdash949@gmail.com>2023-12-23 08:54:11 +0100
committerTheArcaneBrony <myrainbowdash949@gmail.com>2023-12-23 08:54:11 +0100
commit14bcb748a853f7cd2afce40477bd2b0cb14ad7e6 (patch)
tree16dc78593288d715c93b5aee2903318c15a3e201
parentCleanup (diff)
downloadLibMatrix-14bcb748a853f7cd2afce40477bd2b0cb14ad7e6.tar.xz
User impersonation support (appservice identity assertion), non-AsyncEnumerable room member lookup
-rw-r--r--LibMatrix/Extensions/HttpClientExtensions.cs14
-rw-r--r--LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs5
-rw-r--r--LibMatrix/RoomTypes/GenericRoom.cs27
-rw-r--r--LibMatrix/RoomTypes/SpaceRoom.cs2
4 files changed, 42 insertions, 6 deletions
diff --git a/LibMatrix/Extensions/HttpClientExtensions.cs b/LibMatrix/Extensions/HttpClientExtensions.cs
index 93e1441..17cc31d 100644
--- a/LibMatrix/Extensions/HttpClientExtensions.cs
+++ b/LibMatrix/Extensions/HttpClientExtensions.cs
@@ -25,6 +25,7 @@ public static class HttpClientExtensions {
 }
 
 public class MatrixHttpClient : HttpClient {
+    public Dictionary<string, string> AdditionalQueryParameters { get; set; } = new();
     internal string? AssertedUserId { get; set; }
 
     private JsonSerializerOptions GetJsonSerializerOptions(JsonSerializerOptions? options = null) {
@@ -38,7 +39,11 @@ public class MatrixHttpClient : HttpClient {
 
     public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
         if (request.RequestUri is null) throw new NullReferenceException("RequestUri is null");
-        if (AssertedUserId is not null) request.RequestUri = request.RequestUri.AddQuery("user_id", AssertedUserId);
+        if (!request.RequestUri.IsAbsoluteUri) request.RequestUri = new Uri(BaseAddress, request.RequestUri);
+        // if (AssertedUserId is not null) request.RequestUri = request.RequestUri.AddQuery("user_id", AssertedUserId);
+        foreach (var (key, value) in AdditionalQueryParameters) {
+            request.RequestUri = request.RequestUri.AddQuery(key, value);
+        }
 
         Console.WriteLine($"Sending request to {request.RequestUri}");
 
@@ -86,6 +91,11 @@ public class MatrixHttpClient : HttpClient {
         return await SendAsync(request, cancellationToken);
     }
 
+    // GetAsync
+    public Task<HttpResponseMessage> GetAsync([StringSyntax("Uri")] string? requestUri, CancellationToken? cancellationToken = null) {
+        return SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri), cancellationToken ?? CancellationToken.None);
+    }
+
     // GetFromJsonAsync
     public async Task<T> GetFromJsonAsync<T>(string requestUri, JsonSerializerOptions? options = null, CancellationToken cancellationToken = default) {
         options = GetJsonSerializerOptions(options);
@@ -175,4 +185,4 @@ public class JsonDecimalStringConverter : JsonConverter<decimal> {
 
     public override void Write(Utf8JsonWriter writer, decimal value, JsonSerializerOptions options)
         => writer.WriteStringValue(value.ToString(CultureInfo.InvariantCulture));
-}
+}
\ No newline at end of file
diff --git a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
index cf85287..73cd641 100644
--- a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
+++ b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
@@ -307,4 +307,9 @@ public class AuthenticatedHomeserverGeneric(string serverName, string accessToke
     }
 
     #endregion
+    
+    public async Task SetImpersonate(string mxid) {
+        ClientHttpClient.AdditionalQueryParameters["user_id"] = mxid;
+        WhoAmI = await ClientHttpClient.GetFromJsonAsync<WhoAmIResponse>("/_matrix/client/v3/account/whoami");
+    }
 }
diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs
index 0cedf29..786dd01 100644
--- a/LibMatrix/RoomTypes/GenericRoom.cs
+++ b/LibMatrix/RoomTypes/GenericRoom.cs
@@ -168,7 +168,7 @@ public class GenericRoom {
         return await res.Content.ReadFromJsonAsync<RoomIdResponse>() ?? throw new Exception("Failed to join room?");
     }
 
-    public async IAsyncEnumerable<StateEventResponse> GetMembersAsync(bool joinedOnly = true) {
+    public async IAsyncEnumerable<StateEventResponse> GetMembersEnumerableAsync(bool joinedOnly = true) {
         var sw = Stopwatch.StartNew();
         var res = await Homeserver.ClientHttpClient.GetAsync($"/_matrix/client/v3/rooms/{RoomId}/members");
         Console.WriteLine($"Members call responded in {sw.GetElapsedAndRestart()}");
@@ -186,6 +186,27 @@ public class GenericRoom {
 
         Console.WriteLine($"Members call iterated in {sw.GetElapsedAndRestart()}");
     }
+    
+    public async Task<List<StateEventResponse>> GetMembersListAsync(bool joinedOnly = true) {
+        var sw = Stopwatch.StartNew();
+        var res = await Homeserver.ClientHttpClient.GetAsync($"/_matrix/client/v3/rooms/{RoomId}/members");
+        Console.WriteLine($"Members call responded in {sw.GetElapsedAndRestart()}");
+        // var resText = await res.Content.ReadAsStringAsync();
+        Console.WriteLine($"Members call response read in {sw.GetElapsedAndRestart()}");
+        var result = await JsonSerializer.DeserializeAsync<ChunkedStateEventResponse>(await res.Content.ReadAsStreamAsync(), new JsonSerializerOptions() {
+            TypeInfoResolver = ChunkedStateEventResponseSerializerContext.Default,
+        });
+        Console.WriteLine($"Members call deserialised in {sw.GetElapsedAndRestart()}");
+        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;
+            members.Add(resp);
+        }
+
+        Console.WriteLine($"Members call iterated in {sw.GetElapsedAndRestart()}");
+        return members;
+    }
 
 #region Utility shortcuts
 
@@ -232,7 +253,7 @@ public class GenericRoom {
         }
         catch {
             try {
-                var members = GetMembersAsync();
+                var members = GetMembersEnumerableAsync();
                 var memberList = new List<string>();
                 int memberCount = 0;
                 await foreach (var member in members)
@@ -373,7 +394,7 @@ public class GenericRoom {
             return await mxaeHomeserver.ClientHttpClient.GetFromJsonAsync<Dictionary<string, List<string>>>(
                 $"/_matrix/client/v3/rooms/{RoomId}/members_by_homeserver?joined_only={joinedOnly}");
         Dictionary<string, List<string>> roomHomeservers = new();
-        var members = GetMembersAsync();
+        var members = GetMembersEnumerableAsync();
         await foreach (var member in members) {
             string memberHs = member.StateKey.Split(':', 2)[1];
             roomHomeservers.TryAdd(memberHs, new());
diff --git a/LibMatrix/RoomTypes/SpaceRoom.cs b/LibMatrix/RoomTypes/SpaceRoom.cs
index 6ebd62f..bf16efb 100644
--- a/LibMatrix/RoomTypes/SpaceRoom.cs
+++ b/LibMatrix/RoomTypes/SpaceRoom.cs
@@ -15,7 +15,7 @@ public class SpaceRoom(AuthenticatedHomeserverGeneric homeserver, string roomId)
     }
 
     public async Task<EventIdResponse> AddChildAsync(GenericRoom room) {
-        var members = room.GetMembersAsync(true);
+        var members = room.GetMembersEnumerableAsync(true);
         Dictionary<string, int> memberCountByHs = new();
         await foreach (var member in members) {
             var server = member.StateKey.Split(':')[1];