using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Discord.Commands;
using Discord.WebSocket;
using DiscordBotCore.Interfaces;
using DiscordBotCore.Loaders;
using DiscordBotCore.Others;
using DiscordBotCore.Others.Permissions;
namespace DiscordBotCore.Bot;
internal class CommandHandler
{
private readonly string _botPrefix;
private readonly DiscordSocketClient _client;
private readonly CommandService _commandService;
///
/// Command handler constructor
///
/// The discord bot client
/// The discord bot command service
/// The prefix to watch for
public CommandHandler(DiscordSocketClient client, CommandService commandService, string botPrefix)
{
_client = client;
_commandService = commandService;
_botPrefix = botPrefix;
}
///
/// The method to initialize all commands
///
///
public async Task InstallCommandsAsync()
{
_client.MessageReceived += MessageHandler;
_client.SlashCommandExecuted += Client_SlashCommandExecuted;
await _commandService.AddModulesAsync(Assembly.GetEntryAssembly(), null);
}
private Task Client_SlashCommandExecuted(SocketSlashCommand arg)
{
try
{
var plugin = PluginLoader.SlashCommands.FirstOrDefault(p => p.Name == arg.Data.Name);
if (plugin is null)
throw new Exception("Failed to run command !");
if (arg.Channel is SocketDMChannel)
plugin.ExecuteDM(arg);
else plugin.ExecuteServer(arg);
}
catch (Exception ex)
{
Application.CurrentApplication.Logger.LogException(ex, this);
}
return Task.CompletedTask;
}
///
/// The message handler for the bot
///
/// The message got from the user in discord chat
///
private async Task MessageHandler(SocketMessage Message)
{
try
{
if (Message.Author.IsBot)
return;
if (Message as SocketUserMessage == null)
return;
var message = Message as SocketUserMessage;
if (message is null)
return;
var argPos = 0;
if (!message.Content.StartsWith(_botPrefix) && !message.HasMentionPrefix(_client.CurrentUser, ref argPos))
return;
var context = new SocketCommandContext(_client, message);
await _commandService.ExecuteAsync(context, argPos, null);
DBCommand? plugin;
var cleanMessage = "";
if (message.HasMentionPrefix(_client.CurrentUser, ref argPos))
{
var mentionPrefix = "<@" + _client.CurrentUser.Id + ">";
plugin = PluginLoader.Commands!
.FirstOrDefault(plug => plug.Command ==
message.Content.Substring(mentionPrefix.Length + 1)
.Split(' ')[0] ||
plug.Aliases is not null &&
plug.Aliases.Contains(message.CleanContent
.Substring(mentionPrefix.Length + 1)
.Split(' ')[0]
)
);
cleanMessage = message.Content.Substring(mentionPrefix.Length + 1);
}
else
{
plugin = PluginLoader.Commands!
.FirstOrDefault(p => p.Command ==
message.Content.Split(' ')[0].Substring(_botPrefix.Length) ||
p.Aliases is not null &&
p.Aliases.Contains(
message.Content.Split(' ')[0]
.Substring(_botPrefix.Length)
)
);
cleanMessage = message.Content.Substring(_botPrefix.Length);
}
if (plugin is null)
return;
if (plugin.requireAdmin && !context.Message.Author.IsAdmin())
return;
var split = cleanMessage.Split(' ');
string[]? argsClean = null;
if (split.Length > 1)
argsClean = string.Join(' ', split, 1, split.Length - 1).Split(' ');
DbCommandExecutingArguments cmd = new(context, cleanMessage, split[0], argsClean);
Application.CurrentApplication.Logger.Log(
$"User ({context.User.Username}) from Guild \"{context.Guild.Name}\" executed command \"{cmd.cleanContent}\"",
typeof(CommandHandler),
LogType.INFO
);
if (context.Channel is SocketDMChannel)
plugin.ExecuteDM(cmd);
else plugin.ExecuteServer(cmd);
}
catch (Exception ex)
{
Application.CurrentApplication.Logger.LogException(ex, this);
}
}
}