about summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--LibMatrix/RoomTypes/GenericRoom.cs39
-rw-r--r--LibMatrix/RoomTypes/SpaceRoom.cs2
-rw-r--r--Tests/LibMatrix.Tests/Tests/RoomTests/RoomMembershipTests.cs2
-rw-r--r--Tests/LibMatrix.Tests/Tests/RoomTests/RoomTests.cs2
-rw-r--r--Utilities/LibMatrix.Utilities.Bot/LibMatrixBotConfiguration.cs1
-rw-r--r--Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs35
6 files changed, 58 insertions, 23 deletions
diff --git a/LibMatrix/RoomTypes/GenericRoom.cs b/LibMatrix/RoomTypes/GenericRoom.cs

index 93736a3..bc1bc90 100644 --- a/LibMatrix/RoomTypes/GenericRoom.cs +++ b/LibMatrix/RoomTypes/GenericRoom.cs
@@ -232,8 +232,11 @@ public class GenericRoom { return await res.Content.ReadFromJsonAsync<RoomIdResponse>() ?? throw new Exception("Failed to join room?"); } - public async IAsyncEnumerable<StateEventResponse> GetMembersEnumerableAsync(bool joinedOnly = true) { - var res = await Homeserver.ClientHttpClient.GetAsync($"/_matrix/client/v3/rooms/{RoomId}/members"); + public async IAsyncEnumerable<StateEventResponse> GetMembersEnumerableAsync(string? membership = null) { + var url = $"/_matrix/client/v3/rooms/{RoomId}/members"; + var isMembershipSet = !string.IsNullOrWhiteSpace(membership); + if (isMembershipSet) url += $"?membership={membership}"; + var res = await Homeserver.ClientHttpClient.GetAsync(url); var result = await JsonSerializer.DeserializeAsync<ChunkedStateEventResponse>(await res.Content.ReadAsStreamAsync(), new JsonSerializerOptions() { TypeInfoResolver = ChunkedStateEventResponseSerializerContext.Default }); @@ -242,13 +245,16 @@ public class GenericRoom { foreach (var resp in result.Chunk ?? []) { if (resp.Type != "m.room.member") continue; - if (joinedOnly && resp.RawContent?["membership"]?.GetValue<string>() != "join") continue; + if (isMembershipSet && resp.RawContent?["membership"]?.GetValue<string>() != membership) continue; yield return resp; } } - public async Task<FrozenSet<StateEventResponse>> GetMembersListAsync(bool joinedOnly = true) { - var res = await Homeserver.ClientHttpClient.GetAsync($"/_matrix/client/v3/rooms/{RoomId}/members"); + public async Task<FrozenSet<StateEventResponse>> GetMembersListAsync(string? membership = null) { + var url = $"/_matrix/client/v3/rooms/{RoomId}/members"; + var isMembershipSet = !string.IsNullOrWhiteSpace(membership); + if (isMembershipSet) url += $"?membership={membership}"; + var res = await Homeserver.ClientHttpClient.GetAsync(url); var result = await JsonSerializer.DeserializeAsync<ChunkedStateEventResponse>(await res.Content.ReadAsStreamAsync(), new JsonSerializerOptions() { TypeInfoResolver = ChunkedStateEventResponseSerializerContext.Default }); @@ -258,13 +264,23 @@ public class GenericRoom { var members = new List<StateEventResponse>(); foreach (var resp in result.Chunk ?? []) { if (resp.Type != "m.room.member") continue; - if (joinedOnly && resp.RawContent?["membership"]?.GetValue<string>() != "join") continue; + if (isMembershipSet && resp.RawContent?["membership"]?.GetValue<string>() != membership) continue; members.Add(resp); } return members.ToFrozenSet(); } + public async IAsyncEnumerable<string> GetMemberIdsEnumerableAsync(string? membership = null) { + await foreach (var evt in GetMembersEnumerableAsync(membership)) + yield return evt.StateKey!; + } + + public async Task<FrozenSet<string>> GetMemberIdsListAsync(string? membership = null) { + var members = await GetMembersListAsync(membership); + return members.Select(x => x.StateKey!).ToFrozenSet(); + } + #region Utility shortcuts public Task<EventIdResponse> SendMessageEventAsync(RoomMessageEventContent content) => @@ -393,6 +409,15 @@ public class GenericRoom { return await res.Content.ReadFromJsonAsync<EventIdResponse>() ?? throw new Exception("Failed to send event"); } + public async Task<EventIdResponse> SendReactionAsync(string eventId, string key) => + await SendTimelineEventAsync("m.reaction", new RoomMessageReactionEventContent() { + RelatesTo = new() { + RelationType = "m.annotation", + EventId = eventId, + Key = key + } + }); + 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() { @@ -586,4 +611,4 @@ public class GenericRoom { public class RoomIdResponse { [JsonPropertyName("room_id")] public string RoomId { get; set; } -} +} \ No newline at end of file diff --git a/LibMatrix/RoomTypes/SpaceRoom.cs b/LibMatrix/RoomTypes/SpaceRoom.cs
index 4563ed3..0c74be5 100644 --- a/LibMatrix/RoomTypes/SpaceRoom.cs +++ b/LibMatrix/RoomTypes/SpaceRoom.cs
@@ -17,7 +17,7 @@ public class SpaceRoom(AuthenticatedHomeserverGeneric homeserver, string roomId) } public async Task<EventIdResponse> AddChildAsync(GenericRoom room) { - var members = room.GetMembersEnumerableAsync(true); + var members = room.GetMembersEnumerableAsync("join"); Dictionary<string, int> memberCountByHs = new(); await foreach (var member in members) { var server = member.StateKey.Split(':')[1]; diff --git a/Tests/LibMatrix.Tests/Tests/RoomTests/RoomMembershipTests.cs b/Tests/LibMatrix.Tests/Tests/RoomTests/RoomMembershipTests.cs
index e0784c4..8419518 100644 --- a/Tests/LibMatrix.Tests/Tests/RoomTests/RoomMembershipTests.cs +++ b/Tests/LibMatrix.Tests/Tests/RoomTests/RoomMembershipTests.cs
@@ -162,7 +162,7 @@ public class RoomMembershipTests : TestBed<TestFixture> { await otherUser.GetRoom(room.RoomId).JoinAsync(reason: "Unit test!"); } - var states = await room.GetMembersListAsync(false); + var states = await room.GetMembersListAsync(); Assert.Equal(count + 1, states.Count); await room.LeaveAsync(); diff --git a/Tests/LibMatrix.Tests/Tests/RoomTests/RoomTests.cs b/Tests/LibMatrix.Tests/Tests/RoomTests/RoomTests.cs
index fa9812f..7801ed0 100644 --- a/Tests/LibMatrix.Tests/Tests/RoomTests/RoomTests.cs +++ b/Tests/LibMatrix.Tests/Tests/RoomTests/RoomTests.cs
@@ -300,7 +300,7 @@ public class RoomTests : TestBed<TestFixture> { }); await room.InviteUsersAsync(users.Select(u => u.UserId)); - var members = await room.GetMembersListAsync(false); + var members = await room.GetMembersListAsync(); Assert.NotNull(members); Assert.NotEmpty(members); Assert.All(members, Assert.NotNull); diff --git a/Utilities/LibMatrix.Utilities.Bot/LibMatrixBotConfiguration.cs b/Utilities/LibMatrix.Utilities.Bot/LibMatrixBotConfiguration.cs
index da83cfa..d60dc92 100644 --- a/Utilities/LibMatrix.Utilities.Bot/LibMatrixBotConfiguration.cs +++ b/Utilities/LibMatrix.Utilities.Bot/LibMatrixBotConfiguration.cs
@@ -10,4 +10,5 @@ public class LibMatrixBotConfiguration { public List<string> Prefixes { get; set; } public bool MentionPrefix { get; set; } public string? LogRoom { get; set; } + public bool SelfCommandsOnly { get; set; } = true; } \ No newline at end of file diff --git a/Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs b/Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs
index 9fe460b..745b86e 100644 --- a/Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs +++ b/Utilities/LibMatrix.Utilities.Bot/Services/CommandListenerHostedService.cs
@@ -20,6 +20,7 @@ public class CommandListenerHostedService : IHostedService { private Task? _listenerTask; private CancellationTokenSource _cts = new(); + private long _startupTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); public CommandListenerHostedService(AuthenticatedHomeserverGeneric hs, ILogger<CommandListenerHostedService> logger, IServiceProvider services, LibMatrixBotConfiguration config, Func<CommandResult, Task>? commandResultHandler = null) { @@ -43,16 +44,20 @@ public class CommandListenerHostedService : IHostedService { private async Task? Run(CancellationToken cancellationToken) { _logger.LogInformation("Starting command listener!"); - var filter = await _hs.NamedCaches.FilterCache.GetOrSetValueAsync("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 filter = await _hs.NamedCaches.FilterCache.GetOrSetValueAsync("gay.rory.libmatrix.utilities.bot.command_listener_syncfilter.dev3" + (_config.SelfCommandsOnly), + 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: _config.SelfCommandsOnly ? null : [_hs.WhoAmI.UserId], + senders: _config.SelfCommandsOnly ? [_hs.WhoAmI.UserId] : null + ), + } + }); var syncHelper = new SyncHelper(_hs, _logger) { Timeout = 30_000, @@ -62,9 +67,13 @@ public class CommandListenerHostedService : IHostedService { syncHelper.SyncReceivedHandlers.Add(async sync => { _logger.LogInformation("Sync received!"); foreach (var roomResp in sync.Rooms?.Join ?? []) { - if (roomResp.Value.Timeline?.Events is null or { Count: > 5 }) continue; + // if (roomResp.Value.Timeline?.Events is null or { Count: > 5 }) continue; + if (roomResp.Value.Timeline?.Events is null) continue; foreach (var @event in roomResp.Value.Timeline.Events) { @event.RoomId = roomResp.Key; + if (_config.SelfCommandsOnly && @event.Sender != _hs.WhoAmI.UserId) continue; + if (@event.OriginServerTs < _startupTime) continue; // ignore events older than startup time + try { // var room = _hs.GetRoom(@event.RoomId); // _logger.LogInformation(eventResponse.ToJson(indent: false)); @@ -143,8 +152,8 @@ public class CommandListenerHostedService : IHostedService { .FirstOrDefault(commandWithoutPrefix.StartsWith); var args = usedCommand == null || commandWithoutPrefix.Length <= usedCommand.Length - ? [] - : commandWithoutPrefix[(usedCommand.Length + 1)..].Split(' '); + ? [] + : commandWithoutPrefix[(usedCommand.Length + 1)..].Split(' ').SelectMany(x=>x.Split('\n')).ToArray(); var ctx = new CommandContext { Room = room, MessageEvent = evt,