Redesigned the DiscordBotCore by splitting it into multiple projects. Created a WebUI and preparing to remove the DiscordBot application
This commit is contained in:
192
DiscordBotCore.PluginManagement.Loading/PluginLoader.cs
Normal file
192
DiscordBotCore.PluginManagement.Loading/PluginLoader.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
using System.Net.Mime;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using DiscordBotCore.Configuration;
|
||||
using DiscordBotCore.Logging;
|
||||
using DiscordBotCore.PluginCore;
|
||||
using DiscordBotCore.PluginCore.Helpers;
|
||||
using DiscordBotCore.PluginCore.Helpers.Execution.DbEvent;
|
||||
using DiscordBotCore.PluginCore.Interfaces;
|
||||
using DiscordBotCore.Utilities;
|
||||
|
||||
namespace DiscordBotCore.PluginManagement.Loading;
|
||||
|
||||
public sealed class PluginLoader : IPluginLoader
|
||||
{
|
||||
private readonly DiscordSocketClient _DiscordClient;
|
||||
private readonly IPluginManager _PluginManager;
|
||||
private readonly ILogger _Logger;
|
||||
private readonly IConfiguration _Configuration;
|
||||
|
||||
public delegate void CommandLoaded(IDbCommand eCommand);
|
||||
public delegate void EventLoaded(IDbEvent eEvent);
|
||||
public delegate void SlashCommandLoaded(IDbSlashCommand eSlashCommand);
|
||||
|
||||
public CommandLoaded? OnCommandLoaded;
|
||||
public EventLoaded? OnEventLoaded;
|
||||
public SlashCommandLoaded? OnSlashCommandLoaded;
|
||||
|
||||
public List<IDbCommand> Commands { get; private set; } = new List<IDbCommand>();
|
||||
public List<IDbEvent> Events { get; private set; } = new List<IDbEvent>();
|
||||
public List<IDbSlashCommand> SlashCommands { get; private set; } = new List<IDbSlashCommand>();
|
||||
|
||||
public PluginLoader(IPluginManager pluginManager, ILogger logger, IConfiguration configuration, DiscordSocketClient discordSocketDiscordClient)
|
||||
{
|
||||
_PluginManager = pluginManager;
|
||||
_DiscordClient = discordSocketDiscordClient;
|
||||
_Logger = logger;
|
||||
_Configuration = configuration;
|
||||
}
|
||||
|
||||
public async Task LoadPlugins()
|
||||
{
|
||||
Commands.Clear();
|
||||
Events.Clear();
|
||||
SlashCommands.Clear();
|
||||
|
||||
_Logger.Log("Loading plugins...", this);
|
||||
|
||||
var loader = new Loader(_PluginManager);
|
||||
|
||||
loader.OnFileLoadedException += FileLoadedException;
|
||||
loader.OnPluginLoaded += OnPluginLoaded;
|
||||
|
||||
await loader.Load();
|
||||
}
|
||||
|
||||
private void FileLoadedException(string fileName, Exception exception)
|
||||
{
|
||||
_Logger.LogException(exception, this);
|
||||
}
|
||||
|
||||
private void InitializeDbCommand(IDbCommand command)
|
||||
{
|
||||
Commands.Add(command);
|
||||
OnCommandLoaded?.Invoke(command);
|
||||
}
|
||||
|
||||
private void InitializeEvent(IDbEvent eEvent)
|
||||
{
|
||||
if (!TryStartEvent(eEvent))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Events.Add(eEvent);
|
||||
OnEventLoaded?.Invoke(eEvent);
|
||||
}
|
||||
|
||||
private async void InitializeSlashCommand(IDbSlashCommand slashCommand)
|
||||
{
|
||||
Result result = await TryStartSlashCommand(slashCommand);
|
||||
result.Match(
|
||||
() =>
|
||||
{
|
||||
if (slashCommand.HasInteraction)
|
||||
_DiscordClient.InteractionCreated += interaction => slashCommand.ExecuteInteraction(_Logger, interaction);
|
||||
SlashCommands.Add(slashCommand);
|
||||
OnSlashCommandLoaded?.Invoke(slashCommand);
|
||||
},
|
||||
HandleError
|
||||
);
|
||||
}
|
||||
|
||||
private void HandleError(Exception exception)
|
||||
{
|
||||
_Logger.LogException(exception, this);
|
||||
}
|
||||
|
||||
private void OnPluginLoaded(PluginLoaderResult result)
|
||||
{
|
||||
result.Match(
|
||||
InitializeDbCommand,
|
||||
InitializeEvent,
|
||||
InitializeSlashCommand,
|
||||
HandleError
|
||||
);
|
||||
}
|
||||
|
||||
private bool TryStartEvent(IDbEvent? dbEvent)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (dbEvent is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dbEvent));
|
||||
}
|
||||
IDbEventExecutingArgument args = new DbEventExecutingArgument(
|
||||
_Logger,
|
||||
_DiscordClient,
|
||||
_Configuration.Get<string>("prefix"),
|
||||
new DirectoryInfo(Path.Combine(_Configuration.Get<string>("ResourcesPath"), dbEvent.Name)));
|
||||
dbEvent.Start(args);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_Logger.Log($"Error starting event {dbEvent.Name}: {e.Message}", typeof(PluginLoader), LogType.Error);
|
||||
_Logger.LogException(e, typeof(PluginLoader));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Result> TryStartSlashCommand(IDbSlashCommand? dbSlashCommand)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (dbSlashCommand is null)
|
||||
{
|
||||
return Result.Failure(new Exception("dbSlashCommand is null"));
|
||||
}
|
||||
|
||||
if (_DiscordClient.Guilds.Count == 0)
|
||||
{
|
||||
return Result.Failure(new Exception("No guilds found"));
|
||||
}
|
||||
|
||||
var builder = new SlashCommandBuilder();
|
||||
builder.WithName(dbSlashCommand.Name);
|
||||
builder.WithDescription(dbSlashCommand.Description);
|
||||
builder.Options = dbSlashCommand.Options;
|
||||
|
||||
if (dbSlashCommand.CanUseDm)
|
||||
builder.WithContextTypes(InteractionContextType.BotDm, InteractionContextType.Guild);
|
||||
else
|
||||
builder.WithContextTypes(InteractionContextType.Guild);
|
||||
|
||||
List<ulong> serverIds = _Configuration.GetList("ServerIds", new List<ulong>());
|
||||
|
||||
foreach(ulong guildId in serverIds)
|
||||
{
|
||||
bool result = await EnableSlashCommandPerGuild(guildId, builder);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
return Result.Failure($"Failed to enable slash command {dbSlashCommand.Name} for guild {guildId}");
|
||||
}
|
||||
}
|
||||
|
||||
await _DiscordClient.CreateGlobalApplicationCommandAsync(builder.Build());
|
||||
|
||||
return Result.Success();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Result.Failure("Error starting slash command");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> EnableSlashCommandPerGuild(ulong guildId, SlashCommandBuilder builder)
|
||||
{
|
||||
SocketGuild? guild = _DiscordClient.GetGuild(guildId);
|
||||
if (guild is null)
|
||||
{
|
||||
_Logger.Log("Failed to get guild with ID " + guildId, typeof(PluginLoader), LogType.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
await guild.CreateApplicationCommandAsync(builder.Build());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user