about summary refs log tree commit diff
path: root/LibMatrix/RoomTypes/GenericRoom.cs
diff options
context:
space:
mode:
Diffstat (limited to 'LibMatrix/RoomTypes/GenericRoom.cs')
-rw-r--r--LibMatrix/RoomTypes/GenericRoom.cs88
1 files changed, 80 insertions, 8 deletions
diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs
index b81713a..d26b1f8 100644
--- a/LibMatrix/RoomTypes/GenericRoom.cs
+++ b/LibMatrix/RoomTypes/GenericRoom.cs
@@ -29,13 +29,16 @@ public class GenericRoom {
     public string RoomId { get; set; }
 
     public async IAsyncEnumerable<StateEventResponse?> GetFullStateAsync() {
-        var result = _httpClient.GetAsyncEnumerableFromJsonAsync<StateEventResponse>(
-            $"/_matrix/client/v3/rooms/{RoomId}/state");
+        var result = _httpClient.GetAsyncEnumerableFromJsonAsync<StateEventResponse>($"/_matrix/client/v3/rooms/{RoomId}/state");
         await foreach (var resp in result) {
             yield return resp;
         }
     }
 
+    public async Task<List<StateEventResponse>> GetFullStateAsListAsync() {
+        return await _httpClient.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";
         if (!string.IsNullOrEmpty(type)) url += $"/{type}";
@@ -77,17 +80,82 @@ public class GenericRoom {
         }
     }
 
-    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}";
+    public async Task<MessagesResponse> GetMessagesAsync(string from = "", int? limit = null, string dir = "b", string filter = "") {
+        var url = $"/_matrix/client/v3/rooms/{RoomId}/messages?dir={dir}";
+        if (!string.IsNullOrWhiteSpace(from)) url += $"&from={from}";
+        if (limit is not null) url += $"&limit={limit}";
+        if (!string.IsNullOrWhiteSpace(filter)) url += $"&filter={filter}";
         var res = await _httpClient.GetFromJsonAsync<MessagesResponse>(url);
         return res ?? new MessagesResponse();
     }
 
+    /// <summary>
+    /// Same as <see cref="GetMessagesAsync"/>, except keeps fetching more responses until the beginning of the room is found, or the target message limit is reached
+    /// </summary>
+    public async IAsyncEnumerable<MessagesResponse> GetManyMessagesAsync(string from = "", int limit = 100, string dir = "b", string filter = "", bool includeState = true,
+        bool fixForward = false) {
+        if (dir == "f" && fixForward) {
+            var concat = new List<MessagesResponse>();
+            while (true) {
+                var resp = await GetMessagesAsync(from, int.MaxValue, "b", filter);
+                concat.Add(resp);
+                if (!includeState)
+                    resp.State.Clear();
+                from = resp.End;
+                if (resp.End is null) break;
+            }
+
+            concat.Reverse();
+            foreach (var eventResponse in concat) {
+                limit -= eventResponse.State.Count + eventResponse.Chunk.Count;
+                while (limit < 0) {
+                    if (eventResponse.State.Count > 0 && eventResponse.State.Max(x => x.OriginServerTs) > eventResponse.Chunk.Max(x => x.OriginServerTs))
+                        eventResponse.State.Remove(eventResponse.State.MaxBy(x => x.OriginServerTs));
+                    else
+                        eventResponse.Chunk.Remove(eventResponse.Chunk.MaxBy(x => x.OriginServerTs));
+
+                    limit++;
+                }
+
+                eventResponse.Chunk.Reverse();
+                eventResponse.State.Reverse();
+                yield return eventResponse;
+                if (limit <= 0) yield break;
+            }
+        }
+        else {
+            while (limit > 0) {
+                var resp = await GetMessagesAsync(from, limit, dir, filter);
+
+                if (!includeState)
+                    resp.State.Clear();
+
+                limit -= resp.Chunk.Count + resp.State.Count;
+                from = resp.End;
+                yield return resp;
+                if (resp.End is null) {
+                    Console.WriteLine("End is null");
+                    yield break;
+                }
+            }
+        }
+
+        Console.WriteLine("End of GetManyAsync");
+    }
+
     public async Task<string?> GetNameAsync() => (await GetStateAsync<RoomNameEventContent>("m.room.name"))?.Name;
 
-    public async Task<RoomIdResponse> JoinAsync(string[]? homeservers = null, string? reason = null) {
+    public async Task<RoomIdResponse> JoinAsync(string[]? homeservers = null, string? reason = null, bool checkIfAlreadyMember = true) {
+        if (checkIfAlreadyMember) {
+            try {
+                var ce = await GetCreateEventAsync();
+                return new() {
+                    RoomId = RoomId
+                };
+            }
+            catch { } //ignore
+        }
+
         var join_url = $"/_matrix/client/v3/join/{HttpUtility.UrlEncode(RoomId)}";
         Console.WriteLine($"Calling {join_url} with {homeservers?.Length ?? 0} via's...");
         if (homeservers == null || homeservers.Length == 0) homeservers = new[] { RoomId.Split(':')[1] };
@@ -235,13 +303,17 @@ public class GenericRoom {
         return await res.Content.ReadFromJsonAsync<EventIdResponse>();
     }
 
-    public async Task<EventIdResponse?> SendFileAsync(string fileName, Stream fileStream, string messageType = "m.file") {
+    public async Task<EventIdResponse?> SendFileAsync(string fileName, Stream fileStream, string messageType = "m.file", string contentType = "application/octet-stream") {
         var url = await Homeserver.UploadFile(fileName, fileStream);
         var content = new RoomMessageEventContent() {
             MessageType = messageType,
             Url = url,
             Body = fileName,
             FileName = fileName,
+            FileInfo = new() {
+                Size = fileStream.Length,
+                MimeType = contentType
+            }
         };
         return await SendTimelineEventAsync("m.room.message", content);
     }