about summary refs log tree commit diff
path: root/MatrixRoomUtils.Core/RoomTypes
diff options
context:
space:
mode:
Diffstat (limited to 'MatrixRoomUtils.Core/RoomTypes')
-rw-r--r--MatrixRoomUtils.Core/RoomTypes/GenericRoom.cs226
-rw-r--r--MatrixRoomUtils.Core/RoomTypes/SpaceRoom.cs14
2 files changed, 77 insertions, 163 deletions
diff --git a/MatrixRoomUtils.Core/RoomTypes/GenericRoom.cs b/MatrixRoomUtils.Core/RoomTypes/GenericRoom.cs
index 8dc30d1..f57c855 100644
--- a/MatrixRoomUtils.Core/RoomTypes/GenericRoom.cs
+++ b/MatrixRoomUtils.Core/RoomTypes/GenericRoom.cs
@@ -1,15 +1,17 @@
 using System.Net.Http.Json;
-using System.Text;
 using System.Text.Json;
 using System.Web;
 using MatrixRoomUtils.Core.Extensions;
+using MatrixRoomUtils.Core.Responses;
 using MatrixRoomUtils.Core.RoomTypes;
+using MatrixRoomUtils.Core.StateEventTypes;
+using Microsoft.Extensions.Logging;
 
 namespace MatrixRoomUtils.Core;
 
 public class GenericRoom {
     internal readonly AuthenticatedHomeServer _homeServer;
-    internal readonly HttpClient _httpClient;
+    internal readonly MatrixHttpClient _httpClient;
 
     public GenericRoom(AuthenticatedHomeServer homeServer, string roomId) {
         _homeServer = homeServer;
@@ -21,51 +23,41 @@ public class GenericRoom {
 
     public string RoomId { get; set; }
 
-    public async Task<JsonElement?> GetStateAsync(string type, string stateKey = "", bool logOnFailure = true) {
+    [Obsolete("", true)]
+    public async Task<JsonElement?> GetStateAsync(string type, string stateKey = "") {
         var url = $"/_matrix/client/v3/rooms/{RoomId}/state";
         if (!string.IsNullOrEmpty(type)) url += $"/{type}";
         if (!string.IsNullOrEmpty(stateKey)) url += $"/{stateKey}";
+        return await _httpClient.GetFromJsonAsync<JsonElement>(url);
+    }
 
-        var res = await _httpClient.GetAsync(url);
-        if (!res.IsSuccessStatusCode) {
-            if (logOnFailure) Console.WriteLine($"{RoomId}/{stateKey}/{type} - got status: {res.StatusCode}");
-            return null;
+    public async IAsyncEnumerable<StateEventResponse?> GetFullStateAsync() {
+        var res = await _httpClient.GetAsync($"/_matrix/client/v3/rooms/{RoomId}/state");
+        var result =
+            JsonSerializer.DeserializeAsyncEnumerable<StateEventResponse>(await res.Content.ReadAsStreamAsync());
+        await foreach (var resp in result) {
+            yield return resp;
         }
-
-        var result = await res.Content.ReadFromJsonAsync<JsonElement>();
-        return result;
     }
 
-    public async Task<T?> GetStateAsync<T>(string type, string stateKey = "", bool logOnFailure = false) {
-        var res = await GetStateAsync(type, stateKey, logOnFailure);
-        if (res == null) return default;
-        return res.Value.Deserialize<T>();
+    public async Task<T?> GetStateAsync<T>(string type, string stateKey = "") {
+        var url = $"/_matrix/client/v3/rooms/{RoomId}/state";
+        if (!string.IsNullOrEmpty(type)) url += $"/{type}";
+        if (!string.IsNullOrEmpty(stateKey)) url += $"/{stateKey}";
+        return await _httpClient.GetFromJsonAsync<T>(url);
     }
 
     public async Task<MessagesResponse> GetMessagesAsync(string from = "", int limit = 10, string dir = "b",
         string filter = "") {
         var url = $"/_matrix/client/v3/rooms/{RoomId}/messages?from={from}&limit={limit}&dir={dir}";
         if (!string.IsNullOrEmpty(filter)) url += $"&filter={filter}";
-        var res = await _httpClient.GetAsync(url);
-        if (!res.IsSuccessStatusCode) {
-            Console.WriteLine($"Failed to get messages for {RoomId} - got status: {res.StatusCode}");
-            throw new Exception($"Failed to get messages for {RoomId} - got status: {res.StatusCode}");
-        }
-
-        var result = await res.Content.ReadFromJsonAsync<MessagesResponse>();
-        return result ?? new MessagesResponse();
+        var res = await _httpClient.GetFromJsonAsync<MessagesResponse>(url);
+        return res ?? new MessagesResponse();
     }
 
     public async Task<string> GetNameAsync() {
-        var res = await GetStateAsync("m.room.name");
-        if (!res.HasValue) {
-            Console.WriteLine($"Room {RoomId} has no name!");
-            return RoomId;
-        }
-
-        var resn = res?.TryGetProperty("name", out var name) ?? false ? name.GetString() ?? RoomId : RoomId;
-        //Console.WriteLine($"Got name: {resn}");
-        return resn;
+        var res = await GetStateAsync<RoomNameEventData>("m.room.name");
+        return res.Name ?? RoomId;
     }
 
     public async Task JoinAsync(string[]? homeservers = null, string? reason = null) {
@@ -78,165 +70,89 @@ public class GenericRoom {
         });
     }
 
-    public async Task<List<string>> GetMembersAsync(bool joinedOnly = true) {
-        var res = await GetStateAsync("");
-        if (!res.HasValue) return new List<string>();
-        var members = new List<string>();
-        foreach (var member in res.Value.EnumerateArray()) {
-            if (member.GetProperty("type").GetString() != "m.room.member") continue;
-            if (joinedOnly && member.GetProperty("content").GetProperty("membership").GetString() != "join") continue;
-            var memberId = member.GetProperty("state_key").GetString();
-            members.Add(
-                memberId ?? throw new InvalidOperationException("Event type was member but state key was null!"));
+    public async IAsyncEnumerable<StateEventResponse> GetMembersAsync(bool joinedOnly = true) {
+        var res = GetFullStateAsync();
+        await foreach (var member in res) {
+            if (member.Type != "m.room.member") continue;
+            if (joinedOnly && (member.TypedContent as RoomMemberEventData).Membership is not "join") continue;
+            yield return member;
         }
-
-        return members;
     }
 
     public async Task<List<string>> GetAliasesAsync() {
-        var res = await GetStateAsync("m.room.aliases");
-        if (!res.HasValue) return new List<string>();
-        var aliases = new List<string>();
-        foreach (var alias in res.Value.GetProperty("aliases").EnumerateArray()) aliases.Add(alias.GetString() ?? "");
-
-        return aliases;
+        var res = await GetStateAsync<RoomAliasEventData>("m.room.aliases");
+        return res.Aliases;
     }
 
-    public async Task<string> GetCanonicalAliasAsync() {
-        var res = await GetStateAsync("m.room.canonical_alias");
-        if (!res.HasValue) return "";
-        return res.Value.GetProperty("alias").GetString() ?? "";
-    }
-
-    public async Task<string> GetTopicAsync() {
-        var res = await GetStateAsync("m.room.topic");
-        if (!res.HasValue) return "";
-        return res.Value.GetProperty("topic").GetString() ?? "";
-    }
-
-    public async Task<string> GetAvatarUrlAsync() {
-        var res = await GetStateAsync("m.room.avatar");
-        if (!res.HasValue) return "";
-        return res.Value.GetProperty("url").GetString() ?? "";
-    }
+    public async Task<CanonicalAliasEventData?> GetCanonicalAliasAsync() =>
+        await GetStateAsync<CanonicalAliasEventData>("m.room.canonical_alias");
 
-    public async Task<JoinRulesEventData> GetJoinRuleAsync() {
-        var res = await GetStateAsync("m.room.join_rules");
-        if (!res.HasValue) return new JoinRulesEventData();
-        return res.Value.Deserialize<JoinRulesEventData>() ?? new JoinRulesEventData();
-    }
+    public async Task<RoomTopicEventData?> GetTopicAsync() =>
+        await GetStateAsync<RoomTopicEventData>("m.room.topic");
 
-    public async Task<string> GetHistoryVisibilityAsync() {
-        var res = await GetStateAsync("m.room.history_visibility");
-        if (!res.HasValue) return "";
-        return res.Value.GetProperty("history_visibility").GetString() ?? "";
-    }
+    public async Task<RoomAvatarEventData?> GetAvatarUrlAsync() =>
+        await GetStateAsync<RoomAvatarEventData>("m.room.avatar");
 
-    public async Task<string> GetGuestAccessAsync() {
-        var res = await GetStateAsync("m.room.guest_access");
-        if (!res.HasValue) return "";
-        return res.Value.GetProperty("guest_access").GetString() ?? "";
-    }
+    public async Task<JoinRulesEventData> GetJoinRuleAsync() =>
+        await GetStateAsync<JoinRulesEventData>("m.room.join_rules");
 
-    public async Task<CreateEvent> GetCreateEventAsync() {
-        var res = await GetStateAsync("m.room.create");
-        if (!res.HasValue) return new CreateEvent();
+    public async Task<HistoryVisibilityData?> GetHistoryVisibilityAsync() =>
+        await GetStateAsync<HistoryVisibilityData>("m.room.history_visibility");
 
-        res.FindExtraJsonElementFields(typeof(CreateEvent));
+    public async Task<GuestAccessData?> GetGuestAccessAsync() =>
+        await GetStateAsync<GuestAccessData>("m.room.guest_access");
 
-        return res.Value.Deserialize<CreateEvent>() ?? new CreateEvent();
-    }
+    public async Task<CreateEvent> GetCreateEventAsync() =>
+        await GetStateAsync<CreateEvent>("m.room.create");
 
     public async Task<string?> GetRoomType() {
-        var res = await GetStateAsync("m.room.create");
-        if (!res.HasValue) return null;
-        if (res.Value.TryGetProperty("type", out var type)) return type.GetString();
-        return null;
+        var res = await GetStateAsync<RoomCreateEventData>("m.room.create");
+        return res.Type;
     }
 
-    public async Task ForgetAsync() {
-        var res = await _httpClient.PostAsync($"/_matrix/client/v3/rooms/{RoomId}/forget", null);
-        if (!res.IsSuccessStatusCode) {
-            Console.WriteLine($"Failed to forget room {RoomId} - got status: {res.StatusCode}");
-            throw new Exception($"Failed to forget room {RoomId} - got status: {res.StatusCode}");
-        }
-    }
+    public async Task ForgetAsync() =>
+        await _httpClient.PostAsync($"/_matrix/client/v3/rooms/{RoomId}/forget", null);
 
-    public async Task LeaveAsync(string? reason = null) {
-        var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/leave", new {
+    public async Task LeaveAsync(string? reason = null) =>
+        await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/leave", new {
             reason
         });
-        if (!res.IsSuccessStatusCode) {
-            Console.WriteLine($"Failed to leave room {RoomId} - got status: {res.StatusCode}");
-            throw new Exception($"Failed to leave room {RoomId} - got status: {res.StatusCode}");
-        }
-    }
 
-    public async Task KickAsync(string userId, string? reason = null) {
-        var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/kick",
+    public async Task KickAsync(string userId, string? reason = null) =>
+        await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/kick",
             new UserIdAndReason() { UserId = userId, Reason = reason });
-        if (!res.IsSuccessStatusCode) {
-            Console.WriteLine($"Failed to kick {userId} from room {RoomId} - got status: {res.StatusCode}");
-            throw new Exception($"Failed to kick {userId} from room {RoomId} - got status: {res.StatusCode}");
-        }
-    }
 
-    public async Task BanAsync(string userId, string? reason = null) {
-        var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/ban",
+    public async Task BanAsync(string userId, string? reason = null) =>
+        await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/ban",
             new UserIdAndReason() { UserId = userId, Reason = reason });
-        if (!res.IsSuccessStatusCode) {
-            Console.WriteLine($"Failed to ban {userId} from room {RoomId} - got status: {res.StatusCode}");
-            throw new Exception($"Failed to ban {userId} from room {RoomId} - got status: {res.StatusCode}");
-        }
-    }
 
-    public async Task UnbanAsync(string userId) {
-        var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/unban",
+    public async Task UnbanAsync(string userId) =>
+        await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/unban",
             new UserIdAndReason() { UserId = userId });
-        if (!res.IsSuccessStatusCode) {
-            Console.WriteLine($"Failed to unban {userId} from room {RoomId} - got status: {res.StatusCode}");
-            throw new Exception($"Failed to unban {userId} from room {RoomId} - got status: {res.StatusCode}");
-        }
-    }
-
-    public async Task<EventIdResponse> SendStateEventAsync(string eventType, object content) {
-        var res = await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/state/{eventType}", content);
-        if (!res.IsSuccessStatusCode) {
-            Console.WriteLine(
-                $"Failed to send state event {eventType} to room {RoomId} - got status: {res.StatusCode}");
-            throw new Exception(
-                $"Failed to send state event {eventType} to room {RoomId} - got status: {res.StatusCode}");
-        }
 
-        return await res.Content.ReadFromJsonAsync<EventIdResponse>();
-    }
+    public async Task<EventIdResponse> SendStateEventAsync(string eventType, object content) =>
+        await (await _httpClient.PostAsJsonAsync($"/_matrix/client/v3/rooms/{RoomId}/state/{eventType}", content))
+            .Content.ReadFromJsonAsync<EventIdResponse>();
 
     public async Task<EventIdResponse> SendMessageEventAsync(string eventType, MessageEventData content) {
-        var url = $"/_matrix/client/v3/rooms/{RoomId}/send/{eventType}/" + Guid.NewGuid();
-        var res = await _httpClient.PutAsJsonAsync(url, content);
-        if (!res.IsSuccessStatusCode) {
-            Console.WriteLine($"Failed to send event {eventType} to room {RoomId} - got status: {res.StatusCode}");
-            throw new Exception($"Failed to send event {eventType} to room {RoomId} - got status: {res.StatusCode}");
-        }
-
+        var res = await _httpClient.PutAsJsonAsync(
+            $"/_matrix/client/v3/rooms/{RoomId}/send/{eventType}/" + Guid.NewGuid(), content);
         var resu = await res.Content.ReadFromJsonAsync<EventIdResponse>();
-
         return resu;
     }
 
     public async Task<EventIdResponse> SendFileAsync(string eventType, string fileName, Stream fileStream) {
-        var url = $"/_matrix/client/v3/rooms/{RoomId}/send/{eventType}/" + Guid.NewGuid();
         var content = new MultipartFormDataContent();
         content.Add(new StreamContent(fileStream), "file", fileName);
-        var res = await _httpClient.PutAsync(url, content);
-        if (!res.IsSuccessStatusCode) {
-            Console.WriteLine($"Failed to send event {eventType} to room {RoomId} - got status: {res.StatusCode}");
-            throw new Exception($"Failed to send event {eventType} to room {RoomId} - got status: {res.StatusCode}");
-        }
-
-        var resu = await res.Content.ReadFromJsonAsync<EventIdResponse>();
-
-        return resu;
+        var res = await
+            (
+                await _httpClient.PutAsync(
+                    $"/_matrix/client/v3/rooms/{RoomId}/send/{eventType}/" + Guid.NewGuid(),
+                    content
+                )
+            )
+            .Content.ReadFromJsonAsync<EventIdResponse>();
+        return res;
     }
 
     public readonly SpaceRoom AsSpace;
diff --git a/MatrixRoomUtils.Core/RoomTypes/SpaceRoom.cs b/MatrixRoomUtils.Core/RoomTypes/SpaceRoom.cs
index 6b586c7..3be3130 100644
--- a/MatrixRoomUtils.Core/RoomTypes/SpaceRoom.cs
+++ b/MatrixRoomUtils.Core/RoomTypes/SpaceRoom.cs
@@ -8,20 +8,18 @@ namespace MatrixRoomUtils.Core.RoomTypes;
 public class SpaceRoom : GenericRoom {
     private readonly AuthenticatedHomeServer _homeServer;
     private readonly GenericRoom _room;
+
     public SpaceRoom(AuthenticatedHomeServer homeServer, string roomId) : base(homeServer, roomId) {
         _homeServer = homeServer;
     }
 
     public async Task<List<GenericRoom>> GetRoomsAsync(bool includeRemoved = false) {
         var rooms = new List<GenericRoom>();
-        var state = await GetStateAsync("");
-        if (state != null) {
-            var states = state.Value.Deserialize<StateEventResponse[]>()!;
-            foreach (var stateEvent in states.Where(x => x.Type == "m.space.child")) {
-                var roomId = stateEvent.StateKey;
-                if(stateEvent.TypedContent.ToJson() != "{}" || includeRemoved)
-                    rooms.Add(await _homeServer.GetRoom(roomId));
-            }
+        var state = GetFullStateAsync().ToBlockingEnumerable().ToList();
+        var childStates = state.Where(x => x.Type == "m.space.child");
+        foreach (var stateEvent in childStates) {
+            if (stateEvent.TypedContent.ToJson() != "{}" || includeRemoved)
+                rooms.Add(await _homeServer.GetRoom(stateEvent.StateKey));
         }
 
         return rooms;