using Discord.WebSocket; using Newtonsoft.Json.Linq; using System.Collections.Generic; using System.Threading.Tasks; namespace Kerobot.Modules.RegexModerator { /// /// The 'star' feature of Kerobot. Users define pattern-based rules with other constraints. /// When triggered, each rule executes one or more different actions. /// [KerobotModule] public class RegexModerator : ModuleBase { public RegexModerator(Kerobot kb) : base(kb) { 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(); foreach (var def in config.Children()) defs.Add(new ConfDefinition(this, def, guildID)); if (defs.Count == 0) return Task.FromResult(null); return Task.FromResult(defs.AsReadOnly()); } private Task DiscordClient_MessageUpdated(Discord.Cacheable arg1, SocketMessage arg2, ISocketMessageChannel arg3) => ReceiveIncomingMessage(arg2); private Task DiscordClient_MessageReceived(SocketMessage arg) => ReceiveIncomingMessage(arg); /// /// Does initial message checking before further processing. /// private async Task ReceiveIncomingMessage(SocketMessage msg) { // Ignore non-guild channels if (!(msg.Channel is SocketGuildChannel ch)) return; // Get config? var defs = GetGuildState>(ch.Guild.Id); if (defs == null) return; // Send further processing to thread pool. // Match checking is a CPU-intensive task, thus very little checking is done here. 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); var match = item.IsMatch(msg, isMod); await Task.Run(async () => await ProcessMessage(item, msg, isMod)); } } /// /// Does further message checking and response execution. /// Invocations of this method are meant to be on the thread pool. /// private async Task ProcessMessage(ConfDefinition def, SocketMessage msg, bool isMod) { // Reminder: IsMatch handles matching execution time if (!def.IsMatch(msg, isMod)) return; // TODO logging options for match result; handle here? var executor = new ResponseExecutor(def, Kerobot); await executor.Execute(msg); } } }