about summary refs log tree commit diff
path: root/MatrixContentFilter/Commands/RedactCommand.cs
diff options
context:
space:
mode:
authorRory& <root@rory.gay>2024-10-04 19:51:44 +0200
committerRory& <root@rory.gay>2024-10-04 19:51:44 +0200
commitc8f7ef7c1d2bd705a5442c0dc591b8e5a50673a5 (patch)
tree9b951c6e2c120ec370ce8318238aadbdda880a89 /MatrixContentFilter/Commands/RedactCommand.cs
downloadMatrixContentFilter-master.tar.xz
Initial commit HEAD master
Diffstat (limited to 'MatrixContentFilter/Commands/RedactCommand.cs')
-rw-r--r--MatrixContentFilter/Commands/RedactCommand.cs99
1 files changed, 99 insertions, 0 deletions
diff --git a/MatrixContentFilter/Commands/RedactCommand.cs b/MatrixContentFilter/Commands/RedactCommand.cs
new file mode 100644
index 0000000..6b2f8b6
--- /dev/null
+++ b/MatrixContentFilter/Commands/RedactCommand.cs
@@ -0,0 +1,99 @@
+using ArcaneLibs.Extensions;
+using LibMatrix.EventTypes.Spec;
+using LibMatrix.EventTypes.Spec.State;
+using LibMatrix.Filters;
+using LibMatrix.Helpers;
+using LibMatrix.Homeservers;
+using LibMatrix.Utilities.Bot.Interfaces;
+using MatrixContentFilter.Abstractions;
+using MatrixContentFilter.Services;
+using MatrixContentFilter.Services.AsyncActionQueues;
+using Microsoft.Extensions.Logging;
+
+namespace MatrixContentFilter.Commands;
+
+public class RedactCommand(
+    ConfigurationService filterConfigService,
+    AsyncMessageQueue msgQueue,
+    InfoCacheService infoCache,
+    ConfigurationService cfgService,
+    AbstractAsyncActionQueue actionQueue
+) : ICommand {
+    public string Name { get; } = "redact";
+    public string[]? Aliases { get; } = [];
+    public string Description { get; } = "Redact last x messages from user (default: 500)";
+    public bool Unlisted { get; } = false;
+
+    public async Task Invoke(CommandContext ctx) {
+        var count = 500;
+
+        if (ctx.Args.Length == 0) {
+            await ctx.Room.SendMessageEventAsync(new MessageBuilder("m.notice")
+                .WithBody("Please provide a user ID to redact messages from. (Make sure that it isn't formatted! Do not autocomplete!)").Build());
+            return;
+        }
+
+        var mxid = ctx.Args[0];
+        if (ctx.Args.Length > 1) {
+            if (!int.TryParse(ctx.Args[1], out count)) {
+                await ctx.Room.SendMessageEventAsync(new MessageBuilder("m.notice").WithBody($"'{count}' is not a valid number!").Build());
+                return;
+            }
+        }
+
+        var displayName = await infoCache.GetDisplayNameAsync(ctx.Room.RoomId, ctx.MessageEvent.Sender);
+        var roomName = await infoCache.GetRoomNameAsync(ctx.Room.RoomId);
+
+        msgQueue.EnqueueMessageAsync(filterConfigService.LogRoom,
+            new MessageBuilder("m.notice").WithBody($"Removing last {count} messages from ").WithMention(mxid)
+                .WithBody(" in ").WithMention(ctx.Room.RoomId, await infoCache.GetRoomNameAsync(ctx.Room.RoomId)).Build());
+        var hourglassReaction = await ctx.Room.SendTimelineEventAsync("m.reaction", new RoomMessageReactionEventContent() {
+            RelatesTo = new() {
+                EventId = ctx.MessageEvent.EventId,
+                RelationType = "m.annotation",
+                Key = "\u23f3" //hour glass emoji
+            }
+        });
+        
+        await foreach (var resp in ctx.Room.GetManyMessagesAsync(limit: count, chunkSize: Math.Min(count, 250)
+                           ,filter: new SyncFilter.RoomFilter.StateFilter(types: [RoomMemberEventContent.EventId, RoomMessageEventContent.EventId], senders: [mxid])
+                               .ToJson(indent: false, ignoreNull: true).UrlEncode())
+                           ) {
+            foreach (var msg in resp.Chunk) {
+                if (msg.Sender != mxid) continue;
+                if (msg is not { Type: RoomMemberEventContent.EventId or RoomMessageEventContent.EventId }) continue;
+                if (msg.RawContent is not { Count: > 0 }) continue;
+
+                await actionQueue.EqueueActionAsync(msg.EventId, async () => {
+                    while (true) {
+                        try {
+                            await ctx.Room.RedactEventAsync(msg.EventId ?? throw new ArgumentException("Event ID is null?"), "Message removed by moderator.");
+                            break;
+                        }
+                        catch (Exception e) {
+                            msgQueue.EnqueueMessageAsync(cfgService.LogRoom, new MessageBuilder("m.notice")
+                                .WithBody($"Error redacting message in {ctx.Room.RoomId}!")
+                                .WithCollapsibleSection("Error data", msb => msb.WithCodeBlock(e.ToString(), "csharp"))
+                                .Build());
+                        }
+                    }
+
+                    msgQueue.EnqueueMessageAsync(cfgService.LogRoom, new MessageBuilder("m.notice")
+                        .WithBody($"Message sent by ").WithMention(msg.Sender, displayName).WithBody(" in ").WithMention(ctx.Room.RoomId, roomName)
+                        .WithBody(" was removed in request by ").WithMention(ctx.Room.RoomId, roomName).WithBody("!").WithNewline()
+                        .WithCollapsibleSection("Message data", msb => msb.WithCodeBlock(msg.RawContent.ToJson(ignoreNull: true), "json"))
+                        .Build());
+                });
+            }
+            
+            await ctx.Room.RedactEventAsync(hourglassReaction.EventId);
+            await ctx.Room.SendTimelineEventAsync("m.reaction", new RoomMessageReactionEventContent() {
+                RelatesTo = new() {
+                    EventId = ctx.MessageEvent.EventId,
+                    RelationType = "m.annotation",
+                    Key = "\u2714\ufe0f" //check mark emoji
+                }
+            });
+        }
+    }
+}
\ No newline at end of file