about summary refs log tree commit diff
path: root/LibMatrix
diff options
context:
space:
mode:
Diffstat (limited to 'LibMatrix')
-rw-r--r--LibMatrix/Helpers/SyncHelper.cs3
-rw-r--r--LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs21
-rw-r--r--LibMatrix/Responses/CreateRoomRequest.cs50
-rw-r--r--LibMatrix/RoomTypes/GenericRoom.cs22
-rw-r--r--LibMatrix/StateEventTypes/Spec/JoinRulesEventData.cs4
-rw-r--r--LibMatrix/StateEventTypes/Spec/RoomMessageEventData.cs20
6 files changed, 109 insertions, 11 deletions
diff --git a/LibMatrix/Helpers/SyncHelper.cs b/LibMatrix/Helpers/SyncHelper.cs
index de4f3d4..83b1685 100644
--- a/LibMatrix/Helpers/SyncHelper.cs
+++ b/LibMatrix/Helpers/SyncHelper.cs
@@ -113,6 +113,7 @@ public class SyncHelper {
 
             if (sync.Rooms is { Join.Count: > 0 }) {
                 foreach (var updatedRoom in sync.Rooms.Join) {
+                    if(updatedRoom.Value.Timeline is null) continue;
                     foreach (var stateEventResponse in updatedRoom.Value.Timeline.Events) {
                         stateEventResponse.RoomId = updatedRoom.Key;
                         var tasks = TimelineEventHandlers.Select(x => x(stateEventResponse)).ToList();
@@ -178,7 +179,7 @@ public class SyncResult {
 
         public class JoinedRoomDataStructure {
             [JsonPropertyName("timeline")]
-            public TimelineDataStructure Timeline { get; set; }
+            public TimelineDataStructure? Timeline { get; set; }
 
             [JsonPropertyName("state")]
             public EventList State { get; set; }
diff --git a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
index ecac4e4..bb34112 100644
--- a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
+++ b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
@@ -6,6 +6,7 @@ using System.Net.Http;
 using System.Net.Http.Json;
 using System.Text.Json;
 using System.Text.Json.Nodes;
+using System.Text.Json.Serialization;
 using System.Threading.Tasks;
 using LibMatrix.Extensions;
 using LibMatrix.Helpers;
@@ -56,7 +57,10 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeServer {
     }
 
     public async Task<GenericRoom> CreateRoom(CreateRoomRequest creationEvent) {
-        var res = await _httpClient.PostAsJsonAsync("/_matrix/client/v3/createRoom", creationEvent);
+        creationEvent.CreationContent["creator"] = UserId;
+        var res = await _httpClient.PostAsJsonAsync("/_matrix/client/v3/createRoom", creationEvent, new JsonSerializerOptions {
+            DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
+        });
         if (!res.IsSuccessStatusCode) {
             Console.WriteLine($"Failed to create room: {await res.Content.ReadAsStringAsync()}");
             throw new InvalidDataException($"Failed to create room: {await res.Content.ReadAsStringAsync()}");
@@ -68,13 +72,14 @@ public class AuthenticatedHomeserverGeneric : RemoteHomeServer {
 #region Account Data
 
     public async Task<T> GetAccountData<T>(string key) {
-        var res = await _httpClient.GetAsync($"/_matrix/client/v3/user/{UserId}/account_data/{key}");
-        if (!res.IsSuccessStatusCode) {
-            Console.WriteLine($"Failed to get account data: {await res.Content.ReadAsStringAsync()}");
-            throw new InvalidDataException($"Failed to get account data: {await res.Content.ReadAsStringAsync()}");
-        }
-
-        return await res.Content.ReadFromJsonAsync<T>();
+        // var res = await _httpClient.GetAsync($"/_matrix/client/v3/user/{UserId}/account_data/{key}");
+        // if (!res.IsSuccessStatusCode) {
+        //     Console.WriteLine($"Failed to get account data: {await res.Content.ReadAsStringAsync()}");
+        //     throw new InvalidDataException($"Failed to get account data: {await res.Content.ReadAsStringAsync()}");
+        // }
+        //
+        // return await res.Content.ReadFromJsonAsync<T>();
+        return await _httpClient.GetFromJsonAsync<T>($"/_matrix/client/v3/user/{UserId}/account_data/{key}");
     }
 
     public async Task SetAccountData(string key, object data) {
diff --git a/LibMatrix/Responses/CreateRoomRequest.cs b/LibMatrix/Responses/CreateRoomRequest.cs
index c1c1697..2c05088 100644
--- a/LibMatrix/Responses/CreateRoomRequest.cs
+++ b/LibMatrix/Responses/CreateRoomRequest.cs
@@ -7,6 +7,7 @@ using System.Text.Json.Serialization;
 using System.Text.RegularExpressions;
 using LibMatrix.Extensions;
 using LibMatrix.Helpers;
+using LibMatrix.Homeservers;
 using LibMatrix.StateEventTypes.Spec;
 
 namespace LibMatrix.Responses;
@@ -29,6 +30,9 @@ public class CreateRoomRequest {
     [JsonPropertyName("initial_state")]
     public List<StateEvent> InitialState { get; set; } = null!;
 
+    /// <summary>
+    /// One of: ["public", "private"]
+    /// </summary>
     [JsonPropertyName("visibility")]
     public string Visibility { get; set; } = null!;
 
@@ -38,6 +42,9 @@ public class CreateRoomRequest {
     [JsonPropertyName("creation_content")]
     public JsonObject CreationContent { get; set; } = new();
 
+    [JsonPropertyName("invite")]
+    public List<string> Invite { get; set; }
+
     /// <summary>
     ///     For use only when you can't use the CreationContent property
     /// </summary>
@@ -53,9 +60,10 @@ public class CreateRoomRequest {
                         StateEvent.KnownStateEventTypes.FirstOrDefault(x =>
                             x.GetCustomAttributes<MatrixEventAttribute>()?
                                 .Any(y => y.EventName == event_type) ?? false) ?? typeof(object)
-                        )
+                    )
                 });
             }
+
             return stateEvent;
         }
         set {
@@ -75,4 +83,44 @@ public class CreateRoomRequest {
 
         return errors;
     }
+
+    public static CreateRoomRequest CreatePrivate(AuthenticatedHomeserverGeneric hs, string? name = null, string? roomAliasName = null) {
+        var request = new CreateRoomRequest() {
+            Name = name ?? "Private Room",
+            Visibility = "private",
+            CreationContent = new(),
+            PowerLevelContentOverride = new() {
+                EventsDefault = 0,
+                UsersDefault = 0,
+                Kick = 50,
+                Ban = 50,
+                Invite = 25,
+                StateDefault = 10,
+                Redact = 50,
+                NotificationsPl = new() {
+                    Room = 10
+                },
+                Events = new() {
+                    { "m.room.avatar", 50 },
+                    { "m.room.canonical_alias", 50 },
+                    { "m.room.encryption", 100 },
+                    { "m.room.history_visibility", 100 },
+                    { "m.room.name", 50 },
+                    { "m.room.power_levels", 100 },
+                    { "m.room.server_acl", 100 },
+                    { "m.room.tombstone", 100 }
+                },
+                Users = new() {
+                    {
+                        hs.UserId,
+                        101
+                    }
+                }
+            },
+            RoomAliasName = roomAliasName,
+            InitialState = new()
+        };
+
+        return request;
+    }
 }
diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs
index 3ba965b..8ba9a4b 100644
--- a/LibMatrix/RoomTypes/GenericRoom.cs
+++ b/LibMatrix/RoomTypes/GenericRoom.cs
@@ -4,6 +4,7 @@ using System.IO;
 using System.Net.Http;
 using System.Net.Http.Json;
 using System.Text.Json;
+using System.Text.Json.Serialization;
 using System.Threading.Tasks;
 using System.Web;
 using LibMatrix.Extensions;
@@ -83,6 +84,7 @@ public class GenericRoom {
         return res ?? new MessagesResponse();
     }
 
+    // TODO: should we even error handle here?
     public async Task<string> GetNameAsync() {
         try {
             var res = await GetStateAsync<RoomNameEventData>("m.room.name");
@@ -103,6 +105,8 @@ public class GenericRoom {
         });
     }
 
+
+    // TODO: rewrite (members endpoint?)
     public async IAsyncEnumerable<StateEventResponse> GetMembersAsync(bool joinedOnly = true) {
         var res = GetFullStateAsync();
         await foreach (var member in res) {
@@ -112,6 +116,9 @@ public class GenericRoom {
         }
     }
 
+
+#region Utility shortcuts
+
     public async Task<List<string>> GetAliasesAsync() {
         var res = await GetStateAsync<RoomAliasEventData>("m.room.aliases");
         return res.Aliases;
@@ -143,6 +150,13 @@ public class GenericRoom {
         return res.Type;
     }
 
+    public async Task<RoomPowerLevelEventData?> GetPowerLevelAsync() =>
+        await GetStateAsync<RoomPowerLevelEventData>("m.room.power_levels");
+
+#endregion
+
+
+
     public async Task ForgetAsync() =>
         await _httpClient.PostAsync($"/_matrix/client/v3/rooms/{RoomId}/forget", null);
 
@@ -169,7 +183,9 @@ public class GenericRoom {
 
     public async Task<EventIdResponse> SendMessageEventAsync(string eventType, RoomMessageEventData content) {
         var res = await _httpClient.PutAsJsonAsync(
-            $"/_matrix/client/v3/rooms/{RoomId}/send/{eventType}/" + Guid.NewGuid(), content);
+            $"/_matrix/client/v3/rooms/{RoomId}/send/{eventType}/" + Guid.NewGuid(), content, new  JsonSerializerOptions() {
+                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
+            });
         var resu = await res.Content.ReadFromJsonAsync<EventIdResponse>();
         return resu;
     }
@@ -207,4 +223,8 @@ public class GenericRoom {
     }
 
     public readonly SpaceRoom AsSpace;
+
+    public async Task<T> GetEvent<T>(string eventId) {
+        return await _httpClient.GetFromJsonAsync<T>($"/_matrix/client/v3/rooms/{RoomId}/event/{eventId}");
+    }
 }
diff --git a/LibMatrix/StateEventTypes/Spec/JoinRulesEventData.cs b/LibMatrix/StateEventTypes/Spec/JoinRulesEventData.cs
index d3da559..08e8f22 100644
--- a/LibMatrix/StateEventTypes/Spec/JoinRulesEventData.cs
+++ b/LibMatrix/StateEventTypes/Spec/JoinRulesEventData.cs
@@ -12,6 +12,10 @@ public class JoinRulesEventData : IStateEventType {
     private static string Invite = "invite";
     private static string Knock = "knock";
 
+    /// <summary>
+    /// one of ["public", "invite", "knock", "restricted", "knock_restricted"]
+    /// "private" is reserved without implementation!
+    /// </summary>
     [JsonPropertyName("join_rule")]
     public string JoinRule { get; set; }
 
diff --git a/LibMatrix/StateEventTypes/Spec/RoomMessageEventData.cs b/LibMatrix/StateEventTypes/Spec/RoomMessageEventData.cs
index 5d65237..11a0e82 100644
--- a/LibMatrix/StateEventTypes/Spec/RoomMessageEventData.cs
+++ b/LibMatrix/StateEventTypes/Spec/RoomMessageEventData.cs
@@ -17,4 +17,24 @@ public class RoomMessageEventData : IStateEventType {
 
     [JsonPropertyName("format")]
     public string Format { get; set; }
+
+    [JsonPropertyName("m.relates_to")]
+    public MessageRelatesTo? RelatesTo { get; set; }
+
+    /// <summary>
+    /// Media URI for this message, if any
+    /// </summary>
+    [JsonPropertyName("url")]
+    public string? Url { get; set; }
+
+    public class MessageRelatesTo {
+
+        [JsonPropertyName("m.in_reply_to")]
+        public MessageInReplyTo? InReplyTo { get; set; }
+
+        public class MessageInReplyTo {
+            [JsonPropertyName("event_id")]
+            public string EventId { get; set; }
+        }
+    }
 }