Redesigned the DiscordBotCore by splitting it into multiple projects. Created a WebUI and preparing to remove the DiscordBot application

This commit is contained in:
2025-04-04 22:07:30 +03:00
parent 62ba5ec63d
commit a4afb28f36
2290 changed files with 76694 additions and 17052 deletions

View File

@@ -1,43 +1,53 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Discord.Commands;
using Discord.WebSocket;
using DiscordBotCore.Interfaces;
using DiscordBotCore.Loaders;
using DiscordBotCore.Configuration;
using DiscordBotCore.Logging;
using DiscordBotCore.Others;
using DiscordBotCore.Others.Permissions;
using DiscordBotCore.PluginCore.Helpers;
using DiscordBotCore.PluginCore.Helpers.Execution.DbCommand;
using DiscordBotCore.PluginCore.Interfaces;
using DiscordBotCore.PluginManagement.Loading;
namespace DiscordBotCore.Bot;
internal class CommandHandler
internal class CommandHandler : ICommandHandler
{
private readonly string _botPrefix;
private readonly DiscordSocketClient _client;
private readonly CommandService _commandService;
private readonly ILogger _logger;
private readonly IPluginLoader _pluginLoader;
private readonly IConfiguration _configuration;
/// <summary>
/// Command handler constructor
/// </summary>
/// <param name="client">The discord bot client</param>
/// <param name="pluginLoader">The plugin loader</param>
/// <param name="commandService">The discord bot command service</param>
/// <param name="botPrefix">The prefix to watch for</param>
public CommandHandler(DiscordSocketClient client, CommandService commandService, string botPrefix)
/// <param name="logger">The logger</param>
public CommandHandler(ILogger logger, IPluginLoader pluginLoader, IConfiguration configuration, CommandService commandService, string botPrefix)
{
_client = client;
_commandService = commandService;
_botPrefix = botPrefix;
_logger = logger;
_pluginLoader = pluginLoader;
_configuration = configuration;
}
/// <summary>
/// The method to initialize all commands
/// </summary>
/// <returns></returns>
public async Task InstallCommandsAsync()
public async Task InstallCommandsAsync(DiscordSocketClient client)
{
_client.MessageReceived += MessageHandler;
_client.SlashCommandExecuted += Client_SlashCommandExecuted;
client.MessageReceived += (message) => MessageHandler(client, message);
client.SlashCommandExecuted += Client_SlashCommandExecuted;
await _commandService.AddModulesAsync(Assembly.GetEntryAssembly(), null);
}
@@ -45,18 +55,18 @@ internal class CommandHandler
{
try
{
var plugin = PluginLoader.SlashCommands.FirstOrDefault(p => p.Name == arg.Data.Name);
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);
plugin.ExecuteDm(_logger, arg);
else plugin.ExecuteServer(_logger, arg);
}
catch (Exception ex)
{
Application.CurrentApplication.Logger.LogException(ex, this);
_logger.LogException(ex, this);
}
return Task.CompletedTask;
@@ -67,38 +77,38 @@ internal class CommandHandler
/// </summary>
/// <param name="Message">The message got from the user in discord chat</param>
/// <returns></returns>
private async Task MessageHandler(SocketMessage Message)
private async Task MessageHandler(DiscordSocketClient socketClient, SocketMessage socketMessage)
{
try
{
if (Message.Author.IsBot)
if (socketMessage.Author.IsBot)
return;
if (Message as SocketUserMessage == null)
if (socketMessage as SocketUserMessage == null)
return;
var message = Message as SocketUserMessage;
var message = socketMessage as SocketUserMessage;
if (message is null)
return;
var argPos = 0;
if (!message.Content.StartsWith(_botPrefix) && !message.HasMentionPrefix(_client.CurrentUser, ref argPos))
if (!message.Content.StartsWith(_botPrefix) && !message.HasMentionPrefix(socketClient.CurrentUser, ref argPos))
return;
var context = new SocketCommandContext(_client, message);
var context = new SocketCommandContext(socketClient, message);
await _commandService.ExecuteAsync(context, argPos, null);
IDbCommand? plugin;
var cleanMessage = "";
if (message.HasMentionPrefix(_client.CurrentUser, ref argPos))
if (message.HasMentionPrefix(socketClient.CurrentUser, ref argPos))
{
var mentionPrefix = "<@" + _client.CurrentUser.Id + ">";
var mentionPrefix = "<@" + socketClient.CurrentUser.Id + ">";
plugin = PluginLoader.Commands!
plugin = _pluginLoader.Commands!
.FirstOrDefault(plug => plug.Command ==
message.Content.Substring(mentionPrefix.Length + 1)
.Split(' ')[0] ||
@@ -114,7 +124,7 @@ internal class CommandHandler
else
{
plugin = PluginLoader.Commands!
plugin = _pluginLoader.Commands!
.FirstOrDefault(p => p.Command ==
message.Content.Split(' ')[0].Substring(_botPrefix.Length) ||
p.Aliases is not null &&
@@ -138,21 +148,26 @@ internal class CommandHandler
if (split.Length > 1)
argsClean = string.Join(' ', split, 1, split.Length - 1).Split(' ');
DbCommandExecutingArguments cmd = new(context, cleanMessage, split[0], argsClean);
DbCommandExecutingArgument cmd = new(_logger,
context,
cleanMessage,
split[0],
argsClean,
new DirectoryInfo(Path.Combine(_configuration.Get<string>("ResourcesFolder"), plugin.Command)));
Application.CurrentApplication.Logger.Log(
_logger.Log(
$"User ({context.User.Username}) from Guild \"{context.Guild.Name}\" executed command \"{cmd.CleanContent}\"",
this,
LogType.Info
);
if (context.Channel is SocketDMChannel)
plugin.ExecuteDm(cmd);
else plugin.ExecuteServer(cmd);
await plugin.ExecuteDm(cmd);
else await plugin.ExecuteServer(cmd);
}
catch (Exception ex)
{
Application.CurrentApplication.Logger.LogException(ex, this);
_logger.LogException(ex, this);
}
}
}

View File

@@ -1,57 +1,37 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using DiscordBotCore.Others;
using DiscordBotCore.Configuration;
using DiscordBotCore.Logging;
using DiscordBotCore.PluginManagement.Loading;
namespace DiscordBotCore.Bot;
public class DiscordBotApplication
public class DiscordBotApplication : IDiscordBotApplication
{
/// <summary>
/// The bot prefix
/// </summary>
private readonly string _BotPrefix;
/// <summary>
/// The bot token
/// </summary>
private readonly string _BotToken;
/// <summary>
/// The bot client
/// </summary>
public DiscordSocketClient Client;
/// <summary>
/// The bot command handler
/// </summary>
private CommandHandler _CommandServiceHandler;
/// <summary>
/// The command service
/// </summary>
private CommandService _Service;
private static readonly string _DefaultPrefix = ";";
private CommandHandler _CommandServiceHandler;
private CommandService _Service;
private readonly ILogger _Logger;
private readonly IConfiguration _Configuration;
private readonly IPluginLoader _PluginLoader;
/// <summary>
/// Checks if the bot is ready
/// </summary>
/// <value> true if the bot is ready, otherwise false </value>
private bool IsReady { get; set; }
public DiscordSocketClient Client { get; private set; }
/// <summary>
/// The main Boot constructor
/// </summary>
/// <param name="botToken">The bot token</param>
/// <param name="botPrefix">The bot prefix</param>
public DiscordBotApplication(string botToken, string botPrefix)
public DiscordBotApplication(ILogger logger, IConfiguration configuration, IPluginLoader pluginLoader)
{
this._BotPrefix = botPrefix;
this._BotToken = botToken;
this._Logger = logger;
this._Configuration = configuration;
this._PluginLoader = pluginLoader;
}
/// <summary>
@@ -68,25 +48,24 @@ public class DiscordBotApplication
GatewayIntents = GatewayIntents.All
};
Client = new DiscordSocketClient(config);
DiscordSocketClient client = new DiscordSocketClient(config);
Client = client;
_Service = new CommandService();
Client.Log += Log;
Client.LoggedIn += LoggedIn;
Client.Ready += Ready;
Client.Disconnected += Client_Disconnected;
client.Log += Log;
client.LoggedIn += LoggedIn;
client.Ready += Ready;
client.Disconnected += Client_Disconnected;
await Client.LoginAsync(TokenType.Bot, _BotToken);
await client.LoginAsync(TokenType.Bot, _Configuration.Get<string>("token"));
await Client.StartAsync();
await client.StartAsync();
_CommandServiceHandler = new CommandHandler(Client, _Service, _BotPrefix);
_CommandServiceHandler = new CommandHandler(_Logger, _PluginLoader, _Configuration, _Service, _Configuration.Get<string>("prefix", _DefaultPrefix));
await _CommandServiceHandler.InstallCommandsAsync();
Application.CurrentApplication.DiscordBotClient = this;
await _CommandServiceHandler.InstallCommandsAsync(client);
// wait for the bot to be ready
while (!IsReady)
{
await Task.Delay(100);
@@ -97,38 +76,21 @@ public class DiscordBotApplication
{
if (arg.Message.Contains("401"))
{
Application.CurrentApplication.ApplicationEnvironmentVariables.Remove("token");
Application.CurrentApplication.Logger.Log("The token is invalid.", this, LogType.Critical);
await Application.CurrentApplication.ApplicationEnvironmentVariables.SaveToFile();
_Configuration.Set("token", string.Empty);
_Logger.Log("The token is invalid.", this, LogType.Critical);
await _Configuration.SaveToFile();
}
}
private Task Ready()
{
IsReady = true;
if (Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("CustomStatus"))
{
var status = Application.CurrentApplication.ApplicationEnvironmentVariables.GetDictionary<string, string>("CustomStatus");
string type = status["Type"];
string message = status["Message"];
ActivityType activityType = type switch
{
"Playing" => ActivityType.Playing,
"Listening" => ActivityType.Listening,
"Watching" => ActivityType.Watching,
"Streaming" => ActivityType.Streaming,
_ => ActivityType.Playing
};
Client.SetGameAsync(message, null, activityType);
}
return Task.CompletedTask;
}
private Task LoggedIn()
{
Application.CurrentApplication.Logger.Log("Successfully Logged In", this);
_Logger.Log("Successfully Logged In", this);
return Task.CompletedTask;
}
@@ -138,12 +100,12 @@ public class DiscordBotApplication
{
case LogSeverity.Error:
case LogSeverity.Critical:
Application.CurrentApplication.Logger.Log(message.Message, this, LogType.Error);
_Logger.Log(message.Message, this, LogType.Error);
break;
case LogSeverity.Info:
case LogSeverity.Debug:
Application.CurrentApplication.Logger.Log(message.Message, this, LogType.Info);
_Logger.Log(message.Message, this, LogType.Info);
break;

View File

@@ -0,0 +1,13 @@
using System.Threading.Tasks;
using Discord.WebSocket;
namespace DiscordBotCore.Bot;
internal interface ICommandHandler
{
/// <summary>
/// The method to initialize all commands
/// </summary>
/// <returns></returns>
Task InstallCommandsAsync(DiscordSocketClient client);
}

View File

@@ -0,0 +1,14 @@
using System.Threading.Tasks;
using Discord.WebSocket;
namespace DiscordBotCore.Bot;
public interface IDiscordBotApplication
{
public DiscordSocketClient Client { get; }
/// <summary>
/// The start method for the bot. This method is used to load the bot
/// </summary>
Task StartAsync();
}