about summary refs log tree commit diff
diff options
context:
space:
mode:
m---------ArcaneLibs0
m---------ExampleBots/LibMatrix.ExampleBot0
m---------ExampleBots/ModerationBot0
m---------ExampleBots/PluralContactBotPoC0
-rw-r--r--LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs4
-rw-r--r--LibMatrix.EventTypes/Spec/State/RoomInfo/RoomPowerLevelEventContent.cs22
-rw-r--r--LibMatrix/Extensions/HttpClientExtensions.cs2
-rw-r--r--LibMatrix/Helpers/SyncHelper.cs9
-rw-r--r--LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs24
-rw-r--r--LibMatrix/RoomTypes/GenericRoom.cs2
-rw-r--r--LibMatrix/RoomTypes/SpaceRoom.cs5
-rw-r--r--LibMatrix/Utilities/CommonSyncFilters.cs47
-rw-r--r--Tests/LibMatrix.Tests/Tests/RoomTests.cs2
-rw-r--r--Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs15
14 files changed, 108 insertions, 24 deletions
diff --git a/ArcaneLibs b/ArcaneLibs
-Subproject f69bb51f21002870b0f2dd1c135209cabc83549
+Subproject f7bcde91ffd1ec285a3f6d3febbb2433daf9634
diff --git a/ExampleBots/LibMatrix.ExampleBot b/ExampleBots/LibMatrix.ExampleBot
-Subproject ecda7b17dfd83d787bc12d7194103d20cd4a835
+Subproject 4f9311ed047c6e6a62e3d49be330a83a829b72f
diff --git a/ExampleBots/ModerationBot b/ExampleBots/ModerationBot
-Subproject ee6e58970f62fa19d04f07d06d6c1476bf7e278
+Subproject 8579db2c9099630b6a268015d586db73435032f
diff --git a/ExampleBots/PluralContactBotPoC b/ExampleBots/PluralContactBotPoC
-Subproject 14c20d6905640c8f691fec76752318a474fa0bc
+Subproject 7ef0970090c1525a60063c0ba7c0a4bd9fd8cc2
diff --git a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs
index b557e47..349c8a7 100644
--- a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs
+++ b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomJoinRulesEventContent.cs
@@ -43,6 +43,10 @@ public class RoomJoinRulesEventContent : EventContent {
 
         [JsonPropertyName("room_id")]
         public required string RoomId { get; set; }
+
+        public static class Types {
+            public const string RoomMembership = "m.room_membership";
+        }
     }
 
     public enum JoinRules {
diff --git a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomPowerLevelEventContent.cs b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomPowerLevelEventContent.cs
index cb9ebb7..49a1b62 100644
--- a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomPowerLevelEventContent.cs
+++ b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomPowerLevelEventContent.cs
@@ -59,15 +59,31 @@ public class RoomPowerLevelEventContent : EventContent {
 
     public bool UserHasStatePermission(string userId, string eventType) {
         ArgumentNullException.ThrowIfNull(userId);
-        return Users.TryGetValue(userId, out var level) && level >= Events.GetValueOrDefault(eventType, StateDefault ?? 50);
+        var userLevel = GetUserPowerLevel(userId);
+        var eventLevel = GetStateEventPowerLevel(eventType);
+        
+        Console.WriteLine($"{userId}={userLevel} >= {eventType}={eventLevel} = {userLevel >= eventLevel}");
+
+        return userLevel >= eventLevel;
     }
 
     public long GetUserPowerLevel(string userId) {
         ArgumentNullException.ThrowIfNull(userId);
-        return Users.TryGetValue(userId, out var level) ? level : UsersDefault ?? UsersDefault ?? 0;
+        if (Users is null) return UsersDefault ?? 0;
+        return Users.TryGetValue(userId, out var level) ? level : UsersDefault ?? 0;
     }
 
-    public long GetEventPowerLevel(string eventType) => Events.TryGetValue(eventType, out var level) ? level : EventsDefault ?? EventsDefault ?? 0;
+    public long GetStateEventPowerLevel(string eventType) {
+        ArgumentNullException.ThrowIfNull(eventType);
+        if (Events is null) return StateDefault ?? 0;
+        return Events.TryGetValue(eventType, out var level) ? level : StateDefault ?? 0;
+    }
+    
+    public long GetTimelineEventPowerLevel(string eventType) {
+        ArgumentNullException.ThrowIfNull(eventType);
+        if (Events is null) return EventsDefault ?? 0;
+        return Events.TryGetValue(eventType, out var level) ? level : EventsDefault ?? 0;
+    }
 
     public void SetUserPowerLevel(string userId, long powerLevel) {
         ArgumentNullException.ThrowIfNull(userId);
diff --git a/LibMatrix/Extensions/HttpClientExtensions.cs b/LibMatrix/Extensions/HttpClientExtensions.cs
index b2f45bd..60b1fc1 100644
--- a/LibMatrix/Extensions/HttpClientExtensions.cs
+++ b/LibMatrix/Extensions/HttpClientExtensions.cs
@@ -57,7 +57,7 @@ public class MatrixHttpClient : HttpClient {
 
         HttpResponseMessage responseMessage;
         // try {
-        responseMessage = await base.SendAsync(request, cancellationToken);
+        responseMessage = await base.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
         // }
         // catch (Exception e) {
         // if (requestSettings is { Retries: 0 }) throw;
diff --git a/LibMatrix/Helpers/SyncHelper.cs b/LibMatrix/Helpers/SyncHelper.cs
index 47e5b1e..f9a7cb7 100644
--- a/LibMatrix/Helpers/SyncHelper.cs
+++ b/LibMatrix/Helpers/SyncHelper.cs
@@ -120,7 +120,7 @@ public class SyncHelper(AuthenticatedHomeserverGeneric homeserver, ILogger? logg
     }
 
     public async Task RunSyncLoopAsync(bool skipInitialSyncEvents = true, CancellationToken? cancellationToken = null) {
-        var sw = Stopwatch.StartNew();
+        // var sw = Stopwatch.StartNew();
         var emptyInitialSyncCount = 0;
         var syncCount = 0;
         var oldTimeout = Timeout;
@@ -153,7 +153,7 @@ public class SyncHelper(AuthenticatedHomeserverGeneric homeserver, ILogger? logg
                     Timeout = oldTimeout;
                 }
             }
-            else if (syncCount > 15)
+            else if (syncCount > 15 && IsInitialSync)
                 Console.WriteLine(sync.ToJson(ignoreNull: true, indent: true));
 
             await RunSyncLoopCallbacksAsync(sync, IsInitialSync && skipInitialSyncEvents);
@@ -212,4 +212,9 @@ public class SyncHelper(AuthenticatedHomeserverGeneric homeserver, ILogger? logg
     /// Event fired when an account data event is received
     /// </summary>
     public List<Func<StateEventResponse, Task>> AccountDataReceivedHandlers { get; } = new();
+    
+    private void Log(string message) {
+        if (logger is null) Console.WriteLine(message);
+        else logger.LogInformation(message);
+    }
 }
\ No newline at end of file
diff --git a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
index 02f3e3a..1c93235 100644
--- a/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
+++ b/LibMatrix/Homeservers/AuthenticatedHomeserverGeneric.cs
@@ -295,6 +295,27 @@ public class AuthenticatedHomeserverGeneric(string serverName, string accessToke
     }
 
     public async Task<FilterIdResponse> UploadFilterAsync(SyncFilter filter) {
+        List<List<string>?> senderLists = [
+            filter.AccountData?.Senders,
+            filter.AccountData?.NotSenders,
+            filter.Presence?.Senders,
+            filter.Presence?.NotSenders,
+            filter.Room?.AccountData?.Senders,
+            filter.Room?.AccountData?.NotSenders,
+            filter.Room?.Ephemeral?.Senders,
+            filter.Room?.Ephemeral?.NotSenders,
+            filter.Room?.State?.Senders,
+            filter.Room?.State?.NotSenders,
+            filter.Room?.Timeline?.Senders,
+            filter.Room?.Timeline?.NotSenders
+        ];
+        
+        foreach (var list in senderLists)
+            if (list is { Count: > 0 } && list.Contains("@me")) {
+                list.Remove("@me");
+                list.Add(UserId);
+            }
+        
         var resp = await ClientHttpClient.PostAsJsonAsync("/_matrix/client/v3/user/" + UserId + "/filter", filter);
         return await resp.Content.ReadFromJsonAsync<FilterIdResponse>() ?? throw new Exception("Failed to upload filter?");
     }
@@ -327,8 +348,7 @@ public class AuthenticatedHomeserverGeneric(string serverName, string accessToke
     /// <returns>Filter ID response</returns>
     /// <exception cref="Exception"></exception>
     public async Task<FilterIdResponse> UploadNamedFilterAsync(string filterName, SyncFilter filter) {
-        var resp = await ClientHttpClient.PostAsJsonAsync("/_matrix/client/v3/user/" + UserId + "/filter", filter);
-        var idResp = await resp.Content.ReadFromJsonAsync<FilterIdResponse>() ?? throw new Exception("Failed to upload filter?");
+        var idResp = await UploadFilterAsync(filter);
 
         var filterList = await GetNamedFilterListOrNullAsync() ?? new Dictionary<string, string>();
         filterList[filterName] = idResp.FilterId;
diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs
index eee6041..cf32df8 100644
--- a/LibMatrix/RoomTypes/GenericRoom.cs
+++ b/LibMatrix/RoomTypes/GenericRoom.cs
@@ -435,7 +435,7 @@ public class GenericRoom {
 
 #region Disband room
 
-    public async Task DisbandRoomAsync() {
+    public async Task PermanentlyBrickRoomAsync() {
         var states = GetFullStateAsync();
         List<string> stateTypeIgnore = new() {
             "m.room.create",
diff --git a/LibMatrix/RoomTypes/SpaceRoom.cs b/LibMatrix/RoomTypes/SpaceRoom.cs
index 9bd1173..49e751d 100644
--- a/LibMatrix/RoomTypes/SpaceRoom.cs
+++ b/LibMatrix/RoomTypes/SpaceRoom.cs
@@ -1,5 +1,6 @@
 using ArcaneLibs.Extensions;
 using LibMatrix.Homeservers;
+using Microsoft.Extensions.Logging;
 
 namespace LibMatrix.RoomTypes;
 
@@ -31,4 +32,8 @@ public class SpaceRoom(AuthenticatedHomeserverGeneric homeserver, string roomId)
         });
         return resp;
     }
+    
+    public async Task<EventIdResponse> AddChildByIdAsync(string id) {
+        return await AddChildAsync(Homeserver.GetRoom(id));
+    }
 }
\ No newline at end of file
diff --git a/LibMatrix/Utilities/CommonSyncFilters.cs b/LibMatrix/Utilities/CommonSyncFilters.cs
index 8e727be..bf8b987 100644
--- a/LibMatrix/Utilities/CommonSyncFilters.cs
+++ b/LibMatrix/Utilities/CommonSyncFilters.cs
@@ -1,5 +1,7 @@
 using System.Collections.Frozen;
+using LibMatrix.EventTypes.Common;
 using LibMatrix.EventTypes.Spec.State;
+using LibMatrix.EventTypes.Spec.State.RoomInfo;
 using LibMatrix.Filters;
 
 namespace LibMatrix.Utilities;
@@ -9,15 +11,16 @@ public static class CommonSyncFilters {
     public const string GetAccountDataWithRooms = "gay.rory.libmatrix.get_account_data_with_rooms.v0";
     public const string GetBasicRoomInfo = "gay.rory.matrixutils.get_basic_room_info.v0";
     public const string GetSpaceRelations = "gay.rory.matrixutils.get_space_relations.v0";
+    public const string GetOwnMemberEvents = "gay.rory.matrixutils.get_own_member_events.v0";
 
-    public static readonly SyncFilter GetAccountDataFilter = new() {
+    public static SyncFilter GetAccountDataFilter => new() {
         Presence = new SyncFilter.EventFilter(notTypes: ["*"]),
         Room = new SyncFilter.RoomFilter() {
             Rooms = []
         }
     };
 
-    public static readonly SyncFilter GetAccountDataWithRoomsFilter = new() {
+    public static SyncFilter GetAccountDataWithRoomsFilter => new() {
         Presence = new SyncFilter.EventFilter(notTypes: ["*"]),
         Room = new SyncFilter.RoomFilter() {
             State = new SyncFilter.RoomFilter.StateFilter(notTypes: ["*"]),
@@ -26,7 +29,7 @@ public static class CommonSyncFilters {
         }
     };
 
-    public static readonly SyncFilter GetBasicRoomDataFilter = new() {
+    public static SyncFilter GetBasicRoomDataFilter => new() {
         AccountData = new SyncFilter.EventFilter(notTypes: ["*"], limit: 1),
         Presence = new SyncFilter.EventFilter(notTypes: ["*"], limit: 1),
         Room = new SyncFilter.RoomFilter {
@@ -34,11 +37,11 @@ public static class CommonSyncFilters {
             Ephemeral = new SyncFilter.RoomFilter.StateFilter(rooms: []),
             State = new SyncFilter.RoomFilter.StateFilter {
                 Types = new List<string> {
-                    "m.room.create",
-                    "m.room.name",
-                    "m.room.avatar",
-                    "org.matrix.mjolnir.shortcode",
-                    "m.room.power_levels"
+                    RoomCreateEventContent.EventId,
+                    RoomNameEventContent.EventId,
+                    RoomAvatarEventContent.EventId,
+                    MjolnirShortcodeEventContent.EventId,
+                    RoomPowerLevelEventContent.EventId
                 },
                 LazyLoadMembers = true, IncludeRedundantMembers = false
             },
@@ -46,7 +49,7 @@ public static class CommonSyncFilters {
         }
     };
 
-    public static readonly SyncFilter GetSpaceRelationsFilter = new() {
+    public static SyncFilter GetSpaceRelationsFilter => new() {
         AccountData = new SyncFilter.EventFilter(notTypes: ["*"], limit: 1),
         Presence = new SyncFilter.EventFilter(notTypes: ["*"], limit: 1),
         Room = new SyncFilter.RoomFilter {
@@ -54,8 +57,8 @@ public static class CommonSyncFilters {
             Ephemeral = new SyncFilter.RoomFilter.StateFilter(rooms: []),
             State = new SyncFilter.RoomFilter.StateFilter {
                 Types = new List<string> {
-                    "m.space.child",
-                    "m.space.parent"
+                    SpaceChildEventContent.EventId,
+                    SpaceParentEventContent.EventId
                 },
                 LazyLoadMembers = true, IncludeRedundantMembers = false
             },
@@ -63,11 +66,29 @@ public static class CommonSyncFilters {
         }
     };
 
+    public static SyncFilter GetOwnMemberEventsFilter => new() {
+        AccountData = new SyncFilter.EventFilter(types: ["m.room.member"], limit: 1),
+        Presence = new SyncFilter.EventFilter(notTypes: ["*"], limit: 1),
+        Room = new SyncFilter.RoomFilter {
+            AccountData = new SyncFilter.RoomFilter.StateFilter(rooms: []),
+            Ephemeral = new SyncFilter.RoomFilter.StateFilter(rooms: []),
+            State = new SyncFilter.RoomFilter.StateFilter {
+                Types = new List<string> {
+                    RoomMemberEventContent.EventId
+                },
+                LazyLoadMembers = true, IncludeRedundantMembers = false,
+                Senders = ["@me"]
+            },
+            Timeline = new SyncFilter.RoomFilter.StateFilter(rooms: [])
+        }
+    };
+
     // This must be down here, due to statics load order
-    public static readonly FrozenDictionary<string, SyncFilter> FilterMap = new Dictionary<string, SyncFilter>() {
+    public static FrozenDictionary<string, SyncFilter> FilterMap => new Dictionary<string, SyncFilter>() {
         [GetAccountData] = GetAccountDataFilter,
         [GetAccountDataWithRooms] = GetAccountDataWithRoomsFilter,
         [GetBasicRoomInfo] = GetBasicRoomDataFilter,
-        [GetSpaceRelations] = GetSpaceRelationsFilter
+        [GetSpaceRelations] = GetSpaceRelationsFilter,
+        [GetOwnMemberEvents] = GetOwnMemberEventsFilter
     }.ToFrozenDictionary();
 }
\ No newline at end of file
diff --git a/Tests/LibMatrix.Tests/Tests/RoomTests.cs b/Tests/LibMatrix.Tests/Tests/RoomTests.cs
index 4f7ac17..4c8dcb4 100644
--- a/Tests/LibMatrix.Tests/Tests/RoomTests.cs
+++ b/Tests/LibMatrix.Tests/Tests/RoomTests.cs
@@ -198,7 +198,7 @@ public class RoomTests : TestBed<TestFixture> {
         var room = await RoomAbstraction.GetTestRoom(hs);
         Assert.NotNull(room);
 
-        await room.DisbandRoomAsync();
+        await room.PermanentlyBrickRoomAsync();
     }
 
     [Fact]
diff --git a/Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs b/Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs
index 11ee740..d9e4dc8 100644
--- a/Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs
+++ b/Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs
@@ -1,4 +1,6 @@
+using System.Reflection.Metadata;
 using LibMatrix.EventTypes.Spec;
+using LibMatrix.Filters;
 using LibMatrix.Helpers;
 using LibMatrix.Homeservers;
 using LibMatrix.Utilities.Bot.Interfaces;
@@ -37,8 +39,19 @@ public class CommandListenerHostedService : IHostedService {
 
     private async Task? Run(CancellationToken cancellationToken) {
         _logger.LogInformation("Starting command listener!");
+        var filter = await _hs.GetOrUploadNamedFilterIdAsync("gay.rory.libmatrix.utilities.bot.command_listener_syncfilter.dev2", new SyncFilter() {
+            AccountData = new SyncFilter.EventFilter(notTypes: ["*"], limit: 1),
+            Presence = new SyncFilter.EventFilter(notTypes: ["*"]),
+            Room = new SyncFilter.RoomFilter() {
+                AccountData = new SyncFilter.RoomFilter.StateFilter(notTypes: ["*"]),
+                Ephemeral = new SyncFilter.RoomFilter.StateFilter(notTypes: ["*"]),
+                State = new SyncFilter.RoomFilter.StateFilter(notTypes: ["*"]),
+                Timeline = new SyncFilter.RoomFilter.StateFilter(types: ["m.room.message"], notSenders: [_hs.WhoAmI.UserId]),
+            }
+        });
         var syncHelper = new SyncHelper(_hs, _logger) {
-            Timeout = 300_000
+            Timeout = 300_000,
+            FilterId = filter
         };
         syncHelper.TimelineEventHandlers.Add(async @event => {
             try {