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]
|