RegexBot/Feature/ModTools/ModTools.cs
Noikoio 3f376605f2 ModTools configuration redone
Defining config for ModTools now is similar to that of other features.

Additionally, merged the Ban and Kick commands into a single file,
and it no longer scans itself for attribute data on load.
2017-10-09 11:54:12 -07:00

89 lines
3.3 KiB
C#

using Discord.WebSocket;
using Newtonsoft.Json.Linq;
using Noikoio.RegexBot.ConfigItem;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace Noikoio.RegexBot.Feature.ModTools
{
/// <summary>
/// Entry point for the ModTools feature.
/// This feature implements moderation commands that are defined and enabled in configuration.
/// </summary>
// We are not using Discord.Net's Commands extension, as it does not allow for changes during runtime.
class ModTools : BotFeature
{
public override string Name => "ModTools";
public ModTools(DiscordSocketClient client) : base(client)
{
client.MessageReceived += Client_MessageReceived;
}
private async Task Client_MessageReceived(SocketMessage arg)
{
// Disregard if not in a guild
SocketGuild g = (arg.Author as SocketGuildUser)?.Guild;
if (g == null) return;
// Get guild config
ServerConfig sc = RegexBot.Config.Servers.FirstOrDefault(s => s.Id == g.Id);
if (sc == null) return;
// Disregard if not a bot moderator
if (!sc.Moderators.ExistsInList(arg)) return;
// Disregard if the message contains a newline character
if (arg.Content.Contains("\n")) return;
// Check for and invoke command...
string cmdchk;
int spc = arg.Content.IndexOf(' ');
if (spc != -1) cmdchk = arg.Content.Substring(0, spc);
else cmdchk = arg.Content;
if (((IDictionary<string, CommandBase>)GetConfig(g.Id)).TryGetValue(cmdchk, out var c))
{
// ...on the thread pool.
await Task.Run(async () =>
{
try
{
await Log($"'{c.Label}' invoked by {arg.Author.ToString()} in {g.Name}/#{arg.Channel.Name}");
await c.Invoke(g, arg);
}
catch (Exception ex)
{
await Log($"Encountered an error for the command '{c.Label}'. Details follow:");
await Log(ex.ToString());
}
});
}
}
[ConfigSection("modtools")]
public override async Task<object> ProcessConfiguration(JToken configSection)
{
var commands = new Dictionary<string, CommandBase>(StringComparer.OrdinalIgnoreCase);
foreach (var def in configSection.Children<JProperty>())
{
string label = def.Name;
var cmd = CommandBase.CreateInstance(this, def);
if (commands.ContainsKey(cmd.Command))
throw new RuleImportException(
$"{label}: 'command' value must not be equal to that of another definition. " +
$"Given value is being used for {commands[cmd.Command].Label}.");
commands.Add(cmd.Command, cmd);
}
await Log($"Loaded {commands.Count} command definition(s).");
return new ReadOnlyDictionary<string, CommandBase>(commands);
}
public new Task Log(string text) => base.Log(text);
}
}