Reworked the plugin loader
This commit is contained in:
@@ -1,60 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
using DiscordBotCore;
|
|
||||||
using DiscordBotCore.Interfaces;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
using DiscordBotCore.Plugin;
|
|
||||||
|
|
||||||
namespace DiscordBot.Bot.Actions
|
|
||||||
{
|
|
||||||
internal class AddPlugin : ICommandAction
|
|
||||||
{
|
|
||||||
public string ActionName => "add-plugin";
|
|
||||||
|
|
||||||
public string Description => "Add a local plugin to the database";
|
|
||||||
|
|
||||||
public string Usage => "add-plugin <options> <fileName>";
|
|
||||||
|
|
||||||
public IEnumerable<InternalActionOption> ListOfOptions => [
|
|
||||||
new InternalActionOption("options", "Available options", [
|
|
||||||
new InternalActionOption("-enabled", "Enable the plugin"),
|
|
||||||
]),
|
|
||||||
new InternalActionOption("fileName", "The file name")
|
|
||||||
];
|
|
||||||
|
|
||||||
public InternalActionRunType RunType => InternalActionRunType.OnCall;
|
|
||||||
|
|
||||||
public bool RequireOtherThread => false;
|
|
||||||
|
|
||||||
public async Task Execute(string[] args)
|
|
||||||
{
|
|
||||||
if(args.Length < 1)
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log("Incorrect number of arguments !", LogType.Warning);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string fileName = args[^1] + ".dll";
|
|
||||||
var path = Application.GetPluginFullPath(fileName);
|
|
||||||
|
|
||||||
if(!File.Exists(path))
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log("The file does not exist !!", LogType.Error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args[^1] is null)
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log("The plugin name is invalid", LogType.Error);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginInfo pluginInfo = new PluginInfo(args[^1], "1.0.0", [], false, true, args.Contains("-enabled"));
|
|
||||||
Application.CurrentApplication.Logger.Log("Adding plugin: " + args[^1]);
|
|
||||||
await Application.CurrentApplication.PluginManager.AppendPluginToDatabase(pluginInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using DiscordBotCore.Interfaces;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
|
|
||||||
namespace DiscordBot.Bot.Actions;
|
|
||||||
|
|
||||||
public class Clear: ICommandAction
|
|
||||||
{
|
|
||||||
public string ActionName => "clear";
|
|
||||||
public string Description => "Clears the console";
|
|
||||||
public string Usage => "clear";
|
|
||||||
public IEnumerable<InternalActionOption> ListOfOptions => [];
|
|
||||||
|
|
||||||
public InternalActionRunType RunType => InternalActionRunType.OnCall;
|
|
||||||
|
|
||||||
public bool RequireOtherThread => false;
|
|
||||||
|
|
||||||
public Task Execute(string[] args)
|
|
||||||
{
|
|
||||||
Console.Clear();
|
|
||||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
|
||||||
Console.WriteLine("===== Seth Discord Bot =====");
|
|
||||||
Console.ResetColor();
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using DiscordBotCore;
|
|
||||||
using DiscordBotCore.Interfaces;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
|
|
||||||
namespace DiscordBot.Bot.Actions;
|
|
||||||
|
|
||||||
public class Exit: ICommandAction
|
|
||||||
{
|
|
||||||
public string ActionName => "exit";
|
|
||||||
public string Description => "Exits the bot and saves the config. Use exit help for more info.";
|
|
||||||
public string Usage => "exit <option?>";
|
|
||||||
public IEnumerable<InternalActionOption> ListOfOptions => new List<InternalActionOption>
|
|
||||||
{
|
|
||||||
new InternalActionOption("help", "Displays this message"),
|
|
||||||
new InternalActionOption("force | -f", "Exits the bot without saving the config")
|
|
||||||
};
|
|
||||||
public InternalActionRunType RunType => InternalActionRunType.OnCall;
|
|
||||||
|
|
||||||
public bool RequireOtherThread => false;
|
|
||||||
|
|
||||||
public async Task Execute(string[] args)
|
|
||||||
{
|
|
||||||
if (args is null || args.Length == 0)
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log("Exiting...", this, LogType.Warning);
|
|
||||||
await Application.CurrentApplication.ApplicationEnvironmentVariables.SaveToFile();
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (args[0])
|
|
||||||
{
|
|
||||||
case "help":
|
|
||||||
Console.WriteLine("Usage : exit [help|force]");
|
|
||||||
Console.WriteLine("help : Displays this message");
|
|
||||||
Console.WriteLine("force | -f : Exits the bot without saving the config");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "-f":
|
|
||||||
case "force":
|
|
||||||
Application.CurrentApplication.Logger.Log("Exiting (FORCE)...", this, LogType.Warning);
|
|
||||||
Environment.Exit(0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
Console.WriteLine("Invalid argument !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
using DiscordBot.Utilities;
|
|
||||||
|
|
||||||
using DiscordBotCore;
|
|
||||||
using DiscordBotCore.Loaders;
|
|
||||||
using DiscordBotCore.Online;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
using DiscordBotCore.Plugin;
|
|
||||||
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace DiscordBot.Bot.Actions.Extra;
|
|
||||||
|
|
||||||
internal static class PluginMethods
|
|
||||||
{
|
|
||||||
|
|
||||||
internal static async Task List()
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Fetching plugin list ...");
|
|
||||||
|
|
||||||
var onlinePlugins = await ConsoleUtilities.ExecuteWithProgressBar(Application.CurrentApplication.PluginManager.GetPluginsList(), "Reading remote database");
|
|
||||||
var installedPlugins = await ConsoleUtilities.ExecuteWithProgressBar(Application.CurrentApplication.PluginManager.GetInstalledPlugins(), "Reading local database ");
|
|
||||||
TableData tableData = new(["Name", "Description", "Author", "Latest Version", "Installed Version"]);
|
|
||||||
|
|
||||||
foreach (var onlinePlugin in onlinePlugins)
|
|
||||||
{
|
|
||||||
bool isInstalled = installedPlugins.Any(p => p.PluginName == onlinePlugin.PluginName);
|
|
||||||
tableData.AddRow([
|
|
||||||
onlinePlugin.PluginName,
|
|
||||||
onlinePlugin.PluginDescription,
|
|
||||||
onlinePlugin.PluginAuthor,
|
|
||||||
onlinePlugin.LatestVersion,
|
|
||||||
isInstalled ? installedPlugins.First(p => p.PluginName == onlinePlugin.PluginName).PluginVersion : "Not Installed"
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
tableData.HasRoundBorders = false;
|
|
||||||
tableData.DisplayLinesBetweenRows = true;
|
|
||||||
tableData.PrintTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static async Task RefreshPlugins(bool quiet)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await LoadPlugins(quiet ? ["-q"] : null);
|
|
||||||
|
|
||||||
}catch(Exception ex)
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.LogException(ex, typeof(PluginMethods), false);
|
|
||||||
} finally
|
|
||||||
{
|
|
||||||
await Application.CurrentApplication.InternalActionManager.Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static async Task DisablePlugin(string pluginName)
|
|
||||||
{
|
|
||||||
await Application.CurrentApplication.PluginManager.SetEnabledStatus(pluginName, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static async Task EnablePlugin(string pluginName)
|
|
||||||
{
|
|
||||||
await Application.CurrentApplication.PluginManager.SetEnabledStatus(pluginName, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task DownloadPluginWithParallelDownloads(string pluginName)
|
|
||||||
{
|
|
||||||
OnlinePlugin? pluginData = await Application.CurrentApplication.PluginManager.GetPluginDataByName(pluginName);
|
|
||||||
|
|
||||||
if (pluginData is null)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Plugin {pluginName} not found. Please check the spelling and try again.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = await Application.CurrentApplication.PluginManager.GatherInstallDataForPlugin(pluginData);
|
|
||||||
List<Tuple<string, string>> downloadList = result.Item1.Select(kvp => new Tuple<string, string>(kvp.Key, kvp.Value)).ToList();
|
|
||||||
|
|
||||||
await ConsoleUtilities.ExecuteParallelDownload(FileDownloader.CreateDownloadTask, new HttpClient(), downloadList, "Downloading:");
|
|
||||||
|
|
||||||
await Application.CurrentApplication.PluginManager.AppendPluginToDatabase(PluginInfo.FromOnlineInfo(pluginData, result.Item2));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
internal static async Task<bool> LoadPlugins(string[] args)
|
|
||||||
{
|
|
||||||
var loader = new PluginLoader(Application.CurrentApplication.DiscordBotClient.Client);
|
|
||||||
if (args != null && args.Contains("-q"))
|
|
||||||
{
|
|
||||||
await loader.LoadPlugins();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
loader.OnCommandLoaded += (command) =>
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log($"Command {command.Command} loaded successfully", LogType.Info);
|
|
||||||
};
|
|
||||||
|
|
||||||
loader.OnEventLoaded += (eEvent) =>
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log($"Event {eEvent.Name} loaded successfully",LogType.Info);
|
|
||||||
};
|
|
||||||
|
|
||||||
loader.OnActionLoaded += (action) =>
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log($"Action {action.ActionName} loaded successfully", LogType.Info);
|
|
||||||
};
|
|
||||||
|
|
||||||
loader.OnSlashCommandLoaded += (slashCommand) =>
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log($"Slash Command {slashCommand.Name} loaded successfully", LogType.Info);
|
|
||||||
};
|
|
||||||
|
|
||||||
await loader.LoadPlugins();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using DiscordBotCore;
|
|
||||||
|
|
||||||
namespace DiscordBot.Bot.Actions.Extra;
|
|
||||||
|
|
||||||
internal static class SettingsConfigExtra
|
|
||||||
{
|
|
||||||
|
|
||||||
internal static void SetSettings(string key, params string[] value)
|
|
||||||
{
|
|
||||||
if (key is null) return;
|
|
||||||
|
|
||||||
if (value is null) return;
|
|
||||||
|
|
||||||
if (!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey(key))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Application.CurrentApplication.ApplicationEnvironmentVariables.Add(key, string.Join(' ', value));
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void RemoveSettings(string key)
|
|
||||||
{
|
|
||||||
if (key is null) return;
|
|
||||||
|
|
||||||
if (!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey(key))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Application.CurrentApplication.ApplicationEnvironmentVariables.Remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void AddSettings(string key, params string[] value)
|
|
||||||
{
|
|
||||||
if (key is null) return;
|
|
||||||
|
|
||||||
if (value is null) return;
|
|
||||||
|
|
||||||
if (Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey(key))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Application.CurrentApplication.ApplicationEnvironmentVariables.Add(key, string.Join(' ', value));
|
|
||||||
// Config.Application.CurrentApplication.ApplicationEnvironmentVariables.SaveToFile().Wait();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using DiscordBot.Utilities;
|
|
||||||
|
|
||||||
using DiscordBotCore;
|
|
||||||
using DiscordBotCore.Interfaces;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace DiscordBot.Bot.Actions;
|
|
||||||
|
|
||||||
public class Help: ICommandAction
|
|
||||||
{
|
|
||||||
public string ActionName => "help";
|
|
||||||
|
|
||||||
public string Description => "Shows the list of commands and their usage";
|
|
||||||
|
|
||||||
public string Usage => "help <command?>";
|
|
||||||
|
|
||||||
public IEnumerable<InternalActionOption> ListOfOptions => [
|
|
||||||
new InternalActionOption("command", "The command to get help for")
|
|
||||||
];
|
|
||||||
|
|
||||||
public InternalActionRunType RunType => InternalActionRunType.OnCall;
|
|
||||||
|
|
||||||
public bool RequireOtherThread => false;
|
|
||||||
|
|
||||||
public async Task Execute(string[] args)
|
|
||||||
{
|
|
||||||
TableData tableData = new TableData();
|
|
||||||
|
|
||||||
if (args == null || args.Length == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
AnsiConsole.MarkupLine("[bold][green]Please make this window full screen to check all the commands.[/][/]");
|
|
||||||
|
|
||||||
tableData.Columns = ["Command", "Usage", "Description", "Options"];
|
|
||||||
|
|
||||||
foreach (var a in Application.CurrentApplication.InternalActionManager.GetActions())
|
|
||||||
{
|
|
||||||
Markup actionName = new Markup($"[bold]{a.ActionName}[/]");
|
|
||||||
Markup usage = new Markup($"[italic]{a.Usage}[/]");
|
|
||||||
Markup description = new Markup($"[dim]{a.Description}[/]");
|
|
||||||
|
|
||||||
if (a.ListOfOptions.Any())
|
|
||||||
{
|
|
||||||
tableData.AddRow([actionName, usage, description, CreateTableWithSubOptions(a.ListOfOptions)]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tableData.AddRow([actionName, usage, description]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// render the table
|
|
||||||
tableData.HasRoundBorders = true;
|
|
||||||
tableData.DisplayLinesBetweenRows = true;
|
|
||||||
tableData.PrintTable();
|
|
||||||
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Application.CurrentApplication.InternalActionManager.Exists(args[0]))
|
|
||||||
{
|
|
||||||
Console.WriteLine("Command not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var action = Application.CurrentApplication.InternalActionManager.GetAction(args[0]);
|
|
||||||
tableData.Columns = ["Command", "Usage", "Description"];
|
|
||||||
tableData.AddRow([action.ActionName, action.Usage, action.Description]);
|
|
||||||
|
|
||||||
|
|
||||||
tableData.PrintTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Table CreateTableWithSubOptions(IEnumerable<InternalActionOption> options)
|
|
||||||
{
|
|
||||||
var tableData = new TableData();
|
|
||||||
tableData.Columns = ["Option", "Description", "SubOptions"];
|
|
||||||
|
|
||||||
foreach (var option in options)
|
|
||||||
{
|
|
||||||
|
|
||||||
Markup optionName = new Markup($"{option.OptionName}");
|
|
||||||
Markup description = new Markup($"{option.OptionDescription}");
|
|
||||||
|
|
||||||
if(option.SubOptions.Any())
|
|
||||||
{
|
|
||||||
tableData.AddRow([optionName, description, CreateTableWithSubOptions(option.SubOptions)]);
|
|
||||||
|
|
||||||
}else {
|
|
||||||
tableData.AddRow([optionName, description]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return tableData.AsTable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using DiscordBot.Bot.Actions.Extra;
|
|
||||||
using DiscordBotCore;
|
|
||||||
using DiscordBotCore.Interfaces;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
|
|
||||||
namespace DiscordBot.Bot.Actions;
|
|
||||||
|
|
||||||
public class Plugin: ICommandAction
|
|
||||||
{
|
|
||||||
private bool pluginsLoaded;
|
|
||||||
public string ActionName => "plugin";
|
|
||||||
public string Description => "Manages plugins. Use plugin help for more info.";
|
|
||||||
public string Usage => "plugin <option!>";
|
|
||||||
|
|
||||||
public IEnumerable<InternalActionOption> ListOfOptions => new List<InternalActionOption>
|
|
||||||
{
|
|
||||||
new InternalActionOption("help", "Displays this message"),
|
|
||||||
new InternalActionOption("list", "Lists all plugins"),
|
|
||||||
new InternalActionOption("load", "Loads all plugins"),
|
|
||||||
new InternalActionOption("install", "Installs a plugin", [
|
|
||||||
new InternalActionOption("name", "The name of the plugin to install")
|
|
||||||
]),
|
|
||||||
new InternalActionOption("refresh", "Refreshes the plugin list"),
|
|
||||||
new InternalActionOption("uninstall", "Uninstalls a plugin"),
|
|
||||||
new InternalActionOption("branch", "Sets a plugin option", [
|
|
||||||
new InternalActionOption("set", "Sets the branch"),
|
|
||||||
new InternalActionOption("get", "Gets the branch")
|
|
||||||
]),
|
|
||||||
new InternalActionOption("enable", "Enables a plugin", [
|
|
||||||
new InternalActionOption("name", "The name of the plugin to enable")
|
|
||||||
]),
|
|
||||||
new InternalActionOption("disable", "Disables a plugin", [
|
|
||||||
new InternalActionOption("name", "The name of the plugin to disable")
|
|
||||||
])
|
|
||||||
};
|
|
||||||
|
|
||||||
public InternalActionRunType RunType => InternalActionRunType.OnCall;
|
|
||||||
|
|
||||||
public bool RequireOtherThread => false;
|
|
||||||
|
|
||||||
public async Task Execute(string[] args)
|
|
||||||
{
|
|
||||||
if (args is null || args.Length == 0)
|
|
||||||
{
|
|
||||||
await Application.CurrentApplication.InternalActionManager.Execute("help", ActionName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (args[0])
|
|
||||||
{
|
|
||||||
case "enable":
|
|
||||||
{
|
|
||||||
if (args.Length < 2)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Usage : plugin enable <plugin name>");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string pluginName = string.Join(' ', args, 1, args.Length - 1);
|
|
||||||
await PluginMethods.EnablePlugin(pluginName);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "disable":
|
|
||||||
{
|
|
||||||
if (args.Length < 2)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Usage : plugin disable <plugin name>");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string pluginName = string.Join(' ', args, 1, args.Length - 1);
|
|
||||||
await PluginMethods.DisablePlugin(pluginName);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "refresh":
|
|
||||||
await PluginMethods.RefreshPlugins(true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "uninstall":
|
|
||||||
{
|
|
||||||
string plugName = string.Join(' ', args, 1, args.Length - 1);
|
|
||||||
bool result = await Application.CurrentApplication.PluginManager.MarkPluginToUninstall(plugName);
|
|
||||||
if (result)
|
|
||||||
Console.WriteLine($"Marked to uninstall plugin {plugName}. Please restart the bot");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "list":
|
|
||||||
await PluginMethods.List();
|
|
||||||
break;
|
|
||||||
case "load":
|
|
||||||
if (pluginsLoaded)
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log("Plugins already loaded", this, LogType.Warning);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pluginsLoaded = await PluginMethods.LoadPlugins(args);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "install":
|
|
||||||
{
|
|
||||||
var pluginName = string.Join(' ', args, 1, args.Length - 1);
|
|
||||||
if (string.IsNullOrEmpty(pluginName) || pluginName.Length < 2)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Please specify a plugin name");
|
|
||||||
Console.Write("Plugin name : ");
|
|
||||||
pluginName = Console.ReadLine();
|
|
||||||
if (string.IsNullOrEmpty(pluginName) || pluginName.Length < 2)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Invalid plugin name");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await PluginMethods.DownloadPluginWithParallelDownloads(pluginName);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,161 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using DiscordBot.Bot.Actions.Extra;
|
|
||||||
using DiscordBotCore;
|
|
||||||
using DiscordBotCore.Interfaces;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
|
|
||||||
namespace DiscordBot.Bot.Actions;
|
|
||||||
|
|
||||||
public class SettingsConfig: ICommandAction
|
|
||||||
{
|
|
||||||
public string ActionName => "config";
|
|
||||||
public string Description => "Change the settings of the bot";
|
|
||||||
public string Usage => "config <options!>";
|
|
||||||
|
|
||||||
public IEnumerable<InternalActionOption> ListOfOptions => new List<InternalActionOption>
|
|
||||||
{
|
|
||||||
new InternalActionOption("help", "Displays this message"),
|
|
||||||
new InternalActionOption("set", "Set a setting"),
|
|
||||||
new InternalActionOption("remove", "Remove a setting"),
|
|
||||||
new InternalActionOption("add", "Add a setting")
|
|
||||||
};
|
|
||||||
|
|
||||||
public InternalActionRunType RunType => InternalActionRunType.OnCall;
|
|
||||||
|
|
||||||
public bool RequireOtherThread => false;
|
|
||||||
|
|
||||||
public Task Execute(string[] args)
|
|
||||||
{
|
|
||||||
if (args is null)
|
|
||||||
{
|
|
||||||
PrintAllSettings();
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (args[0])
|
|
||||||
{
|
|
||||||
case "-s":
|
|
||||||
case "set":
|
|
||||||
if (args.Length < 3)
|
|
||||||
return Task.CompletedTask;
|
|
||||||
SettingsConfigExtra.SetSettings(args[1], args[2..]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "-r":
|
|
||||||
case "remove":
|
|
||||||
if (args.Length < 2)
|
|
||||||
return Task.CompletedTask;
|
|
||||||
SettingsConfigExtra.RemoveSettings(args[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "-a":
|
|
||||||
case "add":
|
|
||||||
if (args.Length < 3)
|
|
||||||
return Task.CompletedTask;
|
|
||||||
SettingsConfigExtra.AddSettings(args[1], args[2..]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "-h":
|
|
||||||
case "help":
|
|
||||||
Console.WriteLine("Options:");
|
|
||||||
Console.WriteLine("-s <settingName> <newValue>: Set a setting");
|
|
||||||
Console.WriteLine("-r <settingName>: Remove a setting");
|
|
||||||
Console.WriteLine("-a <settingName> <newValue>: Add a setting");
|
|
||||||
Console.WriteLine("-h: Show this help message");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
Console.WriteLine("Invalid option");
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
private void PrintList(IList<object> list, int indentLevel)
|
|
||||||
{
|
|
||||||
bool isListOfDictionaries = list.All(item => item is IDictionary<string, object>);
|
|
||||||
|
|
||||||
if (isListOfDictionaries)
|
|
||||||
{
|
|
||||||
foreach (var item in list)
|
|
||||||
{
|
|
||||||
if (item is IDictionary<string, object> dict)
|
|
||||||
{
|
|
||||||
PrintDictionary(dict, indentLevel + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PrintIndent(indentLevel);
|
|
||||||
Console.WriteLine(string.Join(",", list));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PrintDictionary(IDictionary<string, object> dictionary, int indentLevel)
|
|
||||||
{
|
|
||||||
foreach (var kvp in dictionary)
|
|
||||||
{
|
|
||||||
PrintIndent(indentLevel);
|
|
||||||
Console.Write(kvp.Key + ": ");
|
|
||||||
|
|
||||||
var value = kvp.Value;
|
|
||||||
if (value is IDictionary<string, object> dict)
|
|
||||||
{
|
|
||||||
Console.WriteLine();
|
|
||||||
PrintDictionary(dict, indentLevel + 1);
|
|
||||||
}
|
|
||||||
else if (value is IList<object> list)
|
|
||||||
{
|
|
||||||
if (list.All(item => item is IDictionary<string, object>))
|
|
||||||
{
|
|
||||||
Console.WriteLine();
|
|
||||||
PrintList(list, indentLevel + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PrintList(list, indentLevel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PrintIndent(int indentLevel)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < indentLevel; i++)
|
|
||||||
{
|
|
||||||
Console.Write(" "); // Two spaces for each indentation level
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PrintAllSettings()
|
|
||||||
{
|
|
||||||
var settings = Application.CurrentApplication.ApplicationEnvironmentVariables;
|
|
||||||
foreach (var setting in settings)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Setting: " + setting.Key);
|
|
||||||
if (setting.Value is IDictionary<string, object> dict)
|
|
||||||
{
|
|
||||||
PrintDictionary(dict, 1);
|
|
||||||
}
|
|
||||||
else if (setting.Value is IList<object> list)
|
|
||||||
{
|
|
||||||
PrintList(list, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine(setting.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using Discord;
|
|
||||||
using DiscordBotCore;
|
|
||||||
using DiscordBotCore.Interfaces;
|
|
||||||
using DiscordBotCore.Loaders;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
|
|
||||||
namespace DiscordBot.Bot.Commands;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The help command
|
|
||||||
/// </summary>
|
|
||||||
internal class Help: IDbCommand
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Command name
|
|
||||||
/// </summary>
|
|
||||||
public string Command => "help";
|
|
||||||
|
|
||||||
public List<string> Aliases => null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command Description
|
|
||||||
/// </summary>
|
|
||||||
public string Description => "This command allows you to check all loaded commands";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command usage
|
|
||||||
/// </summary>
|
|
||||||
public string Usage => "help <command>";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Check if the command require administrator to be executed
|
|
||||||
/// </summary>
|
|
||||||
public bool RequireAdmin => false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The main body of the command
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">The command context</param>
|
|
||||||
public void ExecuteServer(DbCommandExecutingArguments args)
|
|
||||||
{
|
|
||||||
if (args.Arguments is not null)
|
|
||||||
{
|
|
||||||
var e = GenerateHelpCommand(args.Arguments[0]);
|
|
||||||
if (e is null)
|
|
||||||
args.Context.Channel.SendMessageAsync("Unknown Command " + args.Arguments[0]);
|
|
||||||
else
|
|
||||||
args.Context.Channel.SendMessageAsync(embed: e.Build());
|
|
||||||
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var embedBuilder = new EmbedBuilder();
|
|
||||||
|
|
||||||
var adminCommands = "";
|
|
||||||
var normalCommands = "";
|
|
||||||
|
|
||||||
foreach (var cmd in PluginLoader.Commands)
|
|
||||||
if (cmd.RequireAdmin)
|
|
||||||
adminCommands += cmd.Command + " ";
|
|
||||||
else
|
|
||||||
normalCommands += cmd.Command + " ";
|
|
||||||
|
|
||||||
|
|
||||||
if (adminCommands.Length > 0)
|
|
||||||
embedBuilder.AddField("Admin Commands", adminCommands);
|
|
||||||
if (normalCommands.Length > 0)
|
|
||||||
embedBuilder.AddField("Normal Commands", normalCommands);
|
|
||||||
args.Context.Channel.SendMessageAsync(embed: embedBuilder.Build());
|
|
||||||
}
|
|
||||||
|
|
||||||
private EmbedBuilder GenerateHelpCommand(string command)
|
|
||||||
{
|
|
||||||
var embedBuilder = new EmbedBuilder();
|
|
||||||
var cmd = PluginLoader.Commands.Find(p => p.Command == command ||
|
|
||||||
p.Aliases is not null && p.Aliases.Contains(command)
|
|
||||||
);
|
|
||||||
if (cmd == null) return null;
|
|
||||||
|
|
||||||
string prefix = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("prefix");
|
|
||||||
|
|
||||||
embedBuilder.AddField("Usage", prefix + cmd.Usage);
|
|
||||||
embedBuilder.AddField("Description", cmd.Description);
|
|
||||||
if (cmd.Aliases is null)
|
|
||||||
return embedBuilder;
|
|
||||||
embedBuilder.AddField("Alias", cmd.Aliases.Count == 0 ? "-" : string.Join(", ", cmd.Aliases));
|
|
||||||
|
|
||||||
return embedBuilder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Discord;
|
|
||||||
using Discord.WebSocket;
|
|
||||||
using DiscordBotCore.Interfaces;
|
|
||||||
using DiscordBotCore.Loaders;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
|
|
||||||
namespace DiscordBot.Bot.Commands.SlashCommands;
|
|
||||||
|
|
||||||
public class Help: IDbSlashCommand
|
|
||||||
{
|
|
||||||
public string Name => "help";
|
|
||||||
public string Description => "This command allows you to check all loaded commands";
|
|
||||||
public bool CanUseDm => true;
|
|
||||||
|
|
||||||
public bool HasInteraction => false;
|
|
||||||
|
|
||||||
public List<SlashCommandOptionBuilder> Options =>
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
new SlashCommandOptionBuilder()
|
|
||||||
.WithName("command")
|
|
||||||
.WithDescription("The command you want to get help for")
|
|
||||||
.WithRequired(false)
|
|
||||||
.WithType(ApplicationCommandOptionType.String)
|
|
||||||
};
|
|
||||||
|
|
||||||
public async void ExecuteServer(SocketSlashCommand context)
|
|
||||||
{
|
|
||||||
EmbedBuilder embedBuilder = new();
|
|
||||||
|
|
||||||
embedBuilder.WithTitle("Help Command");
|
|
||||||
|
|
||||||
var random = new Random();
|
|
||||||
Color c = new Color(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255));
|
|
||||||
|
|
||||||
embedBuilder.WithColor(c);
|
|
||||||
var slashCommands = PluginLoader.SlashCommands;
|
|
||||||
var options = context.Data.Options;
|
|
||||||
|
|
||||||
//Console.WriteLine("Options: " + options.Count);
|
|
||||||
if (options is null || options.Count == 0)
|
|
||||||
foreach (var slashCommand in slashCommands)
|
|
||||||
embedBuilder.AddField(slashCommand.Name, slashCommand.Description);
|
|
||||||
|
|
||||||
if (options.Count > 0)
|
|
||||||
{
|
|
||||||
var commandName = options.First().Value;
|
|
||||||
var slashCommand = slashCommands.FirstOrDefault(x => x.Name.TrimEnd() == commandName.ToString());
|
|
||||||
if (slashCommand is null)
|
|
||||||
{
|
|
||||||
await context.RespondAsync("Unknown Command " + commandName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
embedBuilder.AddField("DM Usable:", slashCommand.CanUseDm, true)
|
|
||||||
.WithDescription(slashCommand.Description);
|
|
||||||
}
|
|
||||||
|
|
||||||
await context.RespondAsync(embed: embedBuilder.Build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ApplicationIcon />
|
|
||||||
<StartupObject />
|
|
||||||
<SignAssembly>False</SignAssembly>
|
|
||||||
<IsPublishable>True</IsPublishable>
|
|
||||||
<AssemblyVersion>1.0.4.0</AssemblyVersion>
|
|
||||||
<PublishAot>False</PublishAot>
|
|
||||||
<FileVersion>1.0.4.0</FileVersion>
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Remove="Data\**" />
|
|
||||||
<Compile Remove="obj\**" />
|
|
||||||
<Compile Remove="Output\**" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Remove="Data\**" />
|
|
||||||
<EmbeddedResource Remove="obj\**" />
|
|
||||||
<EmbeddedResource Remove="Output\**" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Remove="Data\**" />
|
|
||||||
<None Remove="obj\**" />
|
|
||||||
<None Remove="Output\**" />
|
|
||||||
<None Remove="builder.bat" />
|
|
||||||
<None Remove="builder.sh" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
|
|
||||||
<PackageReference Include="Spectre.Console" Version="0.49.1" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\DiscordBotCore\DiscordBotCore.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="..\.dockerignore">
|
|
||||||
<Link>.dockerignore</Link>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
|
||||||
USER $APP_UID
|
|
||||||
WORKDIR /app
|
|
||||||
EXPOSE 5055
|
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
|
||||||
ARG BUILD_CONFIGURATION=Release
|
|
||||||
WORKDIR /src
|
|
||||||
COPY ["DiscordBot/DiscordBot.csproj", "DiscordBot/"]
|
|
||||||
COPY ["DiscordBotCore/DiscordBotCore.csproj", "DiscordBotCore/"]
|
|
||||||
RUN dotnet restore "DiscordBot/DiscordBot.csproj"
|
|
||||||
COPY . .
|
|
||||||
WORKDIR "/src/DiscordBot"
|
|
||||||
RUN dotnet build "DiscordBot.csproj" -c $BUILD_CONFIGURATION -o /app/build
|
|
||||||
|
|
||||||
FROM build AS publish
|
|
||||||
ARG BUILD_CONFIGURATION=Release
|
|
||||||
RUN dotnet publish "DiscordBot.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
|
|
||||||
|
|
||||||
FROM base AS final
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=publish /app/publish .
|
|
||||||
EXPOSE 5055
|
|
||||||
ENTRYPOINT ["dotnet", "DiscordBot.dll"]
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace DiscordBot;
|
|
||||||
|
|
||||||
public static class Entry
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Some startup actions that can are executed when the console first starts. This actions are invoked externally at application launch
|
|
||||||
/// </summary>
|
|
||||||
private static readonly List<IStartupAction> StartupActions = [
|
|
||||||
new StartupAction("--clean-up", () => {
|
|
||||||
foreach (var plugin in Directory.GetFiles("./Data/Plugins", "*.dll", SearchOption.AllDirectories))
|
|
||||||
{
|
|
||||||
File.Delete(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
File.Delete("./Data/Resources/plugins.json");
|
|
||||||
Directory.Delete("./Libraries/", true);
|
|
||||||
}),
|
|
||||||
|
|
||||||
new StartupAction("--update-cleanup", () => {
|
|
||||||
List<string> files = new List<string>();
|
|
||||||
files.AddRange(Directory.GetFiles("./"));
|
|
||||||
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
if (file.EndsWith(".bak"))
|
|
||||||
File.Delete(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
Directory.Delete("temp");
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
private static readonly string logo =
|
|
||||||
@"
|
|
||||||
|
|
||||||
_____ _ _ _____ _ _ ____ _
|
|
||||||
/ ____| | | | | | __ \(_) | | | _ \ | |
|
|
||||||
| (___ ___| |_| |__ | | | |_ ___ ___ ___ _ __ __| | | |_) | ___ | |_
|
|
||||||
\___ \ / _ \ __| '_ \ | | | | / __|/ __/ _ \| '__/ _` | | _ < / _ \| __|
|
|
||||||
____) | __/ |_| | | | | |__| | \__ \ (_| (_) | | | (_| | | |_) | (_) | |_
|
|
||||||
|_____/ \___|\__|_| |_| |_____/|_|___/\___\___/|_| \__,_| |____/ \___/ \__|
|
|
||||||
(Console Application)
|
|
||||||
|
|
||||||
";
|
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
StartupActions.FirstOrDefault(action => action.Command == args[0], null)?.RunAction(args[1..]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.Clear();
|
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
|
||||||
Console.WriteLine(logo);
|
|
||||||
Console.ResetColor();
|
|
||||||
|
|
||||||
|
|
||||||
var currentDomain = AppDomain.CurrentDomain;
|
|
||||||
currentDomain.AssemblyResolve += LoadFromSameFolder;
|
|
||||||
|
|
||||||
static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args)
|
|
||||||
{
|
|
||||||
string requestingAssembly = args.RequestingAssembly?.GetName().Name;
|
|
||||||
var folderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, $"Libraries/{requestingAssembly}");
|
|
||||||
var assemblyName = new AssemblyName(args.Name).Name + ".dll";
|
|
||||||
var assemblyPath = Path.Combine(folderPath, assemblyName);
|
|
||||||
|
|
||||||
Console.WriteLine("Requesting Assembly: " + requestingAssembly);
|
|
||||||
Console.WriteLine("Requested Assembly File: " + assemblyName);
|
|
||||||
|
|
||||||
if (File.Exists(assemblyPath))
|
|
||||||
{
|
|
||||||
var fileAssembly = Assembly.LoadFrom(assemblyPath);
|
|
||||||
Console.WriteLine("Loaded Assembly: " + fileAssembly.FullName);
|
|
||||||
return fileAssembly;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("Failed to load assembly: " + assemblyPath + ". File does not exist");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Program.Startup(args).Wait();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace DiscordBot
|
|
||||||
{
|
|
||||||
internal interface IStartupAction
|
|
||||||
{
|
|
||||||
string Command { get; init; }
|
|
||||||
Action<string[]> RunAction { get; init; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
using DiscordBotCore;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace DiscordBot;
|
|
||||||
|
|
||||||
public static class Installer
|
|
||||||
{
|
|
||||||
private static string AskForConfig(string key, string message)
|
|
||||||
{
|
|
||||||
var value = AnsiConsole.Ask<string>($"[green]{message}[/]");
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(value))
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
AnsiConsole.MarkupLine($"Invalid {key} !");
|
|
||||||
Environment.Exit(-20);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task GenerateStartupConfig()
|
|
||||||
{
|
|
||||||
if (!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("token"))
|
|
||||||
{
|
|
||||||
var response = AskForConfig("token", "Token:");
|
|
||||||
Application.CurrentApplication.ApplicationEnvironmentVariables.Add("token", response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("prefix"))
|
|
||||||
{
|
|
||||||
var response = AskForConfig("prefix", "Prefix:");
|
|
||||||
Application.CurrentApplication.ApplicationEnvironmentVariables.Add("prefix", response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("ServerID"))
|
|
||||||
{
|
|
||||||
var response = AskForConfig("ServerID", "Please enter the server Ids where the bot will be used (separated by ;):");
|
|
||||||
List<ulong> serverIds = new List<ulong>();
|
|
||||||
foreach (var id in response.Split(';'))
|
|
||||||
{
|
|
||||||
if(!ulong.TryParse(id, out ulong sID))
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log($"Invalid server ID {id}", LogType.Warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
serverIds.Add(sID);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!serverIds.Any())
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log($"No valid server id provided", LogType.Critical);
|
|
||||||
Environment.Exit(-20);
|
|
||||||
}
|
|
||||||
|
|
||||||
Application.CurrentApplication.ApplicationEnvironmentVariables.Add("ServerID", serverIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Application.CurrentApplication.ApplicationEnvironmentVariables.SaveToFile();
|
|
||||||
|
|
||||||
Application.CurrentApplication.Logger.Log("Config Saved", typeof(Installer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
using DiscordBot.Bot.Actions.Extra;
|
|
||||||
using DiscordBotCore;
|
|
||||||
using DiscordBotCore.Bot;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace DiscordBot;
|
|
||||||
|
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The main entry point for the application.
|
|
||||||
/// </summary>
|
|
||||||
public static async Task Startup(string[] args)
|
|
||||||
{
|
|
||||||
await LoadComponents(args);
|
|
||||||
await PrepareConsole();
|
|
||||||
await PluginMethods.RefreshPlugins(false);
|
|
||||||
|
|
||||||
await ConsoleInputHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The main loop for the discord bot
|
|
||||||
/// </summary>
|
|
||||||
private static async Task ConsoleInputHandler()
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
var cmd = Console.ReadLine();
|
|
||||||
var args = cmd.Split(' ');
|
|
||||||
var command = args[0];
|
|
||||||
args = args.Skip(1).ToArray();
|
|
||||||
if (args.Length == 0)
|
|
||||||
args = null;
|
|
||||||
|
|
||||||
await Application.CurrentApplication.InternalActionManager.Execute(command, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Start the bot without user interface
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Returns the bootloader for the Discord Bot</returns>
|
|
||||||
private static async Task PrepareConsole()
|
|
||||||
{
|
|
||||||
AnsiConsole.MarkupLine($"[yellow]Running on version: {Assembly.GetExecutingAssembly().GetName().Version}[/]");
|
|
||||||
AnsiConsole.MarkupLine("[yellow]Git SethBot: https://github.com/andreitdr/SethDiscordBot [/]");
|
|
||||||
|
|
||||||
AnsiConsole.MarkupLine("[yellow]Remember to close the bot using the shutdown command ([/][red]exit[/][yellow]) or some settings won't be saved[/]");
|
|
||||||
|
|
||||||
AnsiConsole.MarkupLine("[yellow]===== Seth Discord Bot =====[/]");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var token = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("token");
|
|
||||||
var prefix = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("prefix");
|
|
||||||
|
|
||||||
var discordApp = new DiscordBotApplication(token, prefix);
|
|
||||||
await discordApp.StartAsync();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log(ex.ToString(), typeof(Program), LogType.Critical);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Load the bot components.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="args">The startup arguments</param>
|
|
||||||
private static async Task LoadComponents(string[] args)
|
|
||||||
{
|
|
||||||
await Application.CreateApplication();
|
|
||||||
|
|
||||||
void LogMessageFunction(string message, LogType logType)
|
|
||||||
{
|
|
||||||
string messageAsString = message;
|
|
||||||
switch (logType)
|
|
||||||
{
|
|
||||||
case LogType.Info:
|
|
||||||
messageAsString = $"[green]{messageAsString} [/]";
|
|
||||||
break;
|
|
||||||
case LogType.Warning:
|
|
||||||
messageAsString = $"[yellow]{messageAsString} [/]";
|
|
||||||
break;
|
|
||||||
case LogType.Error:
|
|
||||||
messageAsString = $"[red]{messageAsString} [/]";
|
|
||||||
break;
|
|
||||||
case LogType.Critical:
|
|
||||||
messageAsString = $"[red] [bold]{messageAsString} [/][/]";
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AnsiConsole.MarkupLine(messageAsString);
|
|
||||||
}
|
|
||||||
|
|
||||||
Application.CurrentApplication.Logger.SetOutFunction(LogMessageFunction);
|
|
||||||
|
|
||||||
|
|
||||||
if (!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("ServerID") ||
|
|
||||||
!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("token") ||
|
|
||||||
!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("prefix"))
|
|
||||||
{
|
|
||||||
await Installer.GenerateStartupConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.Length > 0)
|
|
||||||
{
|
|
||||||
if(args.Contains("--http-api"))
|
|
||||||
Application.InitializeThreadedApi();
|
|
||||||
if(args.Contains("--socket-api"))
|
|
||||||
Application.InitializeThreadedSockets();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace DiscordBot
|
|
||||||
{
|
|
||||||
internal class StartupAction : IStartupAction
|
|
||||||
{
|
|
||||||
public string Command { get; init; }
|
|
||||||
public Action<string[]> RunAction { get; init; }
|
|
||||||
|
|
||||||
public StartupAction(string command, Action<string[]> runAction)
|
|
||||||
{
|
|
||||||
this.Command = command;
|
|
||||||
this.RunAction = runAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StartupAction(string command, Action runAction)
|
|
||||||
{
|
|
||||||
this.Command = command;
|
|
||||||
this.RunAction = (args) => runAction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using DiscordBotCore.Online;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace DiscordBot.Utilities;
|
|
||||||
|
|
||||||
internal static class ConsoleUtilities
|
|
||||||
{
|
|
||||||
|
|
||||||
public static async Task<T> ExecuteWithProgressBar<T>(Task<T> function, string message)
|
|
||||||
{
|
|
||||||
T result = default;
|
|
||||||
await AnsiConsole.Progress()
|
|
||||||
.AutoClear(true)
|
|
||||||
.Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn())
|
|
||||||
.StartAsync(
|
|
||||||
async ctx =>
|
|
||||||
{
|
|
||||||
var task = ctx.AddTask(message);
|
|
||||||
task.IsIndeterminate = true;
|
|
||||||
result = await function;
|
|
||||||
task.Increment(100);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task ExecuteTaskWithBuiltInProgress<T>(Func<T, IProgress<float>, Task> method, T parameter, string taskMessage)
|
|
||||||
{
|
|
||||||
await AnsiConsole.Progress()
|
|
||||||
.AutoClear(false) // Do not remove the task list when done
|
|
||||||
.HideCompleted(false) // Hide tasks as they are completed
|
|
||||||
.Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn())
|
|
||||||
.StartAsync(
|
|
||||||
async ctx =>
|
|
||||||
{
|
|
||||||
var task = ctx.AddTask(taskMessage);
|
|
||||||
IProgress<float> progress = new Progress<float>(x => task.Value = x);
|
|
||||||
await method(parameter, progress);
|
|
||||||
task.Value = 100;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task ExecuteTaskWithBuiltInProgress(Func<IProgress<float>, Task> method, string taskMessage)
|
|
||||||
{
|
|
||||||
await AnsiConsole.Progress()
|
|
||||||
.AutoClear(false) // Do not remove the task list when done
|
|
||||||
.HideCompleted(false) // Hide tasks as they are completed
|
|
||||||
.Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn())
|
|
||||||
.StartAsync(
|
|
||||||
async ctx =>
|
|
||||||
{
|
|
||||||
var task = ctx.AddTask(taskMessage);
|
|
||||||
IProgress<float> progress = new Progress<float>(x => task.Value = x);
|
|
||||||
await method(progress);
|
|
||||||
task.Value = 100;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task ExecuteParallelDownload(Func<HttpClient, string, string, IProgress<float>, Task> method, HttpClient client,
|
|
||||||
List<Tuple<string, string>> parameters, string taskMessage)
|
|
||||||
{
|
|
||||||
await AnsiConsole.Progress().AutoClear(false).HideCompleted(false)
|
|
||||||
.Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn())
|
|
||||||
.StartAsync(async ctx =>
|
|
||||||
{
|
|
||||||
var tasks = new List<Task>();
|
|
||||||
foreach (var (location, url) in parameters)
|
|
||||||
{
|
|
||||||
var task = ctx.AddTask(taskMessage + " " + url);
|
|
||||||
IProgress<float> progress = new Progress<float>(x => task.Value = x * 100);
|
|
||||||
tasks.Add(method(client, url, location, progress));
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.WhenAll(tasks);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
using Spectre.Console;
|
|
||||||
using Spectre.Console.Rendering;
|
|
||||||
|
|
||||||
namespace DiscordBot.Utilities
|
|
||||||
{
|
|
||||||
public class TableData
|
|
||||||
{
|
|
||||||
public List<string> Columns;
|
|
||||||
public List<OneOf<string, IRenderable>[]> Rows;
|
|
||||||
|
|
||||||
public TableData()
|
|
||||||
{
|
|
||||||
Columns = new List<string>();
|
|
||||||
Rows = new List<OneOf<string, IRenderable>[]>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public TableData(List<string> columns)
|
|
||||||
{
|
|
||||||
Columns = columns;
|
|
||||||
Rows = new List<OneOf<string, IRenderable>[]>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsEmpty => Rows.Count == 0;
|
|
||||||
public bool HasRoundBorders { get; set; } = true;
|
|
||||||
public bool DisplayLinesBetweenRows { get; set; } = false;
|
|
||||||
|
|
||||||
public void AddRow(OneOf<string, IRenderable>[] row)
|
|
||||||
{
|
|
||||||
Rows.Add(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Table AsTable()
|
|
||||||
{
|
|
||||||
|
|
||||||
var table = new Table();
|
|
||||||
table.Border(this.HasRoundBorders ? TableBorder.Rounded : TableBorder.Square);
|
|
||||||
table.AddColumns(this.Columns.ToArray());
|
|
||||||
table.ShowRowSeparators = DisplayLinesBetweenRows;
|
|
||||||
foreach (var row in this.Rows)
|
|
||||||
{
|
|
||||||
table.AddRow(row.Select(element => element.Match(
|
|
||||||
(string data) => new Markup(data),
|
|
||||||
(IRenderable data) => data
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
table.Alignment(Justify.Center);
|
|
||||||
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PrintTable()
|
|
||||||
{
|
|
||||||
if (IsEmpty) return;
|
|
||||||
AnsiConsole.Write(this.AsTable());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
@echo off
|
|
||||||
echo "Building..."
|
|
||||||
|
|
||||||
echo "Building linux-x64 not self-contained"
|
|
||||||
dotnet publish -r linux-x64 -p:PublishSingleFile=false --self-contained true -c Release -o ../publish/linux-x64
|
|
||||||
|
|
||||||
echo "Building win-x64 not self-contained"
|
|
||||||
dotnet publish -r win-x64 -p:PublishSingleFile=false --self-contained true -c Release -o ../publish/win-x64
|
|
||||||
|
|
||||||
echo "Building osx-x64 not self-contained"
|
|
||||||
dotnet publish -r osx-x64 -p:PublishSingleFile=false --self-contained true -c Release -o ../publish/osx-x64
|
|
||||||
|
|
||||||
|
|
||||||
echo "Building linux-x64 self-contained"
|
|
||||||
dotnet publish -r linux-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ../publish/linux-x64-selfcontained
|
|
||||||
|
|
||||||
echo "Building win-x64 self-contained"
|
|
||||||
dotnet publish -r win-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ../publish/win-x64-selfcontained
|
|
||||||
|
|
||||||
echo "Building osx-x64 self-contained"
|
|
||||||
dotnet publish -r osx-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ../publish/osx-x64-selfcontained
|
|
||||||
|
|
||||||
echo "Zipping..."
|
|
||||||
mkdir ../publish/zip
|
|
||||||
|
|
||||||
|
|
||||||
zip -r ../publish/zip/linux-x64.zip ../publish/linux-x64
|
|
||||||
zip -r ../publish/zip/win-x64.zip ../publish/win-x64
|
|
||||||
zip -r ../publish/zip/osx-x64.zip ../publish/osx-x64
|
|
||||||
|
|
||||||
zip -r ../publish/zip/linux-x64-selfcontained.zip ../publish/linux-x64-selfcontained
|
|
||||||
zip -r ../publish/zip/win-x64-selfcontained.zip ../publish/win-x64-selfcontained
|
|
||||||
zip -r ../publish/zip/osx-x64-selfcontained.zip ../publish/osx-x64-selfcontained
|
|
||||||
|
|
||||||
echo "Done!"
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# All files in this directory will be copied to the root of the container
|
|
||||||
|
|
||||||
echo "Building..."
|
|
||||||
|
|
||||||
echo "Building linux-x64 not self-contained"
|
|
||||||
dotnet publish -r linux-x64 -p:PublishSingleFile=false --self-contained true -c Release -o ./publish/linux-x64
|
|
||||||
|
|
||||||
echo "Building win-x64 not self-contained"
|
|
||||||
dotnet publish -r win-x64 -p:PublishSingleFile=false --self-contained true -c Release -o ./publish/win-x64
|
|
||||||
|
|
||||||
echo "Building osx-x64 not self-contained"
|
|
||||||
dotnet publish -r osx-x64 -p:PublishSingleFile=false --self-contained true -c Release -o ./publish/osx-x64
|
|
||||||
|
|
||||||
#One file per platform
|
|
||||||
echo "Building linux-x64 self-contained"
|
|
||||||
dotnet publish -r linux-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./publish/linux-x64-selfcontained
|
|
||||||
|
|
||||||
echo "Building win-x64 self-contained"
|
|
||||||
dotnet publish -r win-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./publish/win-x64-selfcontained
|
|
||||||
|
|
||||||
echo "Building osx-x64 self-contained"
|
|
||||||
dotnet publish -r osx-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./publish/osx-x64-selfcontained
|
|
||||||
|
|
||||||
echo "Zipping..."
|
|
||||||
mkdir ./publish/zip
|
|
||||||
|
|
||||||
|
|
||||||
zip -r ./publish/zip/linux-x64.zip ./publish/linux-x64
|
|
||||||
zip -r ./publish/zip/win-x64.zip ./publish/win-x64
|
|
||||||
zip -r ./publish/zip/osx-x64.zip ./publish/osx-x64
|
|
||||||
|
|
||||||
zip -r ./publish/zip/linux-x64-selfcontained.zip ./publish/linux-x64-selfcontained
|
|
||||||
zip -r ./publish/zip/win-x64-selfcontained.zip ./publish/win-x64-selfcontained
|
|
||||||
zip -r ./publish/zip/osx-x64-selfcontained.zip ./publish/osx-x64-selfcontained
|
|
||||||
|
|
||||||
echo "Done!"
|
|
||||||
@@ -1,15 +1,27 @@
|
|||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using DiscordBotCore.PluginCore;
|
|
||||||
using DiscordBotCore.PluginCore.Interfaces;
|
using DiscordBotCore.PluginCore.Interfaces;
|
||||||
|
|
||||||
namespace DiscordBotCore.PluginManagement.Loading;
|
namespace DiscordBotCore.PluginManagement.Loading;
|
||||||
|
|
||||||
public interface IPluginLoader
|
public interface IPluginLoader
|
||||||
{
|
{
|
||||||
List<IDbCommand> Commands { get; }
|
public IReadOnlyList<IDbCommand> Commands { get; }
|
||||||
List<IDbEvent> Events { get; }
|
public IReadOnlyList<IDbEvent> Events { get; }
|
||||||
List<IDbSlashCommand> SlashCommands { get; }
|
public IReadOnlyList<IDbSlashCommand> SlashCommands { get; }
|
||||||
Task LoadPlugins();
|
|
||||||
|
|
||||||
void SetClient(DiscordSocketClient client);
|
/// <summary>
|
||||||
|
/// Sets the Discord client for the plugin loader. This is used to initialize the slash commands and events.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="discordSocketClient">The socket client that represents the running Discord Bot</param>
|
||||||
|
public void SetDiscordClient(DiscordSocketClient discordSocketClient);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads all the plugins that are installed.
|
||||||
|
/// </summary>
|
||||||
|
public Task LoadPlugins();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unload all plugins from the plugin manager.
|
||||||
|
/// </summary>
|
||||||
|
public void UnloadAllPlugins();
|
||||||
}
|
}
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using DiscordBotCore.PluginCore;
|
|
||||||
using DiscordBotCore.PluginCore.Interfaces;
|
|
||||||
using DiscordBotCore.PluginManagement.Loading.Exceptions;
|
|
||||||
|
|
||||||
namespace DiscordBotCore.PluginManagement.Loading;
|
|
||||||
|
|
||||||
internal class Loader
|
|
||||||
{
|
|
||||||
internal delegate void FileLoadedHandler(string fileName, Exception exception);
|
|
||||||
internal delegate void PluginLoadedHandler(PluginLoaderResult result);
|
|
||||||
|
|
||||||
internal event FileLoadedHandler? OnFileLoadedException;
|
|
||||||
internal event PluginLoadedHandler? OnPluginLoaded;
|
|
||||||
|
|
||||||
private readonly IPluginManager _pluginManager;
|
|
||||||
|
|
||||||
internal Loader(IPluginManager manager)
|
|
||||||
{
|
|
||||||
_pluginManager = manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal async Task Load()
|
|
||||||
{
|
|
||||||
var installedPlugins = await _pluginManager.GetInstalledPlugins();
|
|
||||||
var files = installedPlugins.Where(plugin => plugin.IsEnabled).Select(plugin => plugin.FilePath).ToArray();
|
|
||||||
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assembly.LoadFrom(file);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
OnFileLoadedException?.Invoke(file, new Exception($"Failed to load plugin from file {file}"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await LoadEverythingOfType<IDbEvent>();
|
|
||||||
await LoadEverythingOfType<IDbCommand>();
|
|
||||||
await LoadEverythingOfType<IDbSlashCommand>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task LoadEverythingOfType<T>()
|
|
||||||
{
|
|
||||||
var types = AppDomain.CurrentDomain.GetAssemblies()
|
|
||||||
.SelectMany(s => s.GetTypes())
|
|
||||||
.Where(p => typeof(T).IsAssignableFrom(p) && !p.IsInterface);
|
|
||||||
|
|
||||||
foreach (var type in types)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var plugin = (T?)Activator.CreateInstance(type);
|
|
||||||
|
|
||||||
if (plugin is null)
|
|
||||||
{
|
|
||||||
throw new Exception($"Failed to create instance of plugin with type {type.FullName} [{type.Assembly}]");
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginLoaderResult result = plugin switch
|
|
||||||
{
|
|
||||||
IDbEvent @event => PluginLoaderResult.FromIDbEvent(@event),
|
|
||||||
IDbCommand command => PluginLoaderResult.FromIDbCommand(command),
|
|
||||||
IDbSlashCommand command => PluginLoaderResult.FromIDbSlashCommand(command),
|
|
||||||
_ => PluginLoaderResult.FromException(new PluginNotFoundException($"Unknown plugin type {plugin.GetType().FullName}"))
|
|
||||||
};
|
|
||||||
|
|
||||||
OnPluginLoaded?.Invoke(result);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
OnPluginLoaded?.Invoke(PluginLoaderResult.FromException(ex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,27 +1,29 @@
|
|||||||
using System.Net.Mime;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Reflection;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using DiscordBotCore.Configuration;
|
using DiscordBotCore.Configuration;
|
||||||
using DiscordBotCore.Logging;
|
using DiscordBotCore.Logging;
|
||||||
using DiscordBotCore.PluginCore;
|
|
||||||
using DiscordBotCore.PluginCore.Helpers;
|
|
||||||
using DiscordBotCore.PluginCore.Helpers.Execution.DbEvent;
|
using DiscordBotCore.PluginCore.Helpers.Execution.DbEvent;
|
||||||
using DiscordBotCore.PluginCore.Interfaces;
|
using DiscordBotCore.PluginCore.Interfaces;
|
||||||
using DiscordBotCore.Utilities;
|
using DiscordBotCore.PluginManagement.Loading.Exceptions;
|
||||||
|
|
||||||
namespace DiscordBotCore.PluginManagement.Loading;
|
namespace DiscordBotCore.PluginManagement.Loading;
|
||||||
|
|
||||||
public sealed class PluginLoader : IPluginLoader
|
public class PluginLoader : IPluginLoader
|
||||||
{
|
{
|
||||||
private readonly IPluginManager _PluginManager;
|
private readonly IPluginManager _PluginManager;
|
||||||
private readonly ILogger _Logger;
|
private readonly ILogger _Logger;
|
||||||
private readonly IConfiguration _Configuration;
|
private readonly IConfiguration _Configuration;
|
||||||
|
|
||||||
public List<IDbCommand> Commands { get; private set; } = new List<IDbCommand>();
|
private DiscordSocketClient? _DiscordClient;
|
||||||
public List<IDbEvent> Events { get; private set; } = new List<IDbEvent>();
|
private PluginLoaderContext? PluginLoaderContext;
|
||||||
public List<IDbSlashCommand> SlashCommands { get; private set; } = new List<IDbSlashCommand>();
|
|
||||||
|
|
||||||
private DiscordSocketClient? _discordClient;
|
private readonly List<IDbCommand> _Commands = new List<IDbCommand>();
|
||||||
|
private readonly List<IDbEvent> _Events = new List<IDbEvent>();
|
||||||
|
private readonly List<IDbSlashCommand> _SlashCommands = new List<IDbSlashCommand>();
|
||||||
|
|
||||||
|
private bool _IsFirstLoad = true;
|
||||||
|
|
||||||
public PluginLoader(IPluginManager pluginManager, ILogger logger, IConfiguration configuration)
|
public PluginLoader(IPluginManager pluginManager, ILogger logger, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
@@ -30,48 +32,150 @@ public sealed class PluginLoader : IPluginLoader
|
|||||||
_Configuration = configuration;
|
_Configuration = configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task LoadPlugins()
|
public IReadOnlyList<IDbCommand> Commands => _Commands;
|
||||||
|
public IReadOnlyList<IDbEvent> Events => _Events;
|
||||||
|
public IReadOnlyList<IDbSlashCommand> SlashCommands => _SlashCommands;
|
||||||
|
|
||||||
|
public void SetDiscordClient(DiscordSocketClient discordSocketClient)
|
||||||
{
|
{
|
||||||
Commands.Clear();
|
if (_DiscordClient is not null)
|
||||||
Events.Clear();
|
|
||||||
SlashCommands.Clear();
|
|
||||||
|
|
||||||
_Logger.Log("Loading plugins...", this);
|
|
||||||
|
|
||||||
var loader = new Loader(_PluginManager);
|
|
||||||
|
|
||||||
loader.OnFileLoadedException += FileLoadedException;
|
|
||||||
loader.OnPluginLoaded += OnPluginLoaded;
|
|
||||||
|
|
||||||
await loader.Load();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetClient(DiscordSocketClient client)
|
|
||||||
{
|
|
||||||
if (_discordClient is not null)
|
|
||||||
{
|
{
|
||||||
_Logger.Log("A client is already set. Please set the client only once.", this, LogType.Error);
|
_Logger.Log("A client is already set. Please set the client only once.", this, LogType.Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client.LoginState != LoginState.LoggedIn)
|
if (discordSocketClient.LoginState != LoginState.LoggedIn)
|
||||||
{
|
{
|
||||||
_Logger.Log("Client is not logged in. Retry after the client is logged in", this, LogType.Error);
|
_Logger.Log("The client must be logged in before setting it.", this, LogType.Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Logger.Log("Client is set to the plugin loader", this);
|
_DiscordClient = discordSocketClient;
|
||||||
_discordClient = client;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FileLoadedException(string fileName, Exception exception)
|
public async Task LoadPlugins()
|
||||||
{
|
{
|
||||||
_Logger.LogException(exception, this);
|
UnloadAllPlugins();
|
||||||
|
|
||||||
|
_Events.Clear();
|
||||||
|
_Commands.Clear();
|
||||||
|
_SlashCommands.Clear();
|
||||||
|
|
||||||
|
await LoadPluginFiles();
|
||||||
|
|
||||||
|
LoadEverythingOfType<IDbEvent>();
|
||||||
|
LoadEverythingOfType<IDbCommand>();
|
||||||
|
LoadEverythingOfType<IDbSlashCommand>();
|
||||||
|
|
||||||
|
_Logger.Log("Loaded plugins", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnloadAllPlugins()
|
||||||
|
{
|
||||||
|
if (_IsFirstLoad)
|
||||||
|
{
|
||||||
|
// Allow unloading only after the first load
|
||||||
|
_IsFirstLoad = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PluginLoaderContext is null)
|
||||||
|
{
|
||||||
|
_Logger.Log("The plugins are not loaded. Please load the plugins before unloading them.", this, LogType.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginLoaderContext.Unload();
|
||||||
|
GC.Collect();
|
||||||
|
GC.WaitForPendingFinalizers();
|
||||||
|
GC.Collect();
|
||||||
|
|
||||||
|
PluginLoaderContext = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task LoadPluginFiles()
|
||||||
|
{
|
||||||
|
if (PluginLoaderContext is not null)
|
||||||
|
{
|
||||||
|
_Logger.Log("The plugins are already loaded", this, LogType.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var installedPlugins = await _PluginManager.GetInstalledPlugins();
|
||||||
|
|
||||||
|
if (installedPlugins.Count == 0)
|
||||||
|
{
|
||||||
|
_Logger.Log("No plugin files found. Please check the plugin files.", this, LogType.Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var files = installedPlugins.Where(plugin => plugin.IsEnabled).Select(plugin => plugin.FilePath);
|
||||||
|
|
||||||
|
PluginLoaderContext = new PluginLoaderContext("PluginLoader");
|
||||||
|
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
string fullFilePath = Path.GetFullPath(file);
|
||||||
|
if (string.IsNullOrEmpty(fullFilePath))
|
||||||
|
{
|
||||||
|
_Logger.Log("The file path is empty. Please check the plugin file path.", PluginLoaderContext, LogType.Error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(fullFilePath))
|
||||||
|
{
|
||||||
|
_Logger.Log("The file does not exist. Please check the plugin file path.", PluginLoaderContext, LogType.Error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PluginLoaderContext.LoadFromAssemblyPath(fullFilePath);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_Logger.LogException(ex, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_Logger.Log($"Loaded {PluginLoaderContext.Assemblies.Count()} assemblies", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadEverythingOfType<T>()
|
||||||
|
{
|
||||||
|
var types = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
.SelectMany(s => s.GetTypes())
|
||||||
|
.Where(p => typeof(T).IsAssignableFrom(p) && !p.IsInterface);
|
||||||
|
|
||||||
|
foreach (var type in types)
|
||||||
|
{
|
||||||
|
T? plugin = (T?)Activator.CreateInstance(type);
|
||||||
|
if (plugin is null)
|
||||||
|
{
|
||||||
|
_Logger.Log($"Failed to create instance of plugin with type {type.FullName} [{type.Assembly}]", this, LogType.Error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (plugin)
|
||||||
|
{
|
||||||
|
case IDbEvent dbEvent:
|
||||||
|
InitializeEvent(dbEvent);
|
||||||
|
break;
|
||||||
|
case IDbCommand dbCommand:
|
||||||
|
InitializeDbCommand(dbCommand);
|
||||||
|
break;
|
||||||
|
case IDbSlashCommand dbSlashCommand:
|
||||||
|
InitializeSlashCommand(dbSlashCommand);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new PluginNotFoundException($"Unknown plugin type {plugin.GetType().FullName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeDbCommand(IDbCommand command)
|
private void InitializeDbCommand(IDbCommand command)
|
||||||
{
|
{
|
||||||
Commands.Add(command);
|
_Commands.Add(command);
|
||||||
_Logger.Log("Command loaded: " + command.Command, this);
|
_Logger.Log("Command loaded: " + command.Command, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,38 +186,31 @@ public sealed class PluginLoader : IPluginLoader
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Events.Add(eEvent);
|
_Events.Add(eEvent);
|
||||||
_Logger.Log("Event loaded: " + eEvent, this);
|
_Logger.Log("Event loaded: " + eEvent, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void InitializeSlashCommand(IDbSlashCommand slashCommand)
|
private async void InitializeSlashCommand(IDbSlashCommand slashCommand)
|
||||||
{
|
{
|
||||||
Result result = await TryStartSlashCommand(slashCommand);
|
bool result = await TryStartSlashCommand(slashCommand);
|
||||||
result.Match(
|
|
||||||
() =>
|
if (!result)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_DiscordClient is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (slashCommand.HasInteraction)
|
if (slashCommand.HasInteraction)
|
||||||
_discordClient.InteractionCreated += interaction => slashCommand.ExecuteInteraction(_Logger, interaction);
|
{
|
||||||
SlashCommands.Add(slashCommand);
|
_DiscordClient.InteractionCreated += interaction => slashCommand.ExecuteInteraction(_Logger, interaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
_SlashCommands.Add(slashCommand);
|
||||||
_Logger.Log("Slash command loaded: " + slashCommand.Name, this);
|
_Logger.Log("Slash command loaded: " + slashCommand.Name, this);
|
||||||
},
|
|
||||||
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)
|
private bool TryStartEvent(IDbEvent dbEvent)
|
||||||
@@ -125,7 +222,7 @@ public sealed class PluginLoader : IPluginLoader
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_discordClient is null)
|
if (_DiscordClient is null)
|
||||||
{
|
{
|
||||||
_Logger.Log("Discord client is not set. Please set the discord client before starting events.", this, LogType.Error);
|
_Logger.Log("Discord client is not set. Please set the discord client before starting events.", this, LogType.Error);
|
||||||
return false;
|
return false;
|
||||||
@@ -150,7 +247,7 @@ public sealed class PluginLoader : IPluginLoader
|
|||||||
|
|
||||||
IDbEventExecutingArgument args = new DbEventExecutingArgument(
|
IDbEventExecutingArgument args = new DbEventExecutingArgument(
|
||||||
_Logger,
|
_Logger,
|
||||||
_discordClient,
|
_DiscordClient,
|
||||||
botPrefix,
|
botPrefix,
|
||||||
new DirectoryInfo(eventConfigDirectory));
|
new DirectoryInfo(eventConfigDirectory));
|
||||||
|
|
||||||
@@ -158,18 +255,24 @@ public sealed class PluginLoader : IPluginLoader
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Result> TryStartSlashCommand(IDbSlashCommand? dbSlashCommand)
|
private async Task<bool> TryStartSlashCommand(IDbSlashCommand? dbSlashCommand)
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (dbSlashCommand is null)
|
if (dbSlashCommand is null)
|
||||||
{
|
{
|
||||||
return Result.Failure(new Exception("dbSlashCommand is null"));
|
_Logger.Log("The loaded slash command was null. Please check the plugin.", this, LogType.Error);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_discordClient.Guilds.Count == 0)
|
if (_DiscordClient is null)
|
||||||
{
|
{
|
||||||
return Result.Failure(new Exception("No guilds found"));
|
_Logger.Log("The client is not set. Please set the client before starting slash commands.", this, LogType.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_DiscordClient.Guilds.Count == 0)
|
||||||
|
{
|
||||||
|
_Logger.Log("The client is not connected to any guilds. Please check the client.", this, LogType.Error);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var builder = new SlashCommandBuilder();
|
var builder = new SlashCommandBuilder();
|
||||||
@@ -190,26 +293,22 @@ public sealed class PluginLoader : IPluginLoader
|
|||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
return Result.Failure($"Failed to enable slash command {dbSlashCommand.Name} for guild {guildId}");
|
_Logger.Log($"Failed to enable slash command {dbSlashCommand.Name} for guild {guildId}", this, LogType.Error);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await _discordClient.CreateGlobalApplicationCommandAsync(builder.Build());
|
await _DiscordClient.CreateGlobalApplicationCommandAsync(builder.Build());
|
||||||
|
|
||||||
return Result.Success();
|
return true;
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
return Result.Failure("Error starting slash command");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<bool> EnableSlashCommandPerGuild(ulong guildId, SlashCommandBuilder builder)
|
private async Task<bool> EnableSlashCommandPerGuild(ulong guildId, SlashCommandBuilder builder)
|
||||||
{
|
{
|
||||||
SocketGuild? guild = _discordClient.GetGuild(guildId);
|
SocketGuild? guild = _DiscordClient?.GetGuild(guildId);
|
||||||
if (guild is null)
|
if (guild is null)
|
||||||
{
|
{
|
||||||
_Logger.Log("Failed to get guild with ID " + guildId, typeof(PluginLoader), LogType.Error);
|
_Logger.Log("Failed to get guild with ID " + guildId, this, LogType.Error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Loader;
|
||||||
|
|
||||||
|
namespace DiscordBotCore.PluginManagement.Loading;
|
||||||
|
|
||||||
|
public class PluginLoaderContext : AssemblyLoadContext
|
||||||
|
{
|
||||||
|
public PluginLoaderContext(string name) : base(name: name, isCollectible: true) {}
|
||||||
|
|
||||||
|
protected override Assembly? Load(AssemblyName assemblyName)
|
||||||
|
{
|
||||||
|
|
||||||
|
return base.Load(assemblyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
using DiscordBotCore.PluginCore;
|
|
||||||
using DiscordBotCore.PluginCore.Interfaces;
|
|
||||||
using DiscordBotCore.Utilities;
|
|
||||||
|
|
||||||
namespace DiscordBotCore.PluginManagement.Loading;
|
|
||||||
|
|
||||||
|
|
||||||
public class PluginLoaderResult
|
|
||||||
{
|
|
||||||
private Option3<IDbCommand, IDbEvent, IDbSlashCommand, Exception> _Result;
|
|
||||||
|
|
||||||
public static PluginLoaderResult FromIDbCommand(IDbCommand command) => new PluginLoaderResult(new Option3<IDbCommand, IDbEvent, IDbSlashCommand, Exception>(command));
|
|
||||||
|
|
||||||
public static PluginLoaderResult FromIDbEvent(IDbEvent dbEvent) => new PluginLoaderResult(new Option3<IDbCommand, IDbEvent, IDbSlashCommand, Exception>(dbEvent));
|
|
||||||
|
|
||||||
public static PluginLoaderResult FromIDbSlashCommand(IDbSlashCommand slashCommand) => new PluginLoaderResult(new Option3<IDbCommand, IDbEvent, IDbSlashCommand, Exception>(slashCommand));
|
|
||||||
|
|
||||||
public static PluginLoaderResult FromException(Exception exception) => new PluginLoaderResult(new Option3<IDbCommand, IDbEvent, IDbSlashCommand, Exception>(exception));
|
|
||||||
private PluginLoaderResult(Option3<IDbCommand, IDbEvent, IDbSlashCommand, Exception> result)
|
|
||||||
{
|
|
||||||
_Result = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Match(Action<IDbCommand> commandAction, Action<IDbEvent> eventAction, Action<IDbSlashCommand> slashCommandAction,
|
|
||||||
Action<Exception> exceptionAction)
|
|
||||||
{
|
|
||||||
_Result.Match(commandAction, eventAction, slashCommandAction, exceptionAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TResult Match<TResult>(Func<IDbCommand, TResult> commandFunc, Func<IDbEvent, TResult> eventFunc,
|
|
||||||
Func<IDbSlashCommand, TResult> slashCommandFunc,
|
|
||||||
Func<Exception, TResult> exceptionFunc)
|
|
||||||
{
|
|
||||||
return _Result.Match(commandFunc, eventFunc, slashCommandFunc, exceptionFunc);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -18,7 +18,7 @@ public class DiscordBotApplication : IDiscordBotApplication
|
|||||||
private CommandService _Service;
|
private CommandService _Service;
|
||||||
private readonly ILogger _Logger;
|
private readonly ILogger _Logger;
|
||||||
private readonly IConfiguration _Configuration;
|
private readonly IConfiguration _Configuration;
|
||||||
private readonly IPluginLoader _PluginLoader;
|
private readonly IPluginLoader _pluginLoader;
|
||||||
|
|
||||||
public bool IsReady { get; private set; }
|
public bool IsReady { get; private set; }
|
||||||
|
|
||||||
@@ -27,11 +27,11 @@ public class DiscordBotApplication : IDiscordBotApplication
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main Boot constructor
|
/// The main Boot constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DiscordBotApplication(ILogger logger, IConfiguration configuration, IPluginLoader pluginLoader)
|
public DiscordBotApplication(ILogger logger, IConfiguration configuration, IPluginLoader pluginLoaderOld)
|
||||||
{
|
{
|
||||||
this._Logger = logger;
|
this._Logger = logger;
|
||||||
this._Configuration = configuration;
|
this._Configuration = configuration;
|
||||||
this._PluginLoader = pluginLoader;
|
this._pluginLoader = pluginLoaderOld;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StopAsync()
|
public async Task StopAsync()
|
||||||
@@ -84,7 +84,7 @@ public class DiscordBotApplication : IDiscordBotApplication
|
|||||||
|
|
||||||
await client.StartAsync();
|
await client.StartAsync();
|
||||||
|
|
||||||
_CommandServiceHandler = new CommandHandler(_Logger, _PluginLoader, _Configuration, _Service, _Configuration.Get<string>("prefix", _DefaultPrefix));
|
_CommandServiceHandler = new CommandHandler(_Logger, _pluginLoader, _Configuration, _Service, _Configuration.Get<string>("prefix", _DefaultPrefix));
|
||||||
|
|
||||||
await _CommandServiceHandler.InstallCommandsAsync(client);
|
await _CommandServiceHandler.InstallCommandsAsync(client);
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ public class DiscordBotApplication : IDiscordBotApplication
|
|||||||
private Task LoggedIn()
|
private Task LoggedIn()
|
||||||
{
|
{
|
||||||
_Logger.Log("Successfully Logged In", this);
|
_Logger.Log("Successfully Logged In", this);
|
||||||
_PluginLoader.SetClient(Client);
|
_pluginLoader.SetDiscordClient(Client);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.1.32421.90
|
VisualStudioVersion = 17.1.32421.90
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBot", "DiscordBot\DiscordBot.csproj", "{087E64F4-1E1C-4899-8223-295356C9894A}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBotCore", "DiscordBotCore\DiscordBotCore.csproj", "{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBotCore", "DiscordBotCore\DiscordBotCore.csproj", "{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{5CF9AD7B-6BF0-4035-835F-722F989C01E1}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{5CF9AD7B-6BF0-4035-835F-722F989C01E1}"
|
||||||
@@ -45,10 +43,6 @@ Global
|
|||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{087E64F4-1E1C-4899-8223-295356C9894A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{087E64F4-1E1C-4899-8223-295356C9894A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{087E64F4-1E1C-4899-8223-295356C9894A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{087E64F4-1E1C-4899-8223-295356C9894A}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{5A99BFC3-EB39-4AEF-8D61-3CE22D013B02}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
|||||||
Reference in New Issue
Block a user