using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using PluginManager.Interfaces;
using PluginManager.Others;
namespace PluginManager.Loaders;
public class PluginLoader
{
public delegate void CMDLoaded(string name, string typeName, bool success, Exception? e = null);
public delegate void EVELoaded(string name, string typeName, bool success, Exception? e = null);
public delegate void SLSHLoaded(string name, string tyypename, bool success, Exception? e = null);
private const string pluginFolder = @"./Data/Plugins/";
internal const string pluginExtension = "dll";
private readonly DiscordSocketClient _client;
///
/// Event that is fired when a is successfully loaded into commands list
///
public CMDLoaded? onCMDLoad;
///
/// Event that is fired when a is successfully loaded into events list
///
public EVELoaded? onEVELoad;
///
/// Event that is fired when a is successfully loaded into events list
///
public SLSHLoaded? onSLSHLoad;
///
/// The Plugin Loader constructor
///
/// The discord bot client where the plugins will pe attached to
public PluginLoader(DiscordSocketClient discordSocketClient)
{
_client = discordSocketClient;
}
///
/// A list of commands
///
public static List? Commands { get; set; }
///
/// A list of commands
///
public static List? Events { get; set; }
///
/// A list of commands
///
public static List? SlashCommands { get; set; }
public static int PluginsLoaded
{
get
{
var count = 0;
if (Commands is not null)
count += Commands.Count;
if (Events is not null)
count += Events.Count;
if (SlashCommands is not null)
count += SlashCommands.Count;
return count;
}
}
///
/// The main mathod that is called to load all events
///
public async void LoadPlugins()
{
//Load all plugins
Commands = new List();
Events = new List();
SlashCommands = new List();
Config.Logger.Log("Starting plugin loader ... Client: " + _client.CurrentUser.Username, this,
LogLevel.INFO);
var loader = new Loader("./Data/Plugins", "dll");
loader.FileLoaded += args => Config.Logger.Log($"{args.PluginName} file Loaded", this, LogLevel.INFO);
loader.PluginLoaded += Loader_PluginLoaded;
var res = loader.Load();
Events = res.Item1;
Commands = res.Item2;
SlashCommands = res.Item3;
}
private async void Loader_PluginLoaded(LoaderArgs args)
{
switch (args.TypeName)
{
case "DBCommand":
onCMDLoad?.Invoke(((DBCommand)args.Plugin!).Command, args.TypeName!, args.IsLoaded, args.Exception);
break;
case "DBEvent":
try
{
if (args.IsLoaded)
((DBEvent)args.Plugin!).Start(_client);
onEVELoad?.Invoke(((DBEvent)args.Plugin!).Name, args.TypeName!, args.IsLoaded, args.Exception);
}
catch (Exception ex)
{
Config.Logger.Log(ex.Message, this, LogLevel.ERROR);
}
break;
case "DBSlashCommand":
if (args.IsLoaded)
{
var slash = (DBSlashCommand)args.Plugin;
var builder = new SlashCommandBuilder();
builder.WithName(slash.Name);
builder.WithDescription(slash.Description);
builder.WithDMPermission(slash.canUseDM);
builder.Options = slash.Options;
onSLSHLoad?.Invoke(((DBSlashCommand)args.Plugin!).Name, args.TypeName, args.IsLoaded,
args.Exception);
await _client.CreateGlobalApplicationCommandAsync(builder.Build());
}
break;
}
}
public static async Task LoadPluginFromAssembly(Assembly asmb, DiscordSocketClient client)
{
var types = asmb.GetTypes();
foreach (var type in types)
if (type.IsClass && typeof(DBEvent).IsAssignableFrom(type))
{
var instance = (DBEvent)Activator.CreateInstance(type);
instance.Start(client);
Events.Add(instance);
Config.Logger.Log($"[EVENT] Loaded external {type.FullName}!", LogLevel.INFO);
}
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
{
var instance = (DBCommand)Activator.CreateInstance(type);
Commands.Add(instance);
Config.Logger.Log($"[CMD] Instance: {type.FullName} loaded !", LogLevel.INFO);
}
else if (type.IsClass && typeof(DBSlashCommand).IsAssignableFrom(type))
{
var instance = (DBSlashCommand)Activator.CreateInstance(type);
var builder = new SlashCommandBuilder();
builder.WithName(instance.Name);
builder.WithDescription(instance.Description);
builder.WithDMPermission(instance.canUseDM);
builder.Options = instance.Options;
await client.CreateGlobalApplicationCommandAsync(builder.Build());
SlashCommands.Add(instance);
Config.Logger.Log($"[SLASH] Instance: {type.FullName} loaded !", LogLevel.INFO);
}
}
}