2017-08-26 17:24:37 +00:00
|
|
|
|
using Discord.WebSocket;
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
using Noikoio.RegexBot.Feature.AutoMod.Responses;
|
|
|
|
|
using System;
|
2017-08-10 02:29:45 +00:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace Noikoio.RegexBot.Feature.AutoMod
|
|
|
|
|
{
|
|
|
|
|
/// <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-08-10 02:29:45 +00:00
|
|
|
|
class AutoMod : BotFeature
|
|
|
|
|
{
|
|
|
|
|
public override string Name => "AutoMod";
|
|
|
|
|
|
|
|
|
|
public AutoMod(DiscordSocketClient client) : base(client)
|
|
|
|
|
{
|
2017-08-26 17:24:37 +00:00
|
|
|
|
client.MessageReceived += CMessageReceived;
|
|
|
|
|
client.MessageUpdated += CMessageUpdated;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[ConfigSection("automod")]
|
|
|
|
|
public override async Task<object> ProcessConfiguration(JToken configSection)
|
|
|
|
|
{
|
|
|
|
|
List<Rule> rules = new List<Rule>();
|
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;
|
|
|
|
|
var rule = new Rule(this, def);
|
2017-08-26 17:24:37 +00:00
|
|
|
|
rules.Add(rule);
|
|
|
|
|
await Log($"Added rule '{rule.Label}'");
|
|
|
|
|
}
|
2017-08-30 05:25:47 +00:00
|
|
|
|
|
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
|
|
|
|
|
var rules = GetConfig(ch.Guild.Id) as IEnumerable<Rule>;
|
|
|
|
|
if (rules == null) return;
|
|
|
|
|
|
|
|
|
|
foreach (var rule in rules)
|
|
|
|
|
{
|
2017-08-28 01:34:22 +00:00
|
|
|
|
// Checking for mod bypass here (Rule.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>
|
|
|
|
|
private async Task ProcessMessage(SocketMessage m, Rule 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
|
|
|
|
|
await Log($"{r} triggered by {m.Author.ToString()}");
|
|
|
|
|
|
|
|
|
|
foreach (Response resp in r.Response)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
}
|