2017-12-03 06:14:00 +00:00
|
|
|
|
using Discord;
|
|
|
|
|
using Discord.WebSocket;
|
2017-08-06 20:05:44 +00:00
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
using Noikoio.RegexBot.ConfigItem;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
2018-03-10 06:17:55 +00:00
|
|
|
|
namespace Noikoio.RegexBot.Module.ModCommands
|
2017-08-06 20:05:44 +00:00
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
2017-12-03 06:14:00 +00:00
|
|
|
|
/// This class manages reading configuration and creating instances based on it.
|
2018-03-10 06:17:55 +00:00
|
|
|
|
/// It processes input and looks for messages that intend to invoke commands defined in configuration.
|
2017-08-06 20:05:44 +00:00
|
|
|
|
/// </summary>
|
2018-03-10 06:17:55 +00:00
|
|
|
|
/// <remarks>
|
|
|
|
|
/// Discord.Net has its own recommended way of implementing commands, but it's not exactly
|
|
|
|
|
/// done in a way that would easily allow for flexibility and modifications during runtime.
|
|
|
|
|
/// Thus, reinventing the wheel right here.
|
|
|
|
|
/// </remarks>
|
|
|
|
|
class CommandListener : BotModule
|
2017-08-06 20:05:44 +00:00
|
|
|
|
{
|
2018-03-10 06:17:55 +00:00
|
|
|
|
public override string Name => "ModCommands";
|
2017-08-06 20:05:44 +00:00
|
|
|
|
|
2018-03-10 06:17:55 +00:00
|
|
|
|
public CommandListener(DiscordSocketClient client) : base(client)
|
2017-08-06 20:05:44 +00:00
|
|
|
|
{
|
|
|
|
|
client.MessageReceived += Client_MessageReceived;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task Client_MessageReceived(SocketMessage arg)
|
|
|
|
|
{
|
2018-03-10 06:17:55 +00:00
|
|
|
|
// Always ignore these
|
|
|
|
|
if (arg.Author.IsBot || arg.Author.IsWebhook) return;
|
2017-12-08 18:38:40 +00:00
|
|
|
|
|
2017-12-19 06:05:37 +00:00
|
|
|
|
if (arg.Channel is IGuildChannel) await CommandCheckInvoke(arg);
|
2017-08-06 20:05:44 +00:00
|
|
|
|
}
|
2017-12-08 21:57:35 +00:00
|
|
|
|
|
2018-03-10 06:17:55 +00:00
|
|
|
|
[ConfigSection("ModCommands")]
|
2017-08-06 20:05:44 +00:00
|
|
|
|
public override async Task<object> ProcessConfiguration(JToken configSection)
|
|
|
|
|
{
|
2017-12-08 21:57:35 +00:00
|
|
|
|
// Constructor throws exception on config errors
|
|
|
|
|
var conf = new ConfigItem(this, configSection);
|
2017-08-06 20:05:44 +00:00
|
|
|
|
|
2017-12-08 21:57:35 +00:00
|
|
|
|
// Log results
|
|
|
|
|
if (conf.Commands.Count > 0)
|
|
|
|
|
await Log(conf.Commands.Count + " command definition(s) loaded.");
|
2017-12-08 18:30:41 +00:00
|
|
|
|
|
2017-12-08 21:57:35 +00:00
|
|
|
|
return conf;
|
2017-08-06 20:05:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-08 21:57:35 +00:00
|
|
|
|
private new ConfigItem GetConfig(ulong guildId) => (ConfigItem)base.GetConfig(guildId);
|
2017-12-05 22:23:01 +00:00
|
|
|
|
|
2017-08-06 20:05:44 +00:00
|
|
|
|
public new Task Log(string text) => base.Log(text);
|
2017-12-03 06:14:00 +00:00
|
|
|
|
|
|
|
|
|
private async Task CommandCheckInvoke(SocketMessage arg)
|
|
|
|
|
{
|
2017-12-05 22:23:01 +00:00
|
|
|
|
SocketGuild g = ((SocketGuildUser)arg.Author).Guild;
|
2017-08-06 20:05:44 +00:00
|
|
|
|
|
|
|
|
|
// Get guild config
|
|
|
|
|
ServerConfig sc = RegexBot.Config.Servers.FirstOrDefault(s => s.Id == g.Id);
|
|
|
|
|
if (sc == null) return;
|
|
|
|
|
|
|
|
|
|
// Disregard if not a bot moderator
|
2017-08-08 19:48:30 +00:00
|
|
|
|
if (!sc.Moderators.ExistsInList(arg)) return;
|
2017-08-06 20:05:44 +00:00
|
|
|
|
|
|
|
|
|
// Disregard if the message contains a newline character
|
|
|
|
|
if (arg.Content.Contains("\n")) return;
|
|
|
|
|
|
2017-12-03 06:14:00 +00:00
|
|
|
|
// Check for and invoke command
|
2017-08-06 20:05:44 +00:00
|
|
|
|
string cmdchk;
|
|
|
|
|
int spc = arg.Content.IndexOf(' ');
|
|
|
|
|
if (spc != -1) cmdchk = arg.Content.Substring(0, spc);
|
|
|
|
|
else cmdchk = arg.Content;
|
2017-12-08 21:57:35 +00:00
|
|
|
|
if (GetConfig(g.Id).Commands.TryGetValue(cmdchk, out var c))
|
2017-08-06 20:05:44 +00:00
|
|
|
|
{
|
2017-12-03 06:14:00 +00:00
|
|
|
|
try
|
2017-08-06 20:05:44 +00:00
|
|
|
|
{
|
2017-12-03 06:14:00 +00:00
|
|
|
|
await c.Invoke(g, arg);
|
2018-03-10 06:17:55 +00:00
|
|
|
|
// TODO Custom invocation log messages? Not by the user, but by the command.
|
|
|
|
|
await Log($"{g.Name}/#{arg.Channel.Name}: {arg.Author} invoked {arg.Content}");
|
2017-12-03 06:14:00 +00:00
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2018-03-10 06:17:55 +00:00
|
|
|
|
await Log($"Encountered an unhandled exception while processing '{c.Label}'. Details follow:");
|
2017-12-03 06:14:00 +00:00
|
|
|
|
await Log(ex.ToString());
|
|
|
|
|
}
|
2017-08-06 20:05:44 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|