about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--LibMatrix.EventTypes/Spec/RoomMessageReactionEventContent.cs6
-rw-r--r--LibMatrix.EventTypes/Spec/State/RoomInfo/RoomEncryptionEventContent.cs1
-rw-r--r--LibMatrix.EventTypes/Spec/State/RoomInfo/RoomGuestAccessEventContent.cs3
-rw-r--r--LibMatrix.EventTypes/Spec/State/RoomInfo/RoomHistoryVisibilityEventContent.cs3
-rw-r--r--LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs9
-rw-r--r--LibMatrix.EventTypes/Spec/State/RoomInfo/RoomTopicEventContent.cs1
-rw-r--r--LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs2
-rw-r--r--LibMatrix/LibMatrix.csproj4
-rw-r--r--LibMatrix/Responses/ModAS/AdminRoomListingResult.cs62
-rw-r--r--LibMatrix/RoomTypes/GenericRoom.cs26
-rw-r--r--LibMatrix/Services/HomeserverProviderService.cs7
-rw-r--r--LibMatrix/StateEvent.cs64
12 files changed, 130 insertions, 58 deletions
diff --git a/LibMatrix.EventTypes/Spec/RoomMessageReactionEventContent.cs b/LibMatrix.EventTypes/Spec/RoomMessageReactionEventContent.cs
new file mode 100644
index 0000000..64b4f20
--- /dev/null
+++ b/LibMatrix.EventTypes/Spec/RoomMessageReactionEventContent.cs
@@ -0,0 +1,6 @@
+namespace LibMatrix.EventTypes.Spec;
+
+[MatrixEvent(EventName = EventId)]
+public class RoomMessageReactionEventContent : TimelineEventContent {
+    public const string EventId = "m.reaction";
+}
diff --git a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomEncryptionEventContent.cs b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomEncryptionEventContent.cs
index 992b57c..5ddd7f3 100644
--- a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomEncryptionEventContent.cs
+++ b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomEncryptionEventContent.cs
@@ -4,6 +4,7 @@ namespace LibMatrix.EventTypes.Spec.State;
 
 [MatrixEvent(EventName = "m.room.encryption")]
 public class RoomEncryptionEventContent : EventContent {
+    public const string EventId = "m.room.encryption";
     [JsonPropertyName("algorithm")]
     public string? Algorithm { get; set; }
     [JsonPropertyName("rotation_period_ms")]
diff --git a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomGuestAccessEventContent.cs b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomGuestAccessEventContent.cs
index 4f62eb1..5e6e4d2 100644
--- a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomGuestAccessEventContent.cs
+++ b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomGuestAccessEventContent.cs
@@ -4,8 +4,9 @@ namespace LibMatrix.EventTypes.Spec.State;
 
 [MatrixEvent(EventName = "m.room.guest_access")]
 public class RoomGuestAccessEventContent : EventContent {
+    public const string EventId = "m.room.guest_access";
     [JsonPropertyName("guest_access")]
-    public required string GuestAccess { get; set; }
+    public string GuestAccess { get; set; }
 
     [JsonIgnore]
     public bool IsGuestAccessEnabled {
diff --git a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomHistoryVisibilityEventContent.cs b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomHistoryVisibilityEventContent.cs
index 48ba538..c523e5e 100644
--- a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomHistoryVisibilityEventContent.cs
+++ b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomHistoryVisibilityEventContent.cs
@@ -4,6 +4,7 @@ namespace LibMatrix.EventTypes.Spec.State;
 
 [MatrixEvent(EventName = "m.room.history_visibility")]
 public class RoomHistoryVisibilityEventContent : EventContent {
+    public const string EventId = "m.room.history_visibility";
     [JsonPropertyName("history_visibility")]
-    public required string HistoryVisibility { get; set; }
+    public string HistoryVisibility { get; set; }
 }
diff --git a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs
index 0663288..981d927 100644
--- a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs
+++ b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs
@@ -4,9 +4,11 @@ namespace LibMatrix.EventTypes.Spec.State;
 
 [MatrixEvent(EventName = "m.room.join_rules")]
 public class RoomJoinRulesEventContent : EventContent {
+    public const string EventId = "m.room.join_rules";
     /// <summary>
     /// one of ["public", "invite", "knock", "restricted", "knock_restricted"]
     /// "private" is reserved without implementation!
+    /// unknown values are treated as "private"
     /// </summary>
     [JsonPropertyName("join_rule")]
     public string JoinRuleValue { get; set; }
@@ -19,7 +21,7 @@ public class RoomJoinRulesEventContent : EventContent {
             "knock" => JoinRules.Knock,
             "restricted" => JoinRules.Restricted,
             "knock_restricted" => JoinRules.KnockRestricted,
-            _ => throw new ArgumentOutOfRangeException()
+            _ => JoinRules.Private
         };
         set => JoinRuleValue = value switch {
             JoinRules.Public => "public",
@@ -27,7 +29,7 @@ public class RoomJoinRulesEventContent : EventContent {
             JoinRules.Knock => "knock",
             JoinRules.Restricted => "restricted",
             JoinRules.KnockRestricted => "knock_restricted",
-            _ => throw new ArgumentOutOfRangeException(nameof(value), value, null)
+            _ => "private"
         };
     }
 
@@ -47,6 +49,7 @@ public class RoomJoinRulesEventContent : EventContent {
         Invite,
         Knock,
         Restricted,
-        KnockRestricted
+        KnockRestricted,
+        Private // reserved without implementation!
     }
 }
diff --git a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomTopicEventContent.cs b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomTopicEventContent.cs
index 37536d2..8abb2c8 100644
--- a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomTopicEventContent.cs
+++ b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomTopicEventContent.cs
@@ -5,6 +5,7 @@ namespace LibMatrix.EventTypes.Spec.State;
 [MatrixEvent(EventName = "m.room.topic")]
 [MatrixEvent(EventName = "org.matrix.msc3765.topic", Legacy = true)]
 public class RoomTopicEventContent : EventContent {
+    public const string EventId = "m.room.topic";
     [JsonPropertyName("topic")]
     public string? Topic { get; set; }
 }
diff --git a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
index 0f2c1ea..c1d6461 100644
--- a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
+++ b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
@@ -74,8 +74,6 @@ public class AuthenticatedHomeserverGeneric(string serverName, string accessToke
         var roomsJson = await roomQuery.Content.ReadFromJsonAsync<JsonElement>();
         var rooms = roomsJson.GetProperty("joined_rooms").EnumerateArray().Select(room => GetRoom(room.GetString()!)).ToList();
 
-        Console.WriteLine($"Fetched {rooms.Count} rooms");
-
         return rooms;
     }
 
diff --git a/LibMatrix/LibMatrix.csproj b/LibMatrix/LibMatrix.csproj
index 07bd831..57d194d 100644
--- a/LibMatrix/LibMatrix.csproj
+++ b/LibMatrix/LibMatrix.csproj
@@ -25,10 +25,6 @@
         <PackageReference Condition="!Exists('..\ArcaneLibs\ArcaneLibs\ArcaneLibs.csproj')" Include="ArcaneLibs" Version="*-preview*"/>
         <ProjectReference Include="..\LibMatrix.EventTypes\LibMatrix.EventTypes.csproj" />
     </ItemGroup>
-
-    <ItemGroup>
-      <Folder Include="EventTypes\" />
-    </ItemGroup>
     
     <Target Name="ArcaneLibsNugetWarning" AfterTargets="AfterBuild">
         <Warning Text="ArcaneLibs is being referenced from NuGet, which is dangerous. Please read the warning in LibMatrix.csproj!" Condition="!Exists('..\ArcaneLibs\ArcaneLibs\ArcaneLibs.csproj')"/>
diff --git a/LibMatrix/Responses/ModAS/AdminRoomListingResult.cs b/LibMatrix/Responses/ModAS/AdminRoomListingResult.cs
new file mode 100644
index 0000000..95e3dcf
--- /dev/null
+++ b/LibMatrix/Responses/ModAS/AdminRoomListingResult.cs
@@ -0,0 +1,62 @@
+using System.Text.Json.Serialization;
+
+namespace LibMatrix.Responses.ModAS;
+
+public class ModASRoomQueryResult {
+    [JsonPropertyName("room_id")]
+    public required string RoomId { get; set; }
+
+    [JsonPropertyName("name")]
+    public string? Name { get; set; }
+
+    [JsonPropertyName("canonical_alias")]
+    public string? CanonicalAlias { get; set; }
+
+    [JsonPropertyName("joined_members")]
+    public int JoinedMembers { get; set; }
+
+    [JsonPropertyName("joined_local_members")]
+    public int JoinedLocalMembers { get; set; }
+
+    [JsonPropertyName("version")]
+    public string? Version { get; set; }
+
+    [JsonPropertyName("creator")]
+    public string? Creator { get; set; }
+
+    [JsonPropertyName("encryption")]
+    public string? Encryption { get; set; }
+
+    [JsonPropertyName("federatable")]
+    public bool Federatable { get; set; }
+
+    [JsonPropertyName("public")]
+    public bool Public { get; set; }
+
+    [JsonPropertyName("join_rules")]
+    public string? JoinRules { get; set; }
+
+    [JsonPropertyName("guest_access")]
+    public string? GuestAccess { get; set; }
+
+    [JsonPropertyName("history_visibility")]
+    public string? HistoryVisibility { get; set; }
+
+    [JsonPropertyName("state_events")]
+    public int StateEvents { get; set; }
+    
+    [JsonPropertyName("type")]
+    public string? Type { get; set; }
+
+    [JsonPropertyName("avatar_url")]
+    public string? AvatarUrl { get; set; }
+
+    [JsonPropertyName("topic")]
+    public string? RoomTopic { get; set; }
+
+    [JsonPropertyName("total_members")]
+    public int TotalMembers { get; set; }
+    
+    [JsonPropertyName("total_local_members")]
+    public int TotalLocalMembers { get; set; }
+}
\ No newline at end of file
diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs
index 551d780..9e2cb67 100644
--- a/LibMatrix/RoomTypes/GenericRoom.cs
+++ b/LibMatrix/RoomTypes/GenericRoom.cs
@@ -1,3 +1,4 @@
+using System.Collections.Frozen;
 using System.Diagnostics;
 using System.Net.Http.Json;
 using System.Text.Json;
@@ -36,9 +37,8 @@ public class GenericRoom {
         }
     }
 
-    public Task<List<StateEventResponse>> GetFullStateAsListAsync() {
-        return Homeserver.ClientHttpClient.GetFromJsonAsync<List<StateEventResponse>>($"/_matrix/client/v3/rooms/{RoomId}/state");
-    }
+    public Task<List<StateEventResponse>> GetFullStateAsListAsync() =>
+        Homeserver.ClientHttpClient.GetFromJsonAsync<List<StateEventResponse>>($"/_matrix/client/v3/rooms/{RoomId}/state");
 
     public async Task<T?> GetStateAsync<T>(string type, string stateKey = "") {
         var url = $"/_matrix/client/v3/rooms/{RoomId}/state";
@@ -171,7 +171,7 @@ public class GenericRoom {
     public async IAsyncEnumerable<StateEventResponse> GetMembersEnumerableAsync(bool joinedOnly = true) {
         var sw = Stopwatch.StartNew();
         var res = await Homeserver.ClientHttpClient.GetAsync($"/_matrix/client/v3/rooms/{RoomId}/members");
-        if(sw.ElapsedMilliseconds > 1000)
+        if (sw.ElapsedMilliseconds > 1000)
             Console.WriteLine($"Members call responded in {sw.GetElapsedAndRestart()}");
         else sw.Restart();
         // var resText = await res.Content.ReadAsStringAsync();
@@ -179,7 +179,7 @@ public class GenericRoom {
         var result = await JsonSerializer.DeserializeAsync<ChunkedStateEventResponse>(await res.Content.ReadAsStreamAsync(), new JsonSerializerOptions() {
             TypeInfoResolver = ChunkedStateEventResponseSerializerContext.Default,
         });
-        if(sw.ElapsedMilliseconds > 100)
+        if (sw.ElapsedMilliseconds > 100)
             Console.WriteLine($"Members call deserialised in {sw.GetElapsedAndRestart()}");
         else sw.Restart();
         foreach (var resp in result.Chunk) {
@@ -188,14 +188,14 @@ public class GenericRoom {
             yield return resp;
         }
 
-        if(sw.ElapsedMilliseconds > 100)
+        if (sw.ElapsedMilliseconds > 100)
             Console.WriteLine($"Members call iterated in {sw.GetElapsedAndRestart()}");
     }
-    
-    public async Task<List<StateEventResponse>> GetMembersListAsync(bool joinedOnly = true) {
+
+    public async Task<FrozenSet<StateEventResponse>> GetMembersListAsync(bool joinedOnly = true) {
         var sw = Stopwatch.StartNew();
         var res = await Homeserver.ClientHttpClient.GetAsync($"/_matrix/client/v3/rooms/{RoomId}/members");
-        if(sw.ElapsedMilliseconds > 1000)
+        if (sw.ElapsedMilliseconds > 1000)
             Console.WriteLine($"Members call responded in {sw.GetElapsedAndRestart()}");
         else sw.Restart();
         // var resText = await res.Content.ReadAsStringAsync();
@@ -203,7 +203,7 @@ public class GenericRoom {
         var result = await JsonSerializer.DeserializeAsync<ChunkedStateEventResponse>(await res.Content.ReadAsStreamAsync(), new JsonSerializerOptions() {
             TypeInfoResolver = ChunkedStateEventResponseSerializerContext.Default,
         });
-        if(sw.ElapsedMilliseconds > 100)
+        if (sw.ElapsedMilliseconds > 100)
             Console.WriteLine($"Members call deserialised in {sw.GetElapsedAndRestart()}");
         else sw.Restart();
         var members = new List<StateEventResponse>();
@@ -213,9 +213,9 @@ public class GenericRoom {
             members.Add(resp);
         }
 
-        if(sw.ElapsedMilliseconds > 100)
+        if (sw.ElapsedMilliseconds > 100)
             Console.WriteLine($"Members call iterated in {sw.GetElapsedAndRestart()}");
-        return members;
+        return members.ToFrozenSet();
     }
 
 #region Utility shortcuts
@@ -298,7 +298,7 @@ public class GenericRoom {
             catch (Exception e) {
                 Console.WriteLine(e);
             }
-    
+
         return Homeserver.ResolveMediaUri(avatar.Url);
     }
 
diff --git a/LibMatrix/Services/HomeserverProviderService.cs b/LibMatrix/Services/HomeserverProviderService.cs
index 983f469..dc4acb1 100644
--- a/LibMatrix/Services/HomeserverProviderService.cs
+++ b/LibMatrix/Services/HomeserverProviderService.cs
@@ -13,8 +13,8 @@ public class HomeserverProviderService(ILogger<HomeserverProviderService> logger
     private static readonly Dictionary<string, SemaphoreSlim> RemoteHomeserverSemaphore = new();
     private static readonly Dictionary<string, RemoteHomeserver> RemoteHomeserverCache = new();
 
-    public async Task<AuthenticatedHomeserverGeneric> GetAuthenticatedWithToken(string homeserver, string accessToken, string? proxy = null) {
-        var cacheKey = homeserver + accessToken + proxy;
+    public async Task<AuthenticatedHomeserverGeneric> GetAuthenticatedWithToken(string homeserver, string accessToken, string? proxy = null, string? impersonatedMxid = null) {
+        var cacheKey = homeserver + accessToken + proxy + impersonatedMxid;
         var sem = AuthenticatedHomeserverSemaphore.GetOrCreate(cacheKey, _ => new SemaphoreSlim(1, 1));
         await sem.WaitAsync();
         AuthenticatedHomeserverGeneric? hs;
@@ -43,6 +43,9 @@ public class HomeserverProviderService(ILogger<HomeserverProviderService> logger
                 hs = await AuthenticatedHomeserverGeneric.Create<AuthenticatedHomeserverGeneric>(homeserver, accessToken, proxy);
         }
 
+        if(impersonatedMxid is not null)
+            await hs.SetImpersonate(impersonatedMxid);
+        
         lock (AuthenticatedHomeserverCache)
             AuthenticatedHomeserverCache[cacheKey] = hs;
         sem.Release();
diff --git a/LibMatrix/StateEvent.cs b/LibMatrix/StateEvent.cs
index cfc7011..ad7605a 100644
--- a/LibMatrix/StateEvent.cs
+++ b/LibMatrix/StateEvent.cs
@@ -43,7 +43,7 @@ public class StateEvent {
                 // return null;
             // }
             try {
-                return (EventContent)RawContent.Deserialize(GetType, TypedContentSerializerOptions)!;
+                return (EventContent)RawContent.Deserialize(GetStateEventType(Type), TypedContentSerializerOptions)!;
             }
             catch (JsonException e) {
                 Console.WriteLine(e);
@@ -76,37 +76,37 @@ public class StateEvent {
         get => _rawContent;
         set => _rawContent = value;
     }
-
-    [JsonIgnore]
-    public new Type GetType {
-        get {
-            var type = GetStateEventType(Type);
-
-            //special handling for some types
-            // if (type == typeof(RoomEmotesEventContent)) {
-            //     RawContent["emote"] = RawContent["emote"]?.AsObject() ?? new JsonObject();
-            // }
-            //
-            // if (this is StateEventResponse stateEventResponse) {
-            //     if (type == null || type == typeof(object)) {
-            //         Console.WriteLine($"Warning: unknown event type '{Type}'!");
-            //         Console.WriteLine(RawContent.ToJson());
-            //         Directory.CreateDirectory($"unknown_state_events/{Type}");
-            //         File.WriteAllText($"unknown_state_events/{Type}/{stateEventResponse.EventId}.json",
-            //             RawContent.ToJson());
-            //         Console.WriteLine($"Saved to unknown_state_events/{Type}/{stateEventResponse.EventId}.json");
-            //     }
-            //     else if (RawContent is not null && RawContent.FindExtraJsonObjectFields(type)) {
-            //         Directory.CreateDirectory($"unknown_state_events/{Type}");
-            //         File.WriteAllText($"unknown_state_events/{Type}/{stateEventResponse.EventId}.json",
-            //             RawContent.ToJson());
-            //         Console.WriteLine($"Saved to unknown_state_events/{Type}/{stateEventResponse.EventId}.json");
-            //     }
-            // }
-
-            return type;
-        }
-    }
+    //
+    // [JsonIgnore]
+    // public new Type GetType {
+    //     get {
+    //         var type = GetStateEventType(Type);
+    //
+    //         //special handling for some types
+    //         // if (type == typeof(RoomEmotesEventContent)) {
+    //         //     RawContent["emote"] = RawContent["emote"]?.AsObject() ?? new JsonObject();
+    //         // }
+    //         //
+    //         // if (this is StateEventResponse stateEventResponse) {
+    //         //     if (type == null || type == typeof(object)) {
+    //         //         Console.WriteLine($"Warning: unknown event type '{Type}'!");
+    //         //         Console.WriteLine(RawContent.ToJson());
+    //         //         Directory.CreateDirectory($"unknown_state_events/{Type}");
+    //         //         File.WriteAllText($"unknown_state_events/{Type}/{stateEventResponse.EventId}.json",
+    //         //             RawContent.ToJson());
+    //         //         Console.WriteLine($"Saved to unknown_state_events/{Type}/{stateEventResponse.EventId}.json");
+    //         //     }
+    //         //     else if (RawContent is not null && RawContent.FindExtraJsonObjectFields(type)) {
+    //         //         Directory.CreateDirectory($"unknown_state_events/{Type}");
+    //         //         File.WriteAllText($"unknown_state_events/{Type}/{stateEventResponse.EventId}.json",
+    //         //             RawContent.ToJson());
+    //         //         Console.WriteLine($"Saved to unknown_state_events/{Type}/{stateEventResponse.EventId}.json");
+    //         //     }
+    //         // }
+    //
+    //         return type;
+    //     }
+    // }
 
     //debug
     [JsonIgnore]