From 8579db2c9099630b6a268015d586db73435032f0 Mon Sep 17 00:00:00 2001 From: Rory& Date: Fri, 23 Feb 2024 12:31:43 +0100 Subject: Changes --- AccountData/BotData.cs | 8 ++- Commands/BanMediaCommand.cs | 15 ++--- ModerationBot.cs | 1 - PolicyEngine.cs | 50 +++++++------- Program.cs | 2 + Services/ModerationBotRoomProvider.cs | 76 ++++++++++++++++++++++ .../Policies/Implementations/MediaPolicyFile.cs | 2 +- 7 files changed, 117 insertions(+), 37 deletions(-) create mode 100644 Services/ModerationBotRoomProvider.cs diff --git a/AccountData/BotData.cs b/AccountData/BotData.cs index ab680c2..de52679 100644 --- a/AccountData/BotData.cs +++ b/AccountData/BotData.cs @@ -1,14 +1,18 @@ using System.Text.Json.Serialization; +using LibMatrix.EventTypes; namespace ModerationBot.AccountData; +[MatrixEvent(EventName = EventId)] public class BotData { + public const string EventId = "gay.rory.moderation_bot_data"; + [JsonPropertyName("control_room")] - public string ControlRoom { get; set; } = ""; + public string? ControlRoom { get; set; } = ""; [JsonPropertyName("log_room")] public string? LogRoom { get; set; } = ""; [JsonPropertyName("default_policy_room")] public string? DefaultPolicyRoom { get; set; } -} +} \ No newline at end of file diff --git a/Commands/BanMediaCommand.cs b/Commands/BanMediaCommand.cs index 535fd4f..b891932 100644 --- a/Commands/BanMediaCommand.cs +++ b/Commands/BanMediaCommand.cs @@ -6,22 +6,23 @@ using LibMatrix.Helpers; using LibMatrix.Services; using LibMatrix.Utilities.Bot.Interfaces; using ModerationBot.AccountData; +using ModerationBot.Services; using ModerationBot.StateEventTypes.Policies.Implementations; namespace ModerationBot.Commands; -public class BanMediaCommand(IServiceProvider services, HomeserverProviderService hsProvider, HomeserverResolverService hsResolver, PolicyEngine engine) : ICommand { +public class BanMediaCommand(HomeserverResolverService hsResolver, PolicyEngine engine, ModerationBotRoomProvider roomProvider) : ICommand { public string Name { get; } = "banmedia"; public string Description { get; } = "Create a policy banning a piece of media, must be used in reply to a message"; public async Task CanInvoke(CommandContext ctx) { //check if user is admin in control room - var botData = await ctx.Homeserver.GetAccountDataAsync("gay.rory.moderation_bot_data"); - var controlRoom = ctx.Homeserver.GetRoom(botData.ControlRoom); + var controlRoom = await roomProvider.GetControlRoomAsync(); + var logRoom = await roomProvider.GetLogRoomAsync(); var isAdmin = (await controlRoom.GetPowerLevelsAsync())!.UserHasStatePermission(ctx.MessageEvent.Sender, "m.room.ban"); if (!isAdmin) { // await ctx.Reply("You do not have permission to use this command!"); - await ctx.Homeserver.GetRoom(botData.LogRoom!).SendMessageEventAsync( + await logRoom.SendMessageEventAsync( new RoomMessageEventContent(body: $"User {ctx.MessageEvent.Sender} tried to use command {Name} but does not have permission!", messageType: "m.text")); } @@ -29,10 +30,8 @@ public class BanMediaCommand(IServiceProvider services, HomeserverProviderServic } public async Task Invoke(CommandContext ctx) { - - var botData = await ctx.Homeserver.GetAccountDataAsync("gay.rory.moderation_bot_data"); - var policyRoom = ctx.Homeserver.GetRoom(botData.DefaultPolicyRoom ?? botData.ControlRoom); - var logRoom = ctx.Homeserver.GetRoom(botData.LogRoom ?? botData.ControlRoom); + var policyRoom = await roomProvider.GetDefaultPolicyRoomAsync(); + var logRoom = await roomProvider.GetLogRoomAsync(); //check if reply var messageContent = ctx.MessageEvent.TypedContent as RoomMessageEventContent; diff --git a/ModerationBot.cs b/ModerationBot.cs index 2424eee..791d3b5 100644 --- a/ModerationBot.cs +++ b/ModerationBot.cs @@ -30,7 +30,6 @@ public class ModerationBot(AuthenticatedHomeserverGeneric hs, ILogger logger, ModerationBotConfiguration configuration, HomeserverResolverService hsResolver) { +public class PolicyEngine(AuthenticatedHomeserverGeneric hs, ILogger logger, ModerationBotConfiguration configuration, HomeserverResolverService hsResolver, ModerationBotRoomProvider roomProvider) { private Dictionary PolicyListAccountData { get; set; } = new(); + // ReSharper disable once MemberCanBePrivate.Global public List ActivePolicyLists { get; set; } = new(); public List ActivePolicies { get; set; } = new(); @@ -28,11 +31,10 @@ public class PolicyEngine(AuthenticatedHomeserverGeneric hs, ILogger("gay.rory.moderation_bot_data"); - _logRoom ??= hs.GetRoom(botData.LogRoom ?? botData.ControlRoom); - _controlRoom ??= hs.GetRoom(botData.ControlRoom); - + + _logRoom = await roomProvider.GetLogRoomAsync(); + _controlRoom = await roomProvider.GetControlRoomAsync(); + await _controlRoom?.SendMessageEventAsync(MessageFormatter.FormatSuccess("Reloading policy lists!"))!; await _logRoom?.SendMessageEventAsync(MessageFormatter.FormatSuccess("Reloading policy lists!"))!; @@ -46,12 +48,12 @@ public class PolicyEngine(AuthenticatedHomeserverGeneric hs, ILogger>(); foreach (var (roomId, policyList) in PolicyListAccountData) { @@ -62,11 +64,11 @@ public class PolicyEngine(AuthenticatedHomeserverGeneric hs, ILogger= 256 || policyLists.Count == PolicyListAccountData.Count) { + if (true || policyList.Policies.Count >= 256 || policyLists.Count == PolicyListAccountData.Count) { var progressMsgContent = MessageFormatter.FormatSuccess($"{policyLists.Count}/{PolicyListAccountData.Count} policy lists loaded, " + $"{policyLists.Sum(x => x.Policies.Count)} policies total, {sw.Elapsed} elapsed.") .SetReplaceRelation(progressMessage.EventId); - + await _logRoom?.SendMessageEventAsync(progressMsgContent); } } @@ -99,7 +101,6 @@ public class PolicyEngine(AuthenticatedHomeserverGeneric hs, ILogger x.Room.RoomId == roomId)) return; await LoadPolicyListAsync(hs.GetRoom(roomId), ActivePolicyLists.Single(x => x.Room.RoomId == roomId)); @@ -159,7 +160,7 @@ public class PolicyEngine(AuthenticatedHomeserverGeneric hs, ILogger> CheckMessageContent(StateEventResponse @event) { var matchedRules = new List(); @@ -167,11 +168,11 @@ public class PolicyEngine(AuthenticatedHomeserverGeneric hs, ILogger states) { string raw = "Count | State type | Mapped type", html = ""; @@ -261,8 +262,7 @@ public class PolicyEngine(AuthenticatedHomeserverGeneric hs, ILogger { services.AddBot(withCommands: true); services.AddSingleton(); + services.AddSingleton(); services.AddHostedService(); }).UseConsoleLifetime().Build(); diff --git a/Services/ModerationBotRoomProvider.cs b/Services/ModerationBotRoomProvider.cs new file mode 100644 index 0000000..d4a200f --- /dev/null +++ b/Services/ModerationBotRoomProvider.cs @@ -0,0 +1,76 @@ +using System.Diagnostics.CodeAnalysis; +using LibMatrix.Homeservers; +using LibMatrix.Responses; +using LibMatrix.RoomTypes; +using ModerationBot.AccountData; + +namespace ModerationBot.Services; + +public class ModerationBotRoomProvider(AuthenticatedHomeserverGeneric hs, ModerationBotConfiguration cfg) { + private BotData? _botData; + + public BotData? BotData { + get { + if (BotDataExpiry >= DateTime.UtcNow) return _botData; + Console.WriteLine("BotData expired!"); + return null; + } + set { + _botData = value; + Console.WriteLine("BotData updated!"); + BotDataExpiry = DateTime.UtcNow.AddMinutes(5); + } + } + + private DateTime BotDataExpiry { get; set; } + + [MemberNotNull(nameof(BotData))] + private async Task GetBotDataAsync() { + try { + BotData ??= await hs.GetAccountDataAsync(BotData.EventId); + } + catch (Exception e) { + Console.WriteLine(e); + await hs.SetAccountDataAsync(BotData.EventId, new BotData()); + return await GetBotDataAsync(); + } + + if (BotData == null) + throw new NullReferenceException("BotData is null!"); + + return BotData; + } + + public async Task GetControlRoomAsync() { + var botData = await GetBotDataAsync(); + if (botData.ControlRoom == null) { + var createRoomRequest = CreateRoomRequest.CreatePrivate(hs, "Rory&::ModerationBot - Control Room"); + createRoomRequest.Invite = cfg.Admins; + var newRoom = await hs.CreateRoom(createRoomRequest, true, true, true); + BotData.ControlRoom = newRoom.RoomId; + await hs.SetAccountDataAsync(BotData.EventId, BotData); + } + + return hs.GetRoom(BotData.ControlRoom!); + } + + public async Task GetLogRoomAsync() { + var botData = await GetBotDataAsync(); + if (botData.LogRoom == null) { + var controlRoom = await GetControlRoomAsync(); + var createRoomRequest = CreateRoomRequest.CreatePrivate(hs, "Rory&::ModerationBot - Log Room"); + createRoomRequest.Invite = (await controlRoom.GetMembersListAsync()).Select(x=>x.StateKey).ToList(); + var newRoom = await hs.CreateRoom(createRoomRequest, true, true, true); + BotData.LogRoom = newRoom.RoomId; + await hs.SetAccountDataAsync(BotData.EventId, BotData); + } + + return hs.GetRoom(BotData.LogRoom!); + } + + public async Task GetDefaultPolicyRoomAsync() { + var botData = await GetBotDataAsync(); + + return string.IsNullOrWhiteSpace(botData.DefaultPolicyRoom) ? null : hs.GetRoom(BotData.DefaultPolicyRoom!); + } +} \ No newline at end of file diff --git a/StateEventTypes/Policies/Implementations/MediaPolicyFile.cs b/StateEventTypes/Policies/Implementations/MediaPolicyFile.cs index c5b6ef2..f0fef63 100644 --- a/StateEventTypes/Policies/Implementations/MediaPolicyFile.cs +++ b/StateEventTypes/Policies/Implementations/MediaPolicyFile.cs @@ -9,7 +9,7 @@ namespace ModerationBot.StateEventTypes.Policies.Implementations; [MatrixEvent(EventName = "gay.rory.moderation.rule.media")] public class MediaPolicyFile : BasePolicy { /// - /// Hash of the file + /// Hash of the file, hashed with SHA3-256. /// [JsonPropertyName("file_hash")] public string? FileHash { get; set; } -- cgit 1.5.1
CountState typeMapped type