using Discord; namespace RegexBot.Modules.RegexModerator; /// /// The namesake of RegexBot. This module allows users to define pattern-based rules with other constraints. /// When triggered, one or more actions are executed as defined in its configuration. /// [RegexbotModule] internal class RegexModerator : RegexbotModule { public RegexModerator(RegexbotClient bot) : base(bot) { DiscordClient.MessageReceived += DiscordClient_MessageReceived; DiscordClient.MessageUpdated += DiscordClient_MessageUpdated; } public override Task CreateGuildStateAsync(ulong guildID, JToken? config) { if (config == null) return Task.FromResult(null); var defs = new List(); if (config.Type != JTokenType.Array) throw new ModuleLoadException(Name + " configuration must be a JSON array."); // TODO better error reporting during this process foreach (var def in config.Children()) defs.Add(new ConfDefinition(def)); if (defs.Count == 0) return Task.FromResult(null); Log(DiscordClient.GetGuild(guildID), $"Loaded {defs.Count} definition(s)."); return Task.FromResult(defs.AsReadOnly()); } private Task DiscordClient_MessageReceived(SocketMessage arg) => ReceiveIncomingMessage(arg); private Task DiscordClient_MessageUpdated(Cacheable arg1, SocketMessage arg2, ISocketMessageChannel arg3) { // Ignore embed edits (see comment in MessageCachingSubservice) if (!arg2.EditedTimestamp.HasValue) return Task.CompletedTask; return ReceiveIncomingMessage(arg2); } /// /// Does initial message checking before further processing. /// private async Task ReceiveIncomingMessage(SocketMessage msg) { if (!Common.Utilities.IsValidUserMessage(msg, out var ch)) return; // Get config? var defs = GetGuildState>(ch.Guild.Id); if (defs == null) return; // Matching and response processing foreach (var item in defs) { // Need to check sender's moderator status here. Definition can't access mod list. var isMod = GetModerators(ch.Guild.Id).IsListMatch(msg, true); if (!item.IsMatch(msg, isMod)) continue; Log(ch.Guild, $"Rule '{item.Label}' triggered by {msg.Author}."); var exec = new ResponseExecutor(item, Bot, msg, (string logLine) => Log(ch.Guild, logLine)); await exec.Execute(); } } }