2017-08-26 17:24:37 +00:00
|
|
|
|
using Discord.WebSocket;
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
using System;
|
2017-08-10 02:29:45 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
2017-11-12 03:12:24 +00:00
|
|
|
|
namespace Noikoio.RegexBot.Module.AutoMod
|
2017-08-10 02:29:45 +00:00
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Implements per-message regex matching and executes customizable responses.
|
|
|
|
|
/// The name RegexBot comes from the existence of this feature.
|
|
|
|
|
/// </summary>
|
2017-08-26 17:24:37 +00:00
|
|
|
|
/// <remarks>
|
|
|
|
|
/// Strictly for use as a moderation tool only. Triggers that simply reply to messages
|
|
|
|
|
/// should be implemented using <see cref="AutoRespond"/>.
|
|
|
|
|
/// </remarks>
|
2017-11-12 03:12:24 +00:00
|
|
|
|
class AutoMod : BotModule
|
2017-08-10 02:29:45 +00:00
|
|
|
|
{
|
|
|
|
|
public AutoMod(DiscordSocketClient client) : base(client)
|
|
|
|
|
{
|
2017-08-26 17:24:37 +00:00
|
|
|
|
client.MessageReceived += CMessageReceived;
|
|
|
|
|
client.MessageUpdated += CMessageUpdated;
|
|
|
|
|
}
|
2018-03-22 06:27:19 +00:00
|
|
|
|
|
2018-03-22 07:30:22 +00:00
|
|
|
|
public override async Task<object> CreateInstanceState(JToken configSection)
|
2017-08-26 17:24:37 +00:00
|
|
|
|
{
|
2018-03-22 07:30:22 +00:00
|
|
|
|
if (configSection == null) return null;
|
2017-09-05 17:18:07 +00:00
|
|
|
|
List<ConfigItem> rules = new List<ConfigItem>();
|
2017-08-30 05:25:47 +00:00
|
|
|
|
|
|
|
|
|
foreach (var def in configSection.Children<JProperty>())
|
2017-08-26 17:24:37 +00:00
|
|
|
|
{
|
2017-08-30 05:25:47 +00:00
|
|
|
|
string label = def.Name;
|
2017-09-05 17:18:07 +00:00
|
|
|
|
var rule = new ConfigItem(this, def);
|
2017-08-26 17:24:37 +00:00
|
|
|
|
rules.Add(rule);
|
|
|
|
|
}
|
2017-09-05 16:10:46 +00:00
|
|
|
|
if (rules.Count > 0)
|
|
|
|
|
await Log($"Loaded {rules.Count} rule(s) from configuration.");
|
2017-08-26 17:24:37 +00:00
|
|
|
|
return rules.AsReadOnly();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task CMessageReceived(SocketMessage arg)
|
|
|
|
|
=> await ReceiveMessage(arg);
|
|
|
|
|
private async Task CMessageUpdated(Discord.Cacheable<Discord.IMessage, ulong> arg1, SocketMessage arg2, ISocketMessageChannel arg3)
|
|
|
|
|
=> await ReceiveMessage(arg2);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Does initial message checking before sending to further processing.
|
|
|
|
|
/// </summary>
|
|
|
|
|
private async Task ReceiveMessage(SocketMessage m)
|
|
|
|
|
{
|
|
|
|
|
// Determine if incoming channel is in a guild
|
|
|
|
|
var ch = m.Channel as SocketGuildChannel;
|
|
|
|
|
if (ch == null) return;
|
|
|
|
|
|
|
|
|
|
// Get rules
|
2018-03-22 07:30:22 +00:00
|
|
|
|
var rules = GetState<IEnumerable<ConfigItem>>(ch.Guild.Id);
|
2017-08-26 17:24:37 +00:00
|
|
|
|
if (rules == null) return;
|
|
|
|
|
|
|
|
|
|
foreach (var rule in rules)
|
|
|
|
|
{
|
2017-09-05 17:18:07 +00:00
|
|
|
|
// Checking for mod bypass here (ConfigItem.Match isn't able to access mod list)
|
2017-08-26 17:24:37 +00:00
|
|
|
|
bool isMod = IsModerator(ch.Guild.Id, m);
|
2017-08-28 01:34:22 +00:00
|
|
|
|
await Task.Run(async () => await ProcessMessage(m, rule, isMod));
|
2017-08-26 17:24:37 +00:00
|
|
|
|
}
|
2017-08-10 02:29:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-26 17:24:37 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Checks if the incoming message matches the given rule, and executes responses if necessary.
|
|
|
|
|
/// </summary>
|
2017-09-05 17:18:07 +00:00
|
|
|
|
private async Task ProcessMessage(SocketMessage m, ConfigItem r, bool isMod)
|
2017-08-10 02:29:45 +00:00
|
|
|
|
{
|
2017-08-26 17:24:37 +00:00
|
|
|
|
if (!r.Match(m, isMod)) return;
|
|
|
|
|
|
|
|
|
|
// TODO make log optional; configurable
|
2017-09-05 01:55:03 +00:00
|
|
|
|
await Log($"{r} triggered by {m.Author} in {((SocketGuildChannel)m.Channel).Guild.Name}/#{m.Channel.Name}");
|
2017-08-26 17:24:37 +00:00
|
|
|
|
|
2017-09-05 17:18:07 +00:00
|
|
|
|
foreach (ResponseBase resp in r.Response)
|
2017-08-26 17:24:37 +00:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
await resp.Invoke(m);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
await Log($"Encountered an error while processing '{resp.CmdArg0}'. Details follow:");
|
|
|
|
|
await Log(ex.ToString());
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-08-10 02:29:45 +00:00
|
|
|
|
}
|
2017-08-26 17:24:37 +00:00
|
|
|
|
|
|
|
|
|
public new Task Log(string text) => base.Log(text);
|
|
|
|
|
public new DiscordSocketClient Client => base.Client;
|
2017-08-10 02:29:45 +00:00
|
|
|
|
}
|
|
|
|
|
}
|