More fixes to the new config. Module loader reworked
This commit is contained in:
@@ -49,7 +49,7 @@ namespace DiscordBot.Bot.Actions
|
||||
}
|
||||
|
||||
PluginInfo pluginInfo = new PluginInfo(args[^1], new(1, 0, 0), [], false, true, args.Contains("-enabled"));
|
||||
Application.CurrentApplication.Logger.Log("Adding plugin: " + args[^1]);
|
||||
Application.Logger.Log("Adding plugin: " + args[^1]);
|
||||
await Application.CurrentApplication.PluginManager.AppendPluginToDatabase(pluginInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class Exit: ICommandAction
|
||||
{
|
||||
if (args is null || args.Length == 0)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Exiting...", this, LogType.Warning);
|
||||
Application.Logger.Log("Exiting...", this, LogType.Warning);
|
||||
await Application.CurrentApplication.ApplicationEnvironmentVariables.SaveToFile();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public class Exit: ICommandAction
|
||||
|
||||
case "-f":
|
||||
case "force":
|
||||
Application.CurrentApplication.Logger.Log("Exiting (FORCE)...", this, LogType.Warning);
|
||||
Application.Logger.Log("Exiting (FORCE)...", this, LogType.Warning);
|
||||
Environment.Exit(0);
|
||||
break;
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ internal static class PluginMethods
|
||||
|
||||
}catch(Exception ex)
|
||||
{
|
||||
Application.CurrentApplication.Logger.LogException(ex, typeof(PluginMethods), false);
|
||||
Application.Logger.LogException(ex, typeof(PluginMethods), false);
|
||||
} finally
|
||||
{
|
||||
await Application.CurrentApplication.InternalActionManager.Initialize();
|
||||
@@ -226,12 +226,12 @@ internal static class PluginMethods
|
||||
{
|
||||
if (data.IsSuccess)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Successfully loaded command : " + data.PluginName, LogType.Info, "\t\t > {Message}");
|
||||
Application.Logger.Log("Successfully loaded command : " + data.PluginName, LogType.Info, "\t\t > {Message}");
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Failed to load command : " + data.PluginName + " because " + data.ErrorMessage,
|
||||
Application.Logger.Log("Failed to load command : " + data.PluginName + " because " + data.ErrorMessage,
|
||||
typeof(PluginMethods), LogType.Error
|
||||
);
|
||||
}
|
||||
@@ -242,11 +242,11 @@ internal static class PluginMethods
|
||||
{
|
||||
if (data.IsSuccess)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Successfully loaded event : " + data.PluginName, LogType.Info, "\t\t > {Message}");
|
||||
Application.Logger.Log("Successfully loaded event : " + data.PluginName, LogType.Info, "\t\t > {Message}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Failed to load event : " + data.PluginName + " because " + data.ErrorMessage,
|
||||
Application.Logger.Log("Failed to load event : " + data.PluginName + " because " + data.ErrorMessage,
|
||||
typeof(PluginMethods), LogType.Error
|
||||
);
|
||||
}
|
||||
@@ -258,11 +258,11 @@ internal static class PluginMethods
|
||||
{
|
||||
if (data.IsSuccess)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Successfully loaded slash command : " + data.PluginName, LogType.Info, "\t\t > {Message}");
|
||||
Application.Logger.Log("Successfully loaded slash command : " + data.PluginName, LogType.Info, "\t\t > {Message}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Failed to load slash command : " + data.PluginName + " because " + data.ErrorMessage,
|
||||
Application.Logger.Log("Failed to load slash command : " + data.PluginName + " because " + data.ErrorMessage,
|
||||
typeof(PluginMethods), LogType.Error
|
||||
);
|
||||
}
|
||||
@@ -274,11 +274,11 @@ internal static class PluginMethods
|
||||
{
|
||||
if (data.IsSuccess)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Successfully loaded action : " + data.PluginName, LogType.Info, "\t\t > {Message}");
|
||||
Application.Logger.Log("Successfully loaded action : " + data.PluginName, LogType.Info, "\t\t > {Message}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Failed to load action : " + data.PluginName + " because " + data.ErrorMessage,
|
||||
Application.Logger.Log("Failed to load action : " + data.PluginName + " because " + data.ErrorMessage,
|
||||
typeof(PluginMethods), LogType.Error
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using DiscordBotCore;
|
||||
using DiscordBotCore.Interfaces;
|
||||
using DiscordBotCore.Interfaces.Modules;
|
||||
using DiscordBotCore.Modules;
|
||||
using DiscordBotCore.Others;
|
||||
using DiscordBotCore.Others.Actions;
|
||||
|
||||
@@ -45,15 +47,7 @@ namespace DiscordBot.Bot.Actions
|
||||
var modules = DiscordBotCore.Application.CurrentApplication.GetLoadedCoreModules();
|
||||
foreach (var module in modules)
|
||||
{
|
||||
Type moduleType = module.Key;
|
||||
List<object> moduleList = module.Value;
|
||||
|
||||
Console.WriteLine($"Module Type: {moduleType.Name}");
|
||||
|
||||
foreach (dynamic mod in moduleList)
|
||||
{
|
||||
Console.WriteLine($"Module: {mod.Name}");
|
||||
}
|
||||
Application.Logger.Log("Module: " + module.Key.ModuleName, this, LogType.Info);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,13 +128,7 @@ public class Plugin: ICommandAction
|
||||
case "load":
|
||||
if (pluginsLoaded)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Plugins already loaded", this, LogType.Warning);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Application.CurrentApplication.DiscordBotClient is null)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("DiscordBot is null", this, LogType.Warning);
|
||||
Application.Logger.Log("Plugins already loaded", this, LogType.Warning);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace DiscordBot.Bot.Commands;
|
||||
/// <summary>
|
||||
/// The help command
|
||||
/// </summary>
|
||||
internal class Help: DBCommand
|
||||
internal class Help: IDbCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Command name
|
||||
@@ -32,7 +32,7 @@ internal class Help: DBCommand
|
||||
/// <summary>
|
||||
/// Check if the command require administrator to be executed
|
||||
/// </summary>
|
||||
public bool requireAdmin => false;
|
||||
public bool RequireAdmin => false;
|
||||
|
||||
/// <summary>
|
||||
/// The main body of the command
|
||||
@@ -58,7 +58,7 @@ internal class Help: DBCommand
|
||||
var normalCommands = "";
|
||||
|
||||
foreach (var cmd in PluginLoader.Commands)
|
||||
if (cmd.requireAdmin)
|
||||
if (cmd.RequireAdmin)
|
||||
adminCommands += cmd.Command + " ";
|
||||
else
|
||||
normalCommands += cmd.Command + " ";
|
||||
|
||||
@@ -9,11 +9,11 @@ using DiscordBotCore.Others;
|
||||
|
||||
namespace DiscordBot.Bot.Commands.SlashCommands;
|
||||
|
||||
public class Help: DBSlashCommand
|
||||
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 CanUseDm => true;
|
||||
|
||||
public bool HasInteraction => false;
|
||||
|
||||
@@ -55,7 +55,7 @@ public class Help: DBSlashCommand
|
||||
return;
|
||||
}
|
||||
|
||||
embedBuilder.AddField("DM Usable:", slashCommand.canUseDM, true)
|
||||
embedBuilder.AddField("DM Usable:", slashCommand.CanUseDm, true)
|
||||
.WithDescription(slashCommand.Description);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,6 @@ public static class Installer
|
||||
|
||||
await Application.CurrentApplication.ApplicationEnvironmentVariables.SaveToFile();
|
||||
|
||||
Application.CurrentApplication.Logger.Log("Config Saved", typeof(Installer));
|
||||
Application.Logger.Log("Config Saved", typeof(Installer));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public class Program
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log(ex.ToString(), typeof(Program), LogType.Critical);
|
||||
Application.Logger.Log(ex.ToString(), typeof(Program), LogType.Critical);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ public class Program
|
||||
return;
|
||||
}
|
||||
|
||||
Application.CurrentApplication.Logger.SetOutFunction(AnsiConsole.MarkupLine);
|
||||
Application.Logger.SetOutFunction(AnsiConsole.MarkupLine);
|
||||
|
||||
|
||||
if (!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("ServerID") ||
|
||||
|
||||
@@ -6,12 +6,12 @@ using DiscordBotCore.Plugin;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using DiscordBotCore.Others.Exceptions;
|
||||
using DiscordBotCore.Interfaces.Logger;
|
||||
using DiscordBotCore.Modules;
|
||||
using System.Diagnostics;
|
||||
using DiscordBotCore.Interfaces.Modules;
|
||||
using DiscordBotCore.Online.Helpers;
|
||||
using DiscordBotCore.Others.Settings;
|
||||
|
||||
@@ -39,32 +39,6 @@ namespace DiscordBotCore
|
||||
|
||||
public CustomSettingsDictionary ApplicationEnvironmentVariables { get; private set; }
|
||||
public InternalActionManager InternalActionManager { get; private set; }
|
||||
|
||||
public ILogger Logger
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return _ModuleManager.GetModule<ILogger>();
|
||||
}
|
||||
catch (ModuleNotFoundException<ILogger> ex)
|
||||
{
|
||||
Console.WriteLine("No logger found");
|
||||
Console.WriteLine("Not having a valid logger is NOT an option. The default module will be downloaded from the official repo.");
|
||||
Console.WriteLine("Install the default one ? [y/n]");
|
||||
ConsoleKey response = Console.ReadKey().Key;
|
||||
if (response is ConsoleKey.Y)
|
||||
{
|
||||
Process.Start("DiscordBot", "--module-install LoggerModule");
|
||||
}
|
||||
|
||||
Environment.Exit(0);
|
||||
return null!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IPluginManager PluginManager { get; private set; }
|
||||
public Bot.App DiscordBotClient { get; internal set; }
|
||||
|
||||
@@ -88,9 +62,9 @@ namespace DiscordBotCore
|
||||
|
||||
CurrentApplication.ApplicationEnvironmentVariables = await CustomSettingsDictionary.CreateFromFile(_ConfigFile, true);
|
||||
|
||||
CurrentApplication.ApplicationEnvironmentVariables.Set("PluginFolder", _PluginsFolder);
|
||||
CurrentApplication.ApplicationEnvironmentVariables.Set("ResourceFolder", _ResourcesFolder);
|
||||
CurrentApplication.ApplicationEnvironmentVariables.Set("LogsFolder", _LogsFolder);
|
||||
CurrentApplication.ApplicationEnvironmentVariables.Add("PluginFolder", _PluginsFolder);
|
||||
CurrentApplication.ApplicationEnvironmentVariables.Add("ResourceFolder", _ResourcesFolder);
|
||||
CurrentApplication.ApplicationEnvironmentVariables.Add("LogsFolder", _LogsFolder);
|
||||
|
||||
|
||||
CurrentApplication._ModuleManager = new ModuleManager();
|
||||
@@ -117,7 +91,52 @@ namespace DiscordBotCore
|
||||
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<Type, List<object>> GetLoadedCoreModules() => _ModuleManager.LoadedModules.AsReadOnly();
|
||||
public static class Logger
|
||||
{
|
||||
public static async void LogException(Exception ex, object sender, bool fullStackTrace = false)
|
||||
{
|
||||
var loggerModule = CurrentApplication._ModuleManager.GetModule(ModuleType.Logger);
|
||||
await CurrentApplication._ModuleManager.InvokeMethod(loggerModule.Value, loggerModule.Key.MethodMapping["BaseLogException"], [ex, sender, fullStackTrace]);
|
||||
}
|
||||
|
||||
public static async void Log(string message)
|
||||
{
|
||||
var loggerModule = CurrentApplication._ModuleManager.GetModule(ModuleType.Logger);
|
||||
await CurrentApplication._ModuleManager.InvokeMethod(loggerModule.Value, loggerModule.Key.MethodMapping["BaseLog"], [message]);
|
||||
}
|
||||
|
||||
public static async void Log(string message, LogType logType, string format)
|
||||
{
|
||||
var loggerModule = CurrentApplication._ModuleManager.GetModule(ModuleType.Logger);
|
||||
await CurrentApplication._ModuleManager.InvokeMethod(loggerModule.Value, loggerModule.Key.MethodMapping["LogWithTypeAndFormat"], [message, logType, format]);
|
||||
}
|
||||
|
||||
public static async void Log(string message, LogType logType)
|
||||
{
|
||||
var loggerModule = CurrentApplication._ModuleManager.GetModule(ModuleType.Logger);
|
||||
await CurrentApplication._ModuleManager.InvokeMethod(loggerModule.Value, loggerModule.Key.MethodMapping["LogWithType"], [message, logType]);
|
||||
}
|
||||
|
||||
public static async void Log(string message, object sender)
|
||||
{
|
||||
var loggerModule = CurrentApplication._ModuleManager.GetModule(ModuleType.Logger);
|
||||
await CurrentApplication._ModuleManager.InvokeMethod(loggerModule.Value, loggerModule.Key.MethodMapping["LogWithSender"], [message, sender]);
|
||||
}
|
||||
|
||||
public static async void Log(string message, object sender, LogType type)
|
||||
{
|
||||
var loggerModule = CurrentApplication._ModuleManager.GetModule(ModuleType.Logger);
|
||||
await CurrentApplication._ModuleManager.InvokeMethod(loggerModule.Value, loggerModule.Key.MethodMapping["LogWithTypeAndSender"], [message, sender, type]);
|
||||
}
|
||||
|
||||
public static async void SetOutFunction(Action<string> outFunction)
|
||||
{
|
||||
var loggerModule = CurrentApplication._ModuleManager.GetModule(ModuleType.Logger);
|
||||
await CurrentApplication._ModuleManager.InvokeMethod(loggerModule.Value, loggerModule.Key.MethodMapping["SetPrintFunction"], [outFunction]);
|
||||
}
|
||||
}
|
||||
|
||||
public ReadOnlyDictionary<ModuleData, IModule> GetLoadedCoreModules() => _ModuleManager.Modules.AsReadOnly();
|
||||
|
||||
public static string GetResourceFullPath(string path)
|
||||
{
|
||||
|
||||
@@ -107,7 +107,7 @@ public class App
|
||||
if (arg.Message.Contains("401"))
|
||||
{
|
||||
Application.CurrentApplication.ApplicationEnvironmentVariables.Remove("token");
|
||||
Application.CurrentApplication.Logger.Log("The token is invalid.", this, LogType.Critical);
|
||||
Application.Logger.Log("The token is invalid.", this, LogType.Critical);
|
||||
await Application.CurrentApplication.ApplicationEnvironmentVariables.SaveToFile();
|
||||
await Task.Delay(3000);
|
||||
|
||||
@@ -124,7 +124,7 @@ public class App
|
||||
|
||||
private Task LoggedIn()
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Successfully Logged In", this);
|
||||
Application.Logger.Log("Successfully Logged In", this);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -134,12 +134,12 @@ public class App
|
||||
{
|
||||
case LogSeverity.Error:
|
||||
case LogSeverity.Critical:
|
||||
Application.CurrentApplication.Logger.Log(message.Message, this, LogType.Error);
|
||||
Application.Logger.Log(message.Message, this, LogType.Error);
|
||||
break;
|
||||
|
||||
case LogSeverity.Info:
|
||||
case LogSeverity.Debug:
|
||||
Application.CurrentApplication.Logger.Log(message.Message, this, LogType.Info);
|
||||
Application.Logger.Log(message.Message, this, LogType.Info);
|
||||
|
||||
|
||||
break;
|
||||
|
||||
@@ -51,12 +51,12 @@ internal class CommandHandler
|
||||
throw new Exception("Failed to run command !");
|
||||
|
||||
if (arg.Channel is SocketDMChannel)
|
||||
plugin.ExecuteDM(arg);
|
||||
plugin.ExecuteDm(arg);
|
||||
else plugin.ExecuteServer(arg);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Application.CurrentApplication.Logger.LogException(ex, this);
|
||||
Application.Logger.LogException(ex, this);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
@@ -91,7 +91,7 @@ internal class CommandHandler
|
||||
|
||||
await _commandService.ExecuteAsync(context, argPos, null);
|
||||
|
||||
DBCommand? plugin;
|
||||
IDbCommand? plugin;
|
||||
var cleanMessage = "";
|
||||
|
||||
if (message.HasMentionPrefix(_client.CurrentUser, ref argPos))
|
||||
@@ -129,7 +129,7 @@ internal class CommandHandler
|
||||
if (plugin is null)
|
||||
return;
|
||||
|
||||
if (plugin.requireAdmin && !context.Message.Author.IsAdmin())
|
||||
if (plugin.RequireAdmin && !context.Message.Author.IsAdmin())
|
||||
return;
|
||||
|
||||
var split = cleanMessage.Split(' ');
|
||||
@@ -140,19 +140,19 @@ internal class CommandHandler
|
||||
|
||||
DbCommandExecutingArguments cmd = new(context, cleanMessage, split[0], argsClean);
|
||||
|
||||
Application.CurrentApplication.Logger.Log(
|
||||
Application.Logger.Log(
|
||||
$"User ({context.User.Username}) from Guild \"{context.Guild.Name}\" executed command \"{cmd.CleanContent}\"",
|
||||
this,
|
||||
LogType.Info
|
||||
);
|
||||
|
||||
if (context.Channel is SocketDMChannel)
|
||||
plugin.ExecuteDM(cmd);
|
||||
plugin.ExecuteDm(cmd);
|
||||
else plugin.ExecuteServer(cmd);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Application.CurrentApplication.Logger.LogException(ex, this);
|
||||
Application.Logger.LogException(ex, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using DiscordBotCore.Others;
|
||||
|
||||
namespace DiscordBotCore.Interfaces;
|
||||
|
||||
public interface DBCommand
|
||||
public interface IDbCommand
|
||||
{
|
||||
/// <summary>
|
||||
/// Command to be executed
|
||||
@@ -30,7 +30,7 @@ public interface DBCommand
|
||||
/// <summary>
|
||||
/// true if the command requre admin, otherwise false
|
||||
/// </summary>
|
||||
bool requireAdmin { get; }
|
||||
bool RequireAdmin { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The main body of the command. This is what is executed when user calls the command in Server
|
||||
@@ -44,7 +44,7 @@ public interface DBCommand
|
||||
/// The main body of the command. This is what is executed when user calls the command in DM
|
||||
/// </summary>
|
||||
/// <param name="args">The disocrd Context</param>
|
||||
void ExecuteDM(DbCommandExecutingArguments args)
|
||||
void ExecuteDm(DbCommandExecutingArguments args)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace DiscordBotCore.Interfaces;
|
||||
|
||||
public interface DBEvent
|
||||
public interface IDbEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the event
|
||||
@@ -6,11 +6,11 @@ using Discord.WebSocket;
|
||||
|
||||
namespace DiscordBotCore.Interfaces;
|
||||
|
||||
public interface DBSlashCommand
|
||||
public interface IDbSlashCommand
|
||||
{
|
||||
string Name { get; }
|
||||
string Description { get; }
|
||||
bool canUseDM { get; }
|
||||
bool CanUseDm { get; }
|
||||
bool HasInteraction { get; }
|
||||
|
||||
List<SlashCommandOptionBuilder> Options { get; }
|
||||
@@ -18,7 +18,7 @@ public interface DBSlashCommand
|
||||
void ExecuteServer(SocketSlashCommand context)
|
||||
{ }
|
||||
|
||||
void ExecuteDM(SocketSlashCommand context) { }
|
||||
void ExecuteDm(SocketSlashCommand context) { }
|
||||
|
||||
Task ExecuteInteraction(SocketInteraction interaction) => Task.CompletedTask;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
using DiscordBotCore.Others;
|
||||
|
||||
using System;
|
||||
|
||||
namespace DiscordBotCore.Interfaces.Logger
|
||||
{
|
||||
public interface ILogMessage
|
||||
{
|
||||
public string Message { get; protected set; }
|
||||
public DateTime ThrowTime { get; protected set; }
|
||||
public string SenderName { get; protected set; }
|
||||
public LogType LogMessageType { get; protected set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using DiscordBotCore.Interfaces.Modules;
|
||||
using DiscordBotCore.Others;
|
||||
|
||||
using System;
|
||||
|
||||
namespace DiscordBotCore.Interfaces.Logger
|
||||
{
|
||||
public interface ILogger : IBaseModule
|
||||
{
|
||||
public struct FormattedMessage {
|
||||
public string Message;
|
||||
public LogType Type;
|
||||
}
|
||||
|
||||
string LogMessageFormat { get; set; }
|
||||
|
||||
void Log(string message);
|
||||
void Log(string message, LogType logType);
|
||||
void Log(string message, LogType logType, string format);
|
||||
void Log(string message, object Sender);
|
||||
void Log(string message, object Sender, LogType type);
|
||||
void LogException(Exception exception, object Sender, bool logFullStack = false);
|
||||
|
||||
void SetOutFunction(Action<string> outFunction);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace DiscordBotCore.Interfaces.Modules
|
||||
{
|
||||
public interface IBaseModule
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,20 @@
|
||||
|
||||
namespace DiscordBotCore.Interfaces.Modules
|
||||
{
|
||||
public interface IModule<T> where T : IBaseModule
|
||||
|
||||
public enum ModuleType
|
||||
{
|
||||
Logger,
|
||||
Other
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Define a module.
|
||||
/// </summary>
|
||||
public interface IModule
|
||||
{
|
||||
public ModuleType ModuleType { get; }
|
||||
public string Name { get; }
|
||||
public T Module { get; }
|
||||
public Task Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ namespace DiscordBotCore.Interfaces.PluginManager
|
||||
{
|
||||
public string BaseUrl { get; set; }
|
||||
public string Branch { get; set; }
|
||||
|
||||
Task AppendPluginToDatabase(PluginInfo pluginData);
|
||||
Task CheckForUpdates();
|
||||
Task ExecutePluginInstallScripts(List<OnlineScriptDependencyInfo> listOfDependencies);
|
||||
@@ -24,7 +23,6 @@ namespace DiscordBotCore.Interfaces.PluginManager
|
||||
Task<bool> MarkPluginToUninstall(string pluginName);
|
||||
Task RemovePluginFromDatabase(string pluginName);
|
||||
Task UninstallMarkedPlugins();
|
||||
|
||||
Task SetEnabledStatus(string pluginName, bool status);
|
||||
}
|
||||
}
|
||||
@@ -35,9 +35,9 @@ internal class Loader
|
||||
}
|
||||
}
|
||||
|
||||
await LoadEverythingOfType<DBEvent>();
|
||||
await LoadEverythingOfType<DBCommand>();
|
||||
await LoadEverythingOfType<DBSlashCommand>();
|
||||
await LoadEverythingOfType<IDbEvent>();
|
||||
await LoadEverythingOfType<IDbCommand>();
|
||||
await LoadEverythingOfType<IDbSlashCommand>();
|
||||
await LoadEverythingOfType<ICommandAction>();
|
||||
}
|
||||
|
||||
@@ -60,9 +60,9 @@ internal class Loader
|
||||
|
||||
var pluginType = plugin switch
|
||||
{
|
||||
DBEvent => PluginType.EVENT,
|
||||
DBCommand => PluginType.COMMAND,
|
||||
DBSlashCommand => PluginType.SLASH_COMMAND,
|
||||
IDbEvent => PluginType.EVENT,
|
||||
IDbCommand => PluginType.COMMAND,
|
||||
IDbSlashCommand => PluginType.SLASH_COMMAND,
|
||||
ICommandAction => PluginType.ACTION,
|
||||
_ => PluginType.UNKNOWN
|
||||
};
|
||||
|
||||
@@ -6,23 +6,24 @@ using System.Threading.Tasks;
|
||||
|
||||
using DiscordBotCore.Interfaces.Modules;
|
||||
using System.Reflection;
|
||||
using DiscordBotCore.Modules;
|
||||
|
||||
namespace DiscordBotCore.Loaders
|
||||
{
|
||||
internal class ModuleLoader
|
||||
{
|
||||
private readonly string _ModuleFolder;
|
||||
private readonly List<ModuleData> _ModuleData;
|
||||
|
||||
public ModuleLoader(string moduleFolder)
|
||||
public ModuleLoader(List<ModuleData> moduleFolder)
|
||||
{
|
||||
_ModuleFolder = moduleFolder;
|
||||
Directory.CreateDirectory(moduleFolder);
|
||||
_ModuleData = moduleFolder;
|
||||
}
|
||||
|
||||
public Task LoadFileModules()
|
||||
{
|
||||
var files = Directory.GetFiles(_ModuleFolder, "*.dll");
|
||||
foreach (var file in files)
|
||||
var paths = _ModuleData.Select(module => module.ModulePath);
|
||||
|
||||
foreach (var file in paths)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -37,20 +38,20 @@ namespace DiscordBotCore.Loaders
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<List<IModule<T>>> LoadModules<T>() where T : IBaseModule
|
||||
public Task<List<IModule>> LoadModules()
|
||||
{
|
||||
var moduleType = typeof(IModule<T>);
|
||||
var moduleType = typeof(IModule);
|
||||
var moduleTypes = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(s => s.GetTypes())
|
||||
.Where(p => moduleType.IsAssignableFrom(p) && !p.IsInterface);
|
||||
|
||||
var modules = new List<IModule<T>>();
|
||||
var modules = new List<IModule>();
|
||||
foreach (var module in moduleTypes)
|
||||
{
|
||||
try
|
||||
{
|
||||
var instance = (IModule<T>?)Activator.CreateInstance(module);
|
||||
if (instance == null)
|
||||
var instance = (IModule?)Activator.CreateInstance(module);
|
||||
if (instance is null)
|
||||
{
|
||||
Console.WriteLine($"Error loading module {module.Name}: Could not create instance");
|
||||
continue;
|
||||
|
||||
@@ -26,9 +26,9 @@ public class PluginLoader
|
||||
public SlashCommandLoaded? OnSlashCommandLoaded;
|
||||
public ActionLoaded? OnActionLoaded;
|
||||
|
||||
public static List<DBCommand> Commands { get; private set; } = new List<DBCommand>();
|
||||
public static List<DBEvent> Events { get; private set; } = new List<DBEvent>();
|
||||
public static List<DBSlashCommand> SlashCommands { get; private set; } = new List<DBSlashCommand>();
|
||||
public static List<IDbCommand> Commands { get; private set; } = new List<IDbCommand>();
|
||||
public static List<IDbEvent> Events { get; private set; } = new List<IDbEvent>();
|
||||
public static List<IDbSlashCommand> SlashCommands { get; private set; } = new List<IDbSlashCommand>();
|
||||
public static List<ICommandAction> Actions { get; private set; } = new List<ICommandAction>();
|
||||
|
||||
public PluginLoader(DiscordSocketClient discordSocketClient)
|
||||
@@ -41,7 +41,7 @@ public class PluginLoader
|
||||
|
||||
if (_Client == null)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Discord client is null", this, LogType.Error);
|
||||
Application.Logger.Log("Discord client is null", this, LogType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class PluginLoader
|
||||
SlashCommands.Clear();
|
||||
Actions.Clear();
|
||||
|
||||
Application.CurrentApplication.Logger.Log("Loading plugins...", this);
|
||||
Application.Logger.Log("Loading plugins...", this);
|
||||
|
||||
var loader = new Loader();
|
||||
|
||||
@@ -62,7 +62,7 @@ public class PluginLoader
|
||||
|
||||
private void FileLoadedException(FileLoaderResult result)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log(result.ErrorMessage, this, LogType.Error);
|
||||
Application.Logger.Log(result.ErrorMessage, this, LogType.Error);
|
||||
}
|
||||
|
||||
private async void OnPluginLoaded(PluginLoadResultData result)
|
||||
@@ -81,31 +81,31 @@ public class PluginLoader
|
||||
|
||||
break;
|
||||
case PluginType.COMMAND:
|
||||
Commands.Add((DBCommand)result.Plugin);
|
||||
Commands.Add((IDbCommand)result.Plugin);
|
||||
OnCommandLoaded?.Invoke(result);
|
||||
break;
|
||||
case PluginType.EVENT:
|
||||
if (this.TryStartEvent((DBEvent)result.Plugin))
|
||||
if (this.TryStartEvent((IDbEvent)result.Plugin))
|
||||
{
|
||||
Events.Add((DBEvent)result.Plugin);
|
||||
Events.Add((IDbEvent)result.Plugin);
|
||||
OnEventLoaded?.Invoke(result);
|
||||
}
|
||||
|
||||
break;
|
||||
case PluginType.SLASH_COMMAND:
|
||||
if (await this.TryStartSlashCommand((DBSlashCommand)result.Plugin))
|
||||
if (await this.TryStartSlashCommand((IDbSlashCommand)result.Plugin))
|
||||
{
|
||||
if(((DBSlashCommand)result.Plugin).HasInteraction)
|
||||
_Client.InteractionCreated += ((DBSlashCommand)result.Plugin).ExecuteInteraction;
|
||||
SlashCommands.Add((DBSlashCommand)result.Plugin);
|
||||
if(((IDbSlashCommand)result.Plugin).HasInteraction)
|
||||
_Client.InteractionCreated += ((IDbSlashCommand)result.Plugin).ExecuteInteraction;
|
||||
SlashCommands.Add((IDbSlashCommand)result.Plugin);
|
||||
OnSlashCommandLoaded?.Invoke(result);
|
||||
}
|
||||
else
|
||||
Application.CurrentApplication.Logger.Log($"Failed to start slash command {result.PluginName}", this, LogType.Error);
|
||||
Application.Logger.Log($"Failed to start slash command {result.PluginName}", this, LogType.Error);
|
||||
break;
|
||||
case PluginType.UNKNOWN:
|
||||
default:
|
||||
Application.CurrentApplication.Logger.Log("Unknown plugin type", this, LogType.Error);
|
||||
Application.Logger.Log("Unknown plugin type", this, LogType.Error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace DiscordBotCore.Loaders;
|
||||
|
||||
internal static class PluginLoaderExtensions
|
||||
{
|
||||
internal static bool TryStartEvent(this PluginLoader pluginLoader, DBEvent? dbEvent)
|
||||
internal static bool TryStartEvent(this PluginLoader pluginLoader, IDbEvent? dbEvent)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -28,13 +28,13 @@ internal static class PluginLoaderExtensions
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log($"Error starting event {dbEvent.Name}: {e.Message}", typeof(PluginLoader), LogType.Error);
|
||||
Application.CurrentApplication.Logger.LogException(e, typeof(PluginLoader));
|
||||
Application.Logger.Log($"Error starting event {dbEvent.Name}: {e.Message}", typeof(PluginLoader), LogType.Error);
|
||||
Application.Logger.LogException(e, typeof(PluginLoader));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal static async Task<bool> TryStartSlashCommand(this PluginLoader pluginLoader, DBSlashCommand? dbSlashCommand)
|
||||
internal static async Task<bool> TryStartSlashCommand(this PluginLoader pluginLoader, IDbSlashCommand? dbSlashCommand)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -53,7 +53,7 @@ internal static class PluginLoaderExtensions
|
||||
builder.WithDescription(dbSlashCommand.Description);
|
||||
builder.Options = dbSlashCommand.Options;
|
||||
|
||||
if (dbSlashCommand.canUseDM)
|
||||
if (dbSlashCommand.CanUseDm)
|
||||
builder.WithContextTypes(InteractionContextType.BotDm, InteractionContextType.Guild);
|
||||
else
|
||||
builder.WithContextTypes(InteractionContextType.Guild);
|
||||
@@ -64,7 +64,7 @@ internal static class PluginLoaderExtensions
|
||||
|
||||
if (!result)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log($"Failed to enable slash command {dbSlashCommand.Name} for guild {guildId}", typeof(PluginLoader), LogType.Error);
|
||||
Application.Logger.Log($"Failed to enable slash command {dbSlashCommand.Name} for guild {guildId}", typeof(PluginLoader), LogType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ internal static class PluginLoaderExtensions
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log($"Error starting slash command {dbSlashCommand.Name}: {e.Message}", typeof(PluginLoader), LogType.Error);
|
||||
Application.Logger.Log($"Error starting slash command {dbSlashCommand.Name}: {e.Message}", typeof(PluginLoader), LogType.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ internal static class PluginLoaderExtensions
|
||||
SocketGuild? guild = pluginLoader._Client.GetGuild(guildId);
|
||||
if (guild is null)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Failed to get guild with ID " + guildId, typeof(PluginLoader), LogType.Error);
|
||||
Application.Logger.Log("Failed to get guild with ID " + guildId, typeof(PluginLoader), LogType.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
19
DiscordBotCore/Modules/ModuleData.cs
Normal file
19
DiscordBotCore/Modules/ModuleData.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DiscordBotCore.Modules;
|
||||
|
||||
public class ModuleData
|
||||
{
|
||||
public string ModuleName { get; set; }
|
||||
public string ModulePath { get; set; }
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
public IDictionary<string, string> MethodMapping { get; set; }
|
||||
|
||||
public ModuleData(string moduleName, string modulePath, IDictionary<string, string> methodMapping, bool isEnabled)
|
||||
{
|
||||
ModuleName = moduleName;
|
||||
ModulePath = modulePath;
|
||||
MethodMapping = methodMapping;
|
||||
IsEnabled = isEnabled;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using DiscordBotCore.Online;
|
||||
@@ -11,20 +8,24 @@ namespace DiscordBotCore.Modules
|
||||
{
|
||||
public class ModuleDownloader
|
||||
{
|
||||
private string _moduleName;
|
||||
private readonly string _baseUrl = "https://raw.githubusercontent.com/andreitdr/SethPlugins/tests/Modules/";
|
||||
private readonly string _moduleFolder = "./Data/Modules";
|
||||
private readonly string _ModuleName;
|
||||
private const string _BaseUrl = "https://raw.githubusercontent.com/andreitdr/SethPlugins/tests/Modules/";
|
||||
|
||||
public ModuleDownloader(string moduleName)
|
||||
{
|
||||
_moduleName = moduleName;
|
||||
_ModuleName = moduleName;
|
||||
}
|
||||
|
||||
public async Task DownloadModule(IProgress<float> progressToWrite)
|
||||
{
|
||||
Directory.CreateDirectory(_moduleFolder);
|
||||
string url = _baseUrl + _moduleName + ".dll";
|
||||
await ServerCom.DownloadFileAsync(url, _moduleFolder + "/" + _moduleName + ".dll", progressToWrite);
|
||||
string? moduleFolder = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("ModuleFolder");
|
||||
|
||||
if(moduleFolder is null)
|
||||
throw new DirectoryNotFoundException("Module folder not found"); // Should never happen
|
||||
|
||||
Directory.CreateDirectory(moduleFolder);
|
||||
string url = _BaseUrl + _ModuleName + ".dll";
|
||||
await ServerCom.DownloadFileAsync(url, moduleFolder + "/" + _ModuleName + ".dll", progressToWrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using DiscordBotCore.Interfaces.Logger;
|
||||
using DiscordBotCore.Interfaces.Modules;
|
||||
using DiscordBotCore.Loaders;
|
||||
using DiscordBotCore.Others.Exceptions;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace DiscordBotCore.Modules
|
||||
{
|
||||
internal class ModuleManager
|
||||
{
|
||||
private static readonly string _BaseModuleFolder = "./Data/Modules";
|
||||
|
||||
private readonly string _ModuleFolder;
|
||||
internal Dictionary<Type, List<object>> LoadedModules { get; }
|
||||
|
||||
public ModuleManager(string moduleFolder)
|
||||
{
|
||||
_ModuleFolder = moduleFolder;
|
||||
LoadedModules = new Dictionary<Type, List<object>>();
|
||||
}
|
||||
private static readonly string _BaseModuleConfig = "./Data/Resources/modules.json";
|
||||
internal Dictionary<ModuleData, IModule> Modules { get; set; }
|
||||
|
||||
public ModuleManager()
|
||||
{
|
||||
_ModuleFolder = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("ModuleFolder", _BaseModuleFolder);
|
||||
LoadedModules = new Dictionary<Type, List<object>>();
|
||||
Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("ModuleFolder", _BaseModuleFolder);
|
||||
Modules = new Dictionary<ModuleData, IModule>();
|
||||
}
|
||||
|
||||
public T GetModule<T>() where T : IBaseModule
|
||||
public KeyValuePair<ModuleData, IModule> GetModule(string moduleName)
|
||||
{
|
||||
if(!LoadedModules.ContainsKey(typeof(T)))
|
||||
throw new ModuleNotFoundException<T>();
|
||||
return Modules.FirstOrDefault(module => module.Key.ModuleName == moduleName);
|
||||
}
|
||||
|
||||
if (!LoadedModules[typeof(T)].Any())
|
||||
throw new ModuleNotFoundException<T>();
|
||||
|
||||
IModule<T> module = (IModule<T>)LoadedModules[typeof(T)][0];
|
||||
return module.Module;
|
||||
public KeyValuePair<ModuleData, IModule> GetModule(ModuleType moduleType)
|
||||
{
|
||||
return Modules.First(module => module.Value.ModuleType == moduleType);
|
||||
}
|
||||
|
||||
public async Task LoadModules()
|
||||
{
|
||||
ModuleLoader loader = new ModuleLoader(_ModuleFolder);
|
||||
await loader.LoadFileModules();
|
||||
string moduleConfigPath = Application.CurrentApplication.ApplicationEnvironmentVariables
|
||||
.Get<string>("ModuleConfig", _BaseModuleConfig);
|
||||
|
||||
string moduleConfigFile = await File.ReadAllTextAsync(moduleConfigPath);
|
||||
List<ModuleData>? listOfModuleData = JsonConvert.DeserializeObject<List<ModuleData>>(moduleConfigFile);
|
||||
|
||||
var loggers = await loader.LoadModules<ILogger>();
|
||||
foreach (var logger in loggers)
|
||||
if(listOfModuleData is null)
|
||||
return;
|
||||
|
||||
if (!listOfModuleData.Any())
|
||||
{
|
||||
await logger.Initialize();
|
||||
Console.WriteLine("Module Loaded: " + logger.Name);
|
||||
return;
|
||||
}
|
||||
|
||||
LoadedModules.Add(typeof(ILogger), loggers.Cast<object>().ToList());
|
||||
ModuleLoader moduleLoader = new ModuleLoader(listOfModuleData);
|
||||
await moduleLoader.LoadFileModules();
|
||||
var modules = await moduleLoader.LoadModules();
|
||||
|
||||
foreach (var module in modules)
|
||||
{
|
||||
|
||||
ModuleData? moduleData = listOfModuleData.FirstOrDefault(data => data.ModuleName == module.Name);
|
||||
|
||||
if (moduleData is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (moduleData.IsEnabled)
|
||||
{
|
||||
await module.Initialize(); // TODO: Add error handling
|
||||
Modules.Add(moduleData, module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task InvokeMethod(string moduleName, string methodName, object[] parameters)
|
||||
{
|
||||
IModule module = GetModule(moduleName).Value;
|
||||
var method = module.GetType().GetMethod(methodName);
|
||||
|
||||
if (method is null)
|
||||
{
|
||||
throw new Exception("Method not found"); // TODO: Add custom exception
|
||||
}
|
||||
|
||||
await Task.Run(() => method.Invoke(module, parameters));
|
||||
}
|
||||
|
||||
public async Task InvokeMethod(IModule module, string methodName, object[] parameters)
|
||||
{
|
||||
var method = module.GetType().GetMethod(methodName);
|
||||
|
||||
if (method is null)
|
||||
{
|
||||
throw new Exception($"Method not found {methodName}");
|
||||
}
|
||||
|
||||
await Task.Run(() => method.Invoke(module, parameters));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ public class PluginManager : IPluginManager
|
||||
{
|
||||
if (await pluginUpdater.HasUpdate(plugin.PluginName))
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Updating plugin: " + plugin.PluginName, this, LogType.Info);
|
||||
Application.Logger.Log("Updating plugin: " + plugin.PluginName, this, LogType.Info);
|
||||
await pluginUpdater.UpdatePlugin(plugin.PluginName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public class InternalActionManager
|
||||
if (this.Actions.ContainsKey(action.ActionName))
|
||||
{
|
||||
// This should never happen. If it does, log it and return
|
||||
Application.CurrentApplication.Logger.Log($"Action {action.ActionName} already exists", this, LogType.Error);
|
||||
Application.Logger.Log($"Action {action.ActionName} already exists", this, LogType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class InternalActionManager
|
||||
{
|
||||
if (!Actions.ContainsKey(actionName))
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log($"Action {actionName} not found", this, LogType.Error);
|
||||
Application.Logger.Log($"Action {actionName} not found", this, LogType.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class InternalActionManager
|
||||
{
|
||||
if (Actions[actionName].RunType == InternalActionRunType.OnStartup)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log($"Action {actionName} is not executable", this, LogType.Error);
|
||||
Application.Logger.Log($"Action {actionName} is not executable", this, LogType.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public class InternalActionManager
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log(e.Message, type: LogType.Error, Sender: this);
|
||||
Application.Logger.Log(e.Message, type: LogType.Error, sender: this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ public static class ArchiveManager
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log(ex.Message, typeof(ArchiveManager), LogType.Error); // Write the error to a file
|
||||
Application.Logger.Log(ex.Message, typeof(ArchiveManager), LogType.Error); // Write the error to a file
|
||||
await Task.Delay(100);
|
||||
return await ReadFromPakAsync(fileName, archFile);
|
||||
}
|
||||
@@ -141,7 +141,7 @@ public static class ArchiveManager
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log(ex.Message, typeof(ArchiveManager), LogType.Error);
|
||||
Application.Logger.Log(ex.Message, typeof(ArchiveManager), LogType.Error);
|
||||
}
|
||||
|
||||
currentZipFile++;
|
||||
@@ -176,7 +176,7 @@ public static class ArchiveManager
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log(ex.Message, typeof(ArchiveManager), LogType.Error);
|
||||
Application.Logger.Log(ex.Message, typeof(ArchiveManager), LogType.Error);
|
||||
}
|
||||
|
||||
await Task.Delay(10);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -35,14 +37,14 @@ public class CustomSettingsDictionary : CustomSettingsDictionaryBase<string, obj
|
||||
|
||||
public override List<T> GetList<T>(string key, List<T> defaultValue)
|
||||
{
|
||||
List<T> result = base.GetList(key, defaultValue);
|
||||
List<T> value = base.GetList(key, defaultValue);
|
||||
|
||||
if (_EnableAutoAddOnGetWithDefault && defaultValue.All(result.Contains))
|
||||
if (_EnableAutoAddOnGetWithDefault && value.All(defaultValue.Contains))
|
||||
{
|
||||
Add(key,defaultValue);
|
||||
Add(key, defaultValue);
|
||||
}
|
||||
|
||||
return result;
|
||||
return value;
|
||||
}
|
||||
|
||||
public override async Task LoadFromFile()
|
||||
@@ -71,10 +73,20 @@ public class CustomSettingsDictionary : CustomSettingsDictionaryBase<string, obj
|
||||
else if (kvp.Value is JArray nestedJArray)
|
||||
{
|
||||
dict[kvp.Key] = nestedJArray.ToObject<List<object>>();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (kvp.Value.Type == JTokenType.Integer)
|
||||
dict[kvp.Key] = kvp.Value.Value<int>();
|
||||
else if (kvp.Value.Type == JTokenType.Float)
|
||||
dict[kvp.Key] = kvp.Value.Value<float>();
|
||||
else if (kvp.Value.Type == JTokenType.Boolean)
|
||||
dict[kvp.Key] = kvp.Value.Value<bool>();
|
||||
else if (kvp.Value.Type == JTokenType.String)
|
||||
dict[kvp.Key] = kvp.Value.Value<string>();
|
||||
else if (kvp.Value.Type == JTokenType.Date)
|
||||
dict[kvp.Key] = kvp.Value.Value<DateTime>();
|
||||
else
|
||||
dict[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,27 @@ public abstract class CustomSettingsDictionaryBase<TKey,TValue> : ICustomSetting
|
||||
return default;
|
||||
}
|
||||
|
||||
public virtual IDictionary<TSubKey, TSubValue> GetDictionary<TSubKey, TSubValue>(TKey key)
|
||||
{
|
||||
if (_InternalDictionary.TryGetValue(key, out var value))
|
||||
{
|
||||
if (value is not IDictionary)
|
||||
{
|
||||
throw new Exception("The value is not a dictionary");
|
||||
}
|
||||
|
||||
var dictionary = new Dictionary<TSubKey, TSubValue>();
|
||||
foreach (DictionaryEntry item in (IDictionary)value)
|
||||
{
|
||||
dictionary.Add((TSubKey)Convert.ChangeType(item.Key, typeof(TSubKey)), (TSubValue)Convert.ChangeType(item.Value, typeof(TSubValue)));
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
return new Dictionary<TSubKey, TSubValue>();
|
||||
}
|
||||
|
||||
public virtual List<T> GetList<T>(TKey key, List<T> defaultValue)
|
||||
{
|
||||
if(_InternalDictionary.TryGetValue(key, out var value))
|
||||
@@ -67,9 +88,9 @@ public abstract class CustomSettingsDictionaryBase<TKey,TValue> : ICustomSetting
|
||||
}
|
||||
|
||||
var list = new List<T>();
|
||||
foreach (var item in (IList)value)
|
||||
foreach (object? item in (IList)value)
|
||||
{
|
||||
list.Add(ConvertValue<T>(item));
|
||||
list.Add((T)Convert.ChangeType(item, typeof(T)));
|
||||
}
|
||||
|
||||
return list;
|
||||
@@ -141,20 +162,4 @@ public abstract class CustomSettingsDictionaryBase<TKey,TValue> : ICustomSetting
|
||||
public abstract Task SaveToFile();
|
||||
|
||||
public abstract Task LoadFromFile();
|
||||
|
||||
protected virtual T? ConvertValue<T>(object value)
|
||||
{
|
||||
|
||||
if (typeof(T) == typeof(ulong) && value is long longValue)
|
||||
{
|
||||
return (T)(object)Convert.ToUInt64(longValue);
|
||||
}
|
||||
|
||||
if (typeof(T).IsEnum && value is string stringValue)
|
||||
{
|
||||
return (T)Enum.Parse(typeof(T), stringValue);
|
||||
}
|
||||
|
||||
return (T)Convert.ChangeType(value, typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
using DiscordBotCore;
|
||||
using DiscordBotCore.Interfaces.Logger;
|
||||
using DiscordBotCore.Interfaces.Modules;
|
||||
using DiscordBotCore.Interfaces.Modules;
|
||||
using DiscordBotCore.Others;
|
||||
|
||||
namespace LoggerModule
|
||||
{
|
||||
public class Entry : IModule<ILogger>
|
||||
public class Entry : IModule
|
||||
{
|
||||
public string Name => "Logger Module";
|
||||
public string Name => "LoggerModule";
|
||||
public ModuleType ModuleType => ModuleType.Logger;
|
||||
|
||||
const string _LogFolder = "./Data/Logs/";
|
||||
const string _LogFormat = "{ThrowTime} {SenderName} {Message}";
|
||||
|
||||
public ILogger Module { get; private set; }
|
||||
public ILogger Module { get; private set; } = null!;
|
||||
|
||||
public Task Initialize()
|
||||
{
|
||||
@@ -18,5 +19,20 @@ namespace LoggerModule
|
||||
Module = logger;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void SetOutFunction(Action<string> outFunction)
|
||||
{
|
||||
Module.SetOutFunction(outFunction);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void LogMessage(string message) => Module.Log(message);
|
||||
public void LogMessageWithTypeAndFormat(string message, LogType logType, string format) => Module.Log(message, logType, format);
|
||||
public void LogMessageWithType(string message, LogType logType) => Module.Log(message, logType);
|
||||
public void LogMessageWithSender(string message, object Sender) => Module.Log(message, Sender);
|
||||
public void LogMessageWithTypeAndSender(string message, object Sender, LogType type) => Module.Log(message, Sender, type);
|
||||
public void LogExceptionWithSenderAndFullStack(Exception exception, object Sender, bool logFullStack = false) => Module.LogException(exception, Sender, logFullStack);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
12
Modules/LoggerModule/ILogMessage.cs
Normal file
12
Modules/LoggerModule/ILogMessage.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using DiscordBotCore.Others;
|
||||
|
||||
namespace LoggerModule;
|
||||
|
||||
public interface ILogMessage
|
||||
{
|
||||
public string Message { get; protected set; }
|
||||
public DateTime ThrowTime { get; protected set; }
|
||||
public string SenderName { get; protected set; }
|
||||
public LogType LogMessageType { get; protected set; }
|
||||
|
||||
}
|
||||
22
Modules/LoggerModule/ILogger.cs
Normal file
22
Modules/LoggerModule/ILogger.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using DiscordBotCore.Others;
|
||||
|
||||
namespace LoggerModule;
|
||||
|
||||
public interface ILogger
|
||||
{
|
||||
public struct FormattedMessage {
|
||||
public string Message;
|
||||
public LogType Type;
|
||||
}
|
||||
|
||||
string LogMessageFormat { get; set; }
|
||||
|
||||
void Log(string message);
|
||||
void Log(string message, LogType logType);
|
||||
void Log(string message, LogType logType, string format);
|
||||
void Log(string message, object Sender);
|
||||
void Log(string message, object Sender, LogType type);
|
||||
void LogException(Exception exception, object Sender, bool logFullStack = false);
|
||||
|
||||
void SetOutFunction(Action<string> outFunction);
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using DiscordBotCore.Interfaces.Logger;
|
||||
using DiscordBotCore.Others;
|
||||
using DiscordBotCore.Others;
|
||||
|
||||
namespace LoggerModule
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using DiscordBotCore.Interfaces.Logger;
|
||||
using DiscordBotCore.Others;
|
||||
using DiscordBotCore.Others;
|
||||
|
||||
namespace LoggerModule;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace CppWrapper.LibraryManagement
|
||||
return;
|
||||
}
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Loading library {LibraryPath}");
|
||||
Application.Logger.Log($"Loading library {LibraryPath}");
|
||||
|
||||
|
||||
if(!NativeLibrary.TryLoad(LibraryPath, out IntPtr hModule))
|
||||
@@ -29,7 +29,7 @@ namespace CppWrapper.LibraryManagement
|
||||
throw new DllNotFoundException($"Unable to load library {LibraryPath}");
|
||||
}
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Library {LibraryPath} loaded successfully [{hModule}]");
|
||||
Application.Logger.Log($"Library {LibraryPath} loaded successfully [{hModule}]");
|
||||
|
||||
LibraryHandle = hModule;
|
||||
}
|
||||
@@ -44,7 +44,7 @@ namespace CppWrapper.LibraryManagement
|
||||
NativeLibrary.Free(LibraryHandle);
|
||||
LibraryHandle = IntPtr.Zero;
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Library {LibraryPath} freed successfully");
|
||||
Application.Logger.Log($"Library {LibraryPath} freed successfully");
|
||||
}
|
||||
|
||||
private IntPtr GetFunctionPointer(string functionName)
|
||||
@@ -66,11 +66,11 @@ namespace CppWrapper.LibraryManagement
|
||||
{
|
||||
IntPtr functionPointer = GetFunctionPointer(methodName);
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Function pointer for {methodName} obtained successfully [address: {functionPointer}]");
|
||||
Application.Logger.Log($"Function pointer for {methodName} obtained successfully [address: {functionPointer}]");
|
||||
|
||||
T result = (T)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(T));
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Delegate for {methodName} created successfully");
|
||||
Application.Logger.Log($"Delegate for {methodName} created successfully");
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -79,7 +79,7 @@ namespace CppWrapper.LibraryManagement
|
||||
{
|
||||
IntPtr functionPointer = Marshal.GetFunctionPointerForDelegate(functionDelegate);
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Function pointer for delegate {functionDelegate.Method.Name} obtained successfully [address: {functionPointer}]");
|
||||
Application.Logger.Log($"Function pointer for delegate {functionDelegate.Method.Name} obtained successfully [address: {functionPointer}]");
|
||||
|
||||
return functionPointer;
|
||||
}
|
||||
@@ -104,7 +104,7 @@ namespace CppWrapper.LibraryManagement
|
||||
|
||||
var result = setterDelegate.DynamicInvoke(executableFunctionPtr);
|
||||
|
||||
Application.CurrentApplication.Logger.Log($"Function {setterExternFunctionName} bound to local action successfully");
|
||||
Application.Logger.Log($"Function {setterExternFunctionName} bound to local action successfully");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class Entry : ICommandAction
|
||||
|
||||
externalLibrary.FreeLibrary();
|
||||
} catch (Exception dllException) {
|
||||
Application.CurrentApplication.Logger.LogException(dllException, this);
|
||||
Application.Logger.LogException(dllException, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ using DiscordBotCore.Others;
|
||||
|
||||
namespace LevelingSystem;
|
||||
|
||||
internal class LevelCommand: DBCommand
|
||||
internal class LevelCommand: IDbCommand
|
||||
{
|
||||
public string Command => "level";
|
||||
|
||||
@@ -15,13 +15,13 @@ internal class LevelCommand: DBCommand
|
||||
|
||||
public string Usage => "level";
|
||||
|
||||
public bool requireAdmin => false;
|
||||
public bool RequireAdmin => false;
|
||||
|
||||
public async void ExecuteServer(DbCommandExecutingArguments args)
|
||||
{
|
||||
if(Variables.Database is null)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Database is not initialized", this, LogType.Warning);
|
||||
Application.Logger.Log("Database is not initialized", this, LogType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ using static LevelingSystem.Variables;
|
||||
|
||||
namespace LevelingSystem;
|
||||
|
||||
internal class LevelEvent : DBEvent
|
||||
internal class LevelEvent : IDbEvent
|
||||
{
|
||||
public string Name => "Leveling System Event Handler";
|
||||
public string Description => "The Leveling System Event Handler";
|
||||
|
||||
@@ -7,7 +7,7 @@ using DiscordBotCore.Others;
|
||||
|
||||
namespace MusicPlayer.Commands;
|
||||
|
||||
public class AddMelody: DBCommand
|
||||
public class AddMelody: IDbCommand
|
||||
{
|
||||
public string Command => "add_melody";
|
||||
|
||||
@@ -18,7 +18,7 @@ public class AddMelody: DBCommand
|
||||
|
||||
public string Description => "Add a custom melody to the database";
|
||||
public string Usage => "add_melody [title],[description?],[aliases],[byteSize]";
|
||||
public bool requireAdmin => false;
|
||||
public bool RequireAdmin => false;
|
||||
|
||||
public async void ExecuteServer(DbCommandExecutingArguments args)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ using DiscordBotCore.Others;
|
||||
|
||||
namespace MusicPlayer.Commands;
|
||||
|
||||
public class AddMelodyYoutube: DBCommand
|
||||
public class AddMelodyYoutube: IDbCommand
|
||||
{
|
||||
public string Command => "add_melody_youtube";
|
||||
|
||||
@@ -17,7 +17,7 @@ public class AddMelodyYoutube: DBCommand
|
||||
|
||||
public string Description => "Add melody to the database from a youtube link";
|
||||
public string Usage => "add_melody_youtube [URL] <alias1|alias2|...>";
|
||||
public bool requireAdmin => true;
|
||||
public bool RequireAdmin => true;
|
||||
|
||||
public async void ExecuteServer(DbCommandExecutingArguments args)
|
||||
{
|
||||
|
||||
@@ -4,14 +4,14 @@ using DiscordBotCore.Others;
|
||||
|
||||
namespace MusicPlayer.Commands;
|
||||
|
||||
public class SearchMelody: DBCommand
|
||||
public class SearchMelody: IDbCommand
|
||||
{
|
||||
|
||||
public string Command => "search_melody";
|
||||
public List<string>? Aliases => null;
|
||||
public string Description => "Search for a melody in the database";
|
||||
public string Usage => "search_melody [melody name OR one of its aliases]";
|
||||
public bool requireAdmin => false;
|
||||
public bool RequireAdmin => false;
|
||||
|
||||
public void ExecuteServer(DbCommandExecutingArguments args)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ using DiscordBotCore.Interfaces;
|
||||
|
||||
namespace MusicPlayer.Events;
|
||||
|
||||
public class OnLoad: DBEvent
|
||||
public class OnLoad: IDbEvent
|
||||
{
|
||||
private static readonly string _DefaultMusicPath = "Music/";
|
||||
private static readonly string _DefaultSaveLocation = "Music/Melodies/";
|
||||
|
||||
@@ -5,7 +5,7 @@ using DiscordBotCore.Others;
|
||||
|
||||
namespace MusicPlayer.Events;
|
||||
|
||||
public class OnVoiceRemoved: DBEvent
|
||||
public class OnVoiceRemoved: IDbEvent
|
||||
{
|
||||
|
||||
public string Name => "Event: OnVoiceRemoved";
|
||||
@@ -24,7 +24,7 @@ public class OnVoiceRemoved: DBEvent
|
||||
Variables.audioClient = null;
|
||||
Variables._MusicPlayer = null;
|
||||
|
||||
Application.CurrentApplication.Logger.Log("Bot left voice channel.", this, LogType.Info);
|
||||
Application.Logger.Log("Bot left voice channel.", this, LogType.Info);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -29,13 +29,13 @@ public class MusicPlayer
|
||||
{
|
||||
if (isQueueRunning)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Another queue is running !", typeof(MusicPlayer), LogType.Warning);
|
||||
Application.Logger.Log("Another queue is running !", typeof(MusicPlayer), LogType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Variables.audioClient is null)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Audio Client is null", typeof(MusicPlayer), LogType.Warning);
|
||||
Application.Logger.Log("Audio Client is null", typeof(MusicPlayer), LogType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class MusicPlayer
|
||||
string? ffmpegPath = await Application.CurrentApplication.PluginManager.GetDependencyLocation("FFMPEG");
|
||||
if(ffmpegPath is null)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("FFMPEG is missing. Please install it and try again.", typeof(MusicPlayer), LogType.Error);
|
||||
Application.Logger.Log("FFMPEG is missing. Please install it and try again.", typeof(MusicPlayer), LogType.Error);
|
||||
isQueueRunning = false;
|
||||
return;
|
||||
}
|
||||
@@ -61,7 +61,7 @@ public class MusicPlayer
|
||||
using var ffmpeg = CreateStream(ffmpegPath, CurrentlyPlaying.Location);
|
||||
if (ffmpeg is null)
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log($"Failed to start ffmpeg process. FFMPEG is missing or the {CurrentlyPlaying.Location} has an invalid format.", typeof(MusicPlayer), LogType.Error);
|
||||
Application.Logger.Log($"Failed to start ffmpeg process. FFMPEG is missing or the {CurrentlyPlaying.Location} has an invalid format.", typeof(MusicPlayer), LogType.Error);
|
||||
continue;
|
||||
}
|
||||
await using var ffmpegOut = ffmpeg.StandardOutput.BaseStream;
|
||||
@@ -111,7 +111,7 @@ public class MusicPlayer
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Application.CurrentApplication.Logger.LogException(ex, this);
|
||||
Application.Logger.LogException(ex, this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ using DiscordBotCore.Interfaces;
|
||||
|
||||
namespace MusicPlayer.SlashCommands;
|
||||
|
||||
public class Loop: DBSlashCommand
|
||||
public class Loop: IDbSlashCommand
|
||||
{
|
||||
|
||||
public string Name => "loop";
|
||||
public string Description => "Loop the current song for a certain amount of times. If no times are specified, it will loop once";
|
||||
public bool canUseDM => false;
|
||||
public bool CanUseDm => false;
|
||||
public bool HasInteraction => false;
|
||||
|
||||
public List<SlashCommandOptionBuilder> Options => new()
|
||||
|
||||
@@ -7,11 +7,11 @@ using DiscordBotCore.Others;
|
||||
|
||||
namespace MusicPlayer.SlashCommands;
|
||||
|
||||
public class Play: DBSlashCommand
|
||||
public class Play: IDbSlashCommand
|
||||
{
|
||||
public string Name => "play";
|
||||
public string Description => "Play music command";
|
||||
public bool canUseDM => false;
|
||||
public bool CanUseDm => false;
|
||||
public bool HasInteraction => false;
|
||||
|
||||
public List<SlashCommandOptionBuilder> Options => new()
|
||||
@@ -55,7 +55,7 @@ public class Play: DBSlashCommand
|
||||
if (user is null)
|
||||
{
|
||||
await context.RespondAsync("Failed to get user data from channel ! Check error log at " + DateTime.Now.ToLongTimeString());
|
||||
Application.CurrentApplication.Logger.Log("User is null while trying to convert from context.User to IGuildUser.", typeof(Play), LogType.Error);
|
||||
Application.Logger.Log("User is null while trying to convert from context.User to IGuildUser.", typeof(Play), LogType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ using DiscordBotCore.Interfaces;
|
||||
|
||||
namespace MusicPlayer.SlashCommands;
|
||||
|
||||
public class Queue: DBSlashCommand
|
||||
public class Queue: IDbSlashCommand
|
||||
{
|
||||
public string Name => "queue";
|
||||
public string Description => "Queue a melody to play";
|
||||
public bool canUseDM => false;
|
||||
public bool CanUseDm => false;
|
||||
public bool HasInteraction => false;
|
||||
public List<SlashCommandOptionBuilder> Options => null;
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ using DiscordBotCore.Interfaces;
|
||||
|
||||
namespace MusicPlayer.SlashCommands;
|
||||
|
||||
public class Skip: DBSlashCommand
|
||||
public class Skip: IDbSlashCommand
|
||||
{
|
||||
public string Name => "skip";
|
||||
public string Description => "Skip the current melody";
|
||||
public bool canUseDM => false;
|
||||
public bool CanUseDm => false;
|
||||
public bool HasInteraction => false;
|
||||
public List<SlashCommandOptionBuilder> Options => null;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user