diff --git a/DiscordBot/Bot/Actions/Exit.cs b/DiscordBot/Bot/Actions/Exit.cs index f01014a..1caa641 100644 --- a/DiscordBot/Bot/Actions/Exit.cs +++ b/DiscordBot/Bot/Actions/Exit.cs @@ -17,9 +17,8 @@ public class Exit : ICommandAction { if (args is null || args.Length == 0) { - Config.Logger.Log("Exiting...", "Exit", isInternal: false); + Config.Logger.Log("Exiting...", source: typeof(ICommandAction), type: LogType.WARNING); await Config.AppSettings.SaveToFile(); - await Config.Logger.SaveToFile(); Environment.Exit(0); } else @@ -34,7 +33,7 @@ public class Exit : ICommandAction case "-f": case "force": - Config.Logger.Log("Exiting (FORCE)...", "Exit", LogLevel.WARNING, false); + Config.Logger.Log("Exiting (FORCE)...", source: typeof(ICommandAction), type: LogType.WARNING); Environment.Exit(0); break; diff --git a/DiscordBot/Bot/Actions/Extra/PluginMethods.cs b/DiscordBot/Bot/Actions/Extra/PluginMethods.cs new file mode 100644 index 0000000..3b96d7d --- /dev/null +++ b/DiscordBot/Bot/Actions/Extra/PluginMethods.cs @@ -0,0 +1,204 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using DiscordBot.Utilities; +using PluginManager; +using PluginManager.Interfaces; +using PluginManager.Loaders; +using PluginManager.Online; +using PluginManager.Others; +using Spectre.Console; + +namespace DiscordBot.Bot.Actions.Extra; + +internal static class PluginMethods +{ + private static readonly PluginsManager PluginsManager = new(); + + internal static async Task List() + { + var data = await ConsoleUtilities.ExecuteWithProgressBar(PluginsManager.GetAvailablePlugins(), "Loading plugins..."); + + TableData tableData = new(new List { "Name", "Description", "Type", "Version" }); + foreach (var plugin in data) tableData.AddRow(plugin); + + tableData.HasRoundBorders = false; + tableData.PrintAsTable(); + } + + internal static async Task RefreshPlugins(bool quiet) + { + await Program.internalActionManager.Execute("plugin", "load", quiet ? "-q" : string.Empty); + await Program.internalActionManager.Refresh(); + } + + internal static async Task DownloadPlugin(PluginsManager manager, string pluginName) + { + var pluginData = await manager.GetPluginLinkByName(pluginName); + if (pluginData.Length == 0) + { + Console.WriteLine($"Plugin {pluginName} not found. Please check the spelling and try again."); + return; + } + + var pluginType = pluginData[0]; + var pluginLink = pluginData[1]; + var pluginRequirements = pluginData[2]; + + + await AnsiConsole.Progress() + .Columns(new ProgressColumn[] + { + new TaskDescriptionColumn(), + new ProgressBarColumn(), + new PercentageColumn() + }) + .StartAsync(async ctx => + { + var downloadTask = ctx.AddTask("Downloading plugin..."); + + IProgress progress = new Progress(p => { downloadTask.Value = p; }); + + await ServerCom.DownloadFileAsync(pluginLink, $"./Data/{pluginType}s/{pluginName}.dll", progress); + + downloadTask.Increment(100); + + ctx.Refresh(); + }); + + if (pluginRequirements == string.Empty) + { + Console.WriteLine("Finished installing " + pluginName + " successfully"); + await RefreshPlugins(false); + return; + } + + List requirementsUrLs = new(); + + await AnsiConsole.Progress() + .Columns(new ProgressColumn[] + { + new TaskDescriptionColumn(), + new ProgressBarColumn(), + new PercentageColumn() + }) + .StartAsync(async ctx => + { + var gatherInformationTask = ctx.AddTask("Gathering info..."); + gatherInformationTask.IsIndeterminate = true; + requirementsUrLs = await ServerCom.ReadTextFromURL(pluginRequirements); + await Task.Delay(2000); + gatherInformationTask.Increment(100); + }); + + await AnsiConsole.Progress() + .Columns(new ProgressColumn[] + { + new TaskDescriptionColumn(), + new ProgressBarColumn(), + new PercentageColumn() + }) + .StartAsync(async ctx => + { + List, Task>> downloadTasks = new(); + + foreach (var info in requirementsUrLs) + { + if (info.Length < 2) continue; + string[] data = info.Split(','); + string url = data[0]; + string fileName = data[1]; + + var task = ctx.AddTask($"Downloading {fileName}..."); + IProgress progress = new Progress(p => + { + task.Value = p; + }); + + var downloadTask = ServerCom.DownloadFileAsync(url, $"./{fileName}", progress); + downloadTasks.Add(new Tuple, Task>(task, progress, downloadTask)); + } + + foreach (var task in downloadTasks) + { + await task.Item3; + } + + }); + + await RefreshPlugins(false); + } + + internal static async Task LoadPlugins(string[] args) + { + var loader = new PluginLoader(Config.DiscordBot.client); + if (args.Length == 2 && args[1] == "-q") + { + loader.LoadPlugins(); + return true; + } + + var cc = Console.ForegroundColor; + loader.onCMDLoad += (name, typeName, success, exception) => + { + if (name == null || name.Length < 2) + name = typeName; + if (success) + { + Config.Logger.Log("Successfully loaded command : " + name, source: typeof(ICommandAction), + type: LogType.INFO); + } + + else + { + Config.Logger.Log("Failed to load command : " + name + " because " + exception?.Message, + source: typeof(ICommandAction), type: LogType.ERROR); + } + + Console.ForegroundColor = cc; + }; + loader.onEVELoad += (name, typeName, success, exception) => + { + if (name == null || name.Length < 2) + name = typeName; + + if (success) + { + Config.Logger.Log("Successfully loaded event : " + name, source: typeof(ICommandAction), + type: LogType.INFO); + } + else + { + Config.Logger.Log("Failed to load event : " + name + " because " + exception?.Message, + source: typeof(ICommandAction), type: LogType.ERROR); + } + + Console.ForegroundColor = cc; + }; + + loader.onSLSHLoad += (name, typeName, success, exception) => + { + if (name == null || name.Length < 2) + name = typeName; + + if (success) + { + Config.Logger.Log("Successfully loaded slash command : " + name, source: typeof(ICommandAction), + type: LogType.INFO); + } + else + { + Config.Logger.Log("Failed to load slash command : " + name + " because " + exception?.Message, + source: typeof(ICommandAction), type: LogType.ERROR); + } + + Console.ForegroundColor = cc; + }; + + loader.LoadPlugins(); + Console.ForegroundColor = cc; + return true; + } + + +} diff --git a/DiscordBot/Bot/Actions/Plugin.cs b/DiscordBot/Bot/Actions/Plugin.cs index c577711..a24ef12 100644 --- a/DiscordBot/Bot/Actions/Plugin.cs +++ b/DiscordBot/Bot/Actions/Plugin.cs @@ -1,9 +1,8 @@ using System; using System.Collections.Generic; -using System.Globalization; -using System.Threading; using System.Threading.Tasks; -using DiscordBot.Utilities; +using System.Windows.Input; +using DiscordBot.Bot.Actions.Extra; using PluginManager; using PluginManager.Interfaces; using PluginManager.Loaders; @@ -40,105 +39,26 @@ public class Plugin : ICommandAction switch (args[0]) { case "refresh": - await RefreshPlugins(true); + await PluginMethods.RefreshPlugins(true); break; case "list": - var data = await ConsoleUtilities.ExecuteWithProgressBar(manager.GetAvailablePlugins(), "Loading plugins..."); - - TableData tableData = new(new List { "Name", "Description", "Type", "Version" }); - foreach (var plugin in data) tableData.AddRow(plugin); - - tableData.HasRoundBorders = false; - tableData.PrintAsTable(); + await PluginMethods.List(); break; - - case "load": if (pluginsLoaded) - break; - if (Config.DiscordBot is null) { - AnsiConsole.MarkupLine("[red]Discord bot not initialized[/]"); + Config.Logger.Log("Plugins already loaded", source: typeof(ICommandAction), type: LogType.WARNING); break; } - var loader = new PluginLoader(Config.DiscordBot.client); - if (args.Length == 2 && args[1] == "-q") + if (Config.DiscordBot is null) { - Console.WriteLine("Loading plugins in quiet mode..."); - loader.LoadPlugins(); - pluginsLoaded = true; + Config.Logger.Log("DiscordBot is null", source: typeof(ICommandAction), type: LogType.WARNING); break; } - var cc = Console.ForegroundColor; - loader.onCMDLoad += (name, typeName, success, exception) => - { - if (name == null || name.Length < 2) - name = typeName; - if (success) - { - Console.ForegroundColor = ConsoleColor.Green; - Console.WriteLine("[CMD] Successfully loaded command : " + name); - } - - else - { - Console.ForegroundColor = ConsoleColor.Red; - if (exception is null) - Console.WriteLine("An error occured while loading: " + name); - else - Console.WriteLine("[CMD] Failed to load command : " + name + " because " + - exception!.Message - ); - } - - Console.ForegroundColor = cc; - }; - loader.onEVELoad += (name, typeName, success, exception) => - { - if (name == null || name.Length < 2) - name = typeName; - - if (success) - { - Console.ForegroundColor = ConsoleColor.Green; - Console.WriteLine("[EVENT] Successfully loaded event : " + name); - } - else - { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine("[EVENT] Failed to load event : " + name + " because " + exception!.Message); - } - - Console.ForegroundColor = cc; - }; - - loader.onSLSHLoad += (name, typeName, success, exception) => - { - if (name == null || name.Length < 2) - name = typeName; - - if (success) - { - Console.ForegroundColor = ConsoleColor.Green; - Console.WriteLine("[SLASH] Successfully loaded command : " + name); - } - else - { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine("[SLASH] Failed to load command : " + name + " because " + - exception!.Message - ); - } - - Console.ForegroundColor = cc; - }; - - loader.LoadPlugins(); - Console.ForegroundColor = cc; - pluginsLoaded = true; + pluginsLoaded = await PluginMethods.LoadPlugins(args); break; case "install": @@ -155,112 +75,8 @@ public class Plugin : ICommandAction } } - await DownloadPlugin(manager, pluginName); + await PluginMethods.DownloadPlugin(manager, pluginName); break; } } - - private async Task RefreshPlugins(bool quiet) - { - await Program.internalActionManager.Execute("plugin", "load", quiet ? "-q" : string.Empty); - await Program.internalActionManager.Refresh(); - } - - - public async Task DownloadPlugin(PluginsManager manager, string pluginName) - { - var pluginData = await manager.GetPluginLinkByName(pluginName); - if (pluginData.Length == 0) - { - Console.WriteLine($"Plugin {pluginName} not found. Please check the spelling and try again."); - return; - } - - var pluginType = pluginData[0]; - var pluginLink = pluginData[1]; - var pluginRequirements = pluginData[2]; - - - await AnsiConsole.Progress() - .Columns(new ProgressColumn[] - { - new TaskDescriptionColumn(), - new ProgressBarColumn(), - new PercentageColumn() - }) - .StartAsync(async ctx => - { - var downloadTask = ctx.AddTask("Downloading plugin..."); - - IProgress progress = new Progress(p => { downloadTask.Value = p; }); - - await ServerCom.DownloadFileAsync(pluginLink, $"./Data/{pluginType}s/{pluginName}.dll", progress); - - downloadTask.Increment(100); - - ctx.Refresh(); - }); - - if (pluginRequirements == string.Empty) - { - Console.WriteLine("Finished installing " + pluginName + " successfully"); - await RefreshPlugins(false); - return; - } - - List requirementsUrLs = new(); - - await AnsiConsole.Progress() - .Columns(new ProgressColumn[] - { - new TaskDescriptionColumn(), - new ProgressBarColumn(), - new PercentageColumn() - }) - .StartAsync(async ctx => - { - var gatherInformationTask = ctx.AddTask("Gathering info..."); - gatherInformationTask.IsIndeterminate = true; - requirementsUrLs = await ServerCom.ReadTextFromURL(pluginRequirements); - await Task.Delay(2000); - gatherInformationTask.Increment(100); - }); - - await AnsiConsole.Progress() - .Columns(new ProgressColumn[] - { - new TaskDescriptionColumn(), - new ProgressBarColumn(), - new PercentageColumn() - }) - .StartAsync(async ctx => - { - List, Task>> downloadTasks = new(); - - foreach (var info in requirementsUrLs) - { - if (info.Length < 2) continue; - string[] data = info.Split(','); - string url = data[0]; - string fileName = data[1]; - - var task = ctx.AddTask($"Downloading {fileName}..."); - IProgress progress = new Progress(p => - { - task.Value = p; - }); - - var downloadTask = ServerCom.DownloadFileAsync(url, $"./{fileName}", progress); - downloadTasks.Add(new Tuple, Task>(task, progress, downloadTask)); - } - - foreach (var task in downloadTasks) - { - await task.Item3; - } - - }); - - await RefreshPlugins(false); - } } \ No newline at end of file diff --git a/DiscordBot/Installer.cs b/DiscordBot/Installer.cs index 0111a38..1e27dc9 100644 --- a/DiscordBot/Installer.cs +++ b/DiscordBot/Installer.cs @@ -23,6 +23,6 @@ public static class Installer AnsiConsole.MarkupLine("[bold]Config saved ![/]"); - Config.Logger.Log("Config Saved", "Installer", isInternal: true); + Config.Logger.Log("Config Saved", source: typeof(Installer)); } } diff --git a/DiscordBot/Program.cs b/DiscordBot/Program.cs index 17cc867..a766b73 100644 --- a/DiscordBot/Program.cs +++ b/DiscordBot/Program.cs @@ -7,6 +7,7 @@ using DiscordBot.Utilities; using PluginManager.Bot; using PluginManager.Others; using PluginManager.Others.Actions; +using Spectre.Console; using static PluginManager.Config; namespace DiscordBot; @@ -80,7 +81,7 @@ public class Program } catch ( Exception ex ) { - Logger.Log(ex.ToString(), "Bot", LogLevel.ERROR); + Logger.Log(ex.ToString(), source: typeof(Program), type: LogType.CRITICAL); } } @@ -107,7 +108,7 @@ public class Program Logger.Log("An error occured while closing the bot last time. Please consider closing the bot using the &rexit&c method !\n" + "There is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !", - "Bot", LogLevel.ERROR); + source: typeof(Program), type: LogType.ERROR); } } } @@ -116,19 +117,18 @@ public class Program { await Initialize(); - Logger.LogEvent += (message, type, isInternal) => + Logger.OnLog += (sender, logMessage) => { - if (type == LogLevel.INFO) - Console.ForegroundColor = ConsoleColor.Green; - else if (type == LogLevel.WARNING) - Console.ForegroundColor = ConsoleColor.DarkYellow; - else if (type == LogLevel.ERROR) - Console.ForegroundColor = ConsoleColor.Red; - else if (type == LogLevel.CRITICAL) - Console.ForegroundColor = ConsoleColor.DarkRed; - - Console.WriteLine($"[{type.ToString()}] {message}"); - Console.ResetColor(); + string messageColor = logMessage.Type switch + { + LogType.INFO => "[green]", + LogType.WARNING => "[yellow]", + LogType.ERROR => "[red]", + LogType.CRITICAL => "[red]", + _ => "[white]" + }; + + AnsiConsole.MarkupLine($"{messageColor}{logMessage.ThrowTime} {logMessage.Message} [/]"); }; AppSettings["Version"] = Assembly.GetExecutingAssembly().GetName().Version.ToString(); diff --git a/PluginManager/Bot/Boot.cs b/PluginManager/Bot/Boot.cs index 28fd187..849cb98 100644 --- a/PluginManager/Bot/Boot.cs +++ b/PluginManager/Bot/Boot.cs @@ -78,16 +78,13 @@ public class Boot CommonTasks(); await client.LoginAsync(TokenType.Bot, botToken); - + await client.StartAsync(); commandServiceHandler = new CommandHandler(client, service, botPrefix); await commandServiceHandler.InstallCommandsAsync(); - - await Task.Delay(2000); - Config._DiscordBotClient = this; while (!isReady) ; @@ -108,8 +105,7 @@ public class Boot if (arg.Message.Contains("401")) { Config.AppSettings.Remove("token"); - Config.Logger.Log("The token is invalid. Please restart the bot and enter a valid token.", this, - LogLevel.ERROR); + Config.Logger.Log("The token is invalid. Please restart the bot and enter a valid token.", source:typeof(Boot), type: LogType.CRITICAL); await Config.AppSettings.SaveToFile(); await Task.Delay(4000); Environment.Exit(0); @@ -118,7 +114,7 @@ public class Boot private async Task Client_LoggedOut() { - Config.Logger.Log("Successfully Logged Out", this); + Config.Logger.Log("Successfully Logged Out", source: typeof(Boot)); await Log(new LogMessage(LogSeverity.Info, "Boot", "Successfully logged out from discord !")); } @@ -130,7 +126,7 @@ public class Boot private Task LoggedIn() { - Config.Logger.Log("Successfully Logged In", this); + Config.Logger.Log("Successfully Logged In", source: typeof(Boot)); return Task.CompletedTask; } @@ -140,13 +136,12 @@ public class Boot { case LogSeverity.Error: case LogSeverity.Critical: - Config.Logger.Log(message.Message, this, LogLevel.ERROR); - + Config.Logger.Log(message.Message, source: typeof(Boot), type: LogType.ERROR); break; case LogSeverity.Info: case LogSeverity.Debug: - Config.Logger.Log(message.Message, this); + Config.Logger.Log(message.Message, source: typeof(Boot), type: LogType.INFO); break; diff --git a/PluginManager/Bot/CommandHandler.cs b/PluginManager/Bot/CommandHandler.cs index 8cb7ca1..bd3e68d 100644 --- a/PluginManager/Bot/CommandHandler.cs +++ b/PluginManager/Bot/CommandHandler.cs @@ -57,7 +57,7 @@ internal class CommandHandler } catch (Exception ex) { - Config.Logger.Log(ex.Message, "CommandHandler", LogLevel.ERROR); + Config.Logger.Log(ex.Message, type: LogType.ERROR, source: typeof(CommandHandler)); } return Task.CompletedTask; @@ -145,7 +145,7 @@ internal class CommandHandler } catch (Exception ex) { - Config.Logger.Log(ex.Message, this, LogLevel.ERROR); + Config.Logger.Log(ex.Message, type: LogType.ERROR, source: typeof(CommandHandler)); } } } diff --git a/PluginManager/Config.cs b/PluginManager/Config.cs index 3bac0fd..3ae4505 100644 --- a/PluginManager/Config.cs +++ b/PluginManager/Config.cs @@ -9,8 +9,8 @@ namespace PluginManager; public class Config { - private static bool _isLoaded; - public static DBLogger? Logger; + private static bool _isLoaded; + public static Logger Logger; public static SettingsDictionary AppSettings; internal static Boot? _DiscordBotClient; @@ -30,15 +30,14 @@ public class Config AppSettings = new SettingsDictionary("./Data/Resources/config.json"); AppSettings["LogFolder"] = "./Data/Logs/Logs"; - AppSettings["ErrorFolder"] = "./Data/Logs/Errors"; - Logger = new DBLogger(true); + Logger = new Logger(false, true); ArchiveManager.Initialize(); _isLoaded = true; - Logger.Log("Config initialized", LogLevel.INFO); + await Logger.Log(message: "Config initialized", source: typeof(Config)); } } diff --git a/PluginManager/Interfaces/Exceptions/IException.cs b/PluginManager/Interfaces/Exceptions/IException.cs deleted file mode 100644 index ec79dc4..0000000 --- a/PluginManager/Interfaces/Exceptions/IException.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; - -namespace PluginManager.Interfaces.Exceptions; - -public interface IException -{ - public List Messages { get; set; } - public bool isFatal { get; } - public string GenerateFullMessage(); - public void HandleException(); - - public IException AppendError(string message); - - public IException AppendError(List messages); - public IException IsFatal(bool isFatal = true); - -} \ No newline at end of file diff --git a/PluginManager/Interfaces/Logger/ILog.cs b/PluginManager/Interfaces/Logger/ILog.cs new file mode 100644 index 0000000..fd5a300 --- /dev/null +++ b/PluginManager/Interfaces/Logger/ILog.cs @@ -0,0 +1,15 @@ +using System; +using PluginManager.Others; + +namespace PluginManager.Interfaces.Logger; + +internal interface ILog +{ + string Message { get; set; } + string OutputFile { get; set; } + + Type? Source { get; set; } + + LogType Type { get; set; } + DateTime ThrowTime { get; set; } +} diff --git a/PluginManager/Interfaces/Logger/ILogger.cs b/PluginManager/Interfaces/Logger/ILogger.cs new file mode 100644 index 0000000..85c0977 --- /dev/null +++ b/PluginManager/Interfaces/Logger/ILogger.cs @@ -0,0 +1,17 @@ +using System; +using System.Threading.Tasks; +using PluginManager.Others; +using PluginManager.Others.Logger; + +namespace PluginManager.Interfaces.Logger; + +internal interface ILogger +{ + bool IsEnabled { get; init; } + bool OutputToFile { get; init; } + + event EventHandler OnLog; + Task Log( + string message = "", string outputFile = "", Type? source = default, LogType type = LogType.INFO, + DateTime throwTime = default); +} diff --git a/PluginManager/Loaders/Loader.cs b/PluginManager/Loaders/Loader.cs index 054370b..803fddc 100644 --- a/PluginManager/Loaders/Loader.cs +++ b/PluginManager/Loaders/Loader.cs @@ -53,10 +53,9 @@ internal class Loader { Assembly.LoadFrom(file); } - catch (Exception ex) + catch { - Config.Logger.Log("PluginName: " + new FileInfo(file).Name.Split('.')[0] + " not loaded", this, - LogLevel.ERROR); + Config.Logger.Log("PluginName: " + new FileInfo(file).Name.Split('.')[0] + " not loaded", source: typeof(Loader), type: LogType.ERROR); continue; } @@ -130,7 +129,7 @@ internal class Loader } catch (Exception ex) { - Config.Logger.Log(ex.Message, this, LogLevel.ERROR); + Config.Logger.Log(ex.Message, source: typeof(Loader), type: LogType.ERROR); return null; } diff --git a/PluginManager/Loaders/PluginLoader.cs b/PluginManager/Loaders/PluginLoader.cs index afa0561..409edb4 100644 --- a/PluginManager/Loaders/PluginLoader.cs +++ b/PluginManager/Loaders/PluginLoader.cs @@ -88,11 +88,10 @@ public class PluginLoader Events = new List(); SlashCommands = new List(); - Config.Logger.Log("Starting plugin loader ... Client: " + _client.CurrentUser.Username, this, - LogLevel.INFO); + Config.Logger.Log("Starting plugin loader ... Client: " + _client.CurrentUser.Username, source: typeof(PluginLoader), type: LogType.INFO); var loader = new Loader("./Data/Plugins", "dll"); - loader.FileLoaded += args => Config.Logger.Log($"{args.PluginName} file Loaded", this, LogLevel.INFO); + loader.FileLoaded += args => Config.Logger.Log($"{args.PluginName} file Loaded", source: typeof(PluginLoader), type: LogType.INFO); loader.PluginLoaded += Loader_PluginLoaded; var res = loader.Load(); Events = res.Item1; @@ -117,7 +116,7 @@ public class PluginLoader } catch (Exception ex) { - Config.Logger.Log(ex.Message, this, LogLevel.ERROR); + Config.Logger.Log(ex.Message, source: typeof(PluginLoader), type: LogType.ERROR); } break; @@ -151,13 +150,13 @@ public class PluginLoader var instance = (DBEvent)Activator.CreateInstance(type); instance.Start(client); Events.Add(instance); - Config.Logger.Log($"[EVENT] Loaded external {type.FullName}!", LogLevel.INFO); + Config.Logger.Log($"[EVENT] Loaded external {type.FullName}!", source: typeof(PluginLoader)); } else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type)) { var instance = (DBCommand)Activator.CreateInstance(type); Commands.Add(instance); - Config.Logger.Log($"[CMD] Instance: {type.FullName} loaded !", LogLevel.INFO); + Config.Logger.Log($"[CMD] Instance: {type.FullName} loaded !", source: typeof(PluginLoader)); } else if (type.IsClass && typeof(DBSlashCommand).IsAssignableFrom(type)) { @@ -170,13 +169,13 @@ public class PluginLoader await client.CreateGlobalApplicationCommandAsync(builder.Build()); SlashCommands.Add(instance); - Config.Logger.Log($"[SLASH] Instance: {type.FullName} loaded !", LogLevel.INFO); + Config.Logger.Log($"[SLASH] Instance: {type.FullName} loaded !", source: typeof(PluginLoader)); } } catch (Exception ex) { //Console.WriteLine(ex.Message); - Config.Logger.Error(ex); + Config.Logger.Log(ex.Message, source: typeof(PluginLoader), type: LogType.ERROR); } } diff --git a/PluginManager/Online/PluginsManager.cs b/PluginManager/Online/PluginsManager.cs index 64e8932..f3ca97c 100644 --- a/PluginManager/Online/PluginsManager.cs +++ b/PluginManager/Online/PluginsManager.cs @@ -89,8 +89,7 @@ public class PluginsManager } catch (Exception exception) { - Config.Logger.Log("Failed to execute command: listplugs\nReason: " + exception.Message, this, - LogLevel.ERROR); + Config.Logger.Log(message: "Failed to execute command: listplugs\nReason: " + exception.Message, source: typeof(PluginsManager), type: LogType.ERROR ); } return null; @@ -142,8 +141,7 @@ public class PluginsManager } catch (Exception exception) { - Config.Logger.Log("Failed to execute command: listplugs\nReason: " + exception.Message, this, - LogLevel.ERROR); + Config.Logger.Log("Failed to execute command: plugin list\nReason: " + exception.Message, source: typeof(PluginsManager), type: LogType.ERROR); } return null; diff --git a/PluginManager/Others/Actions/InternalActionsManager.cs b/PluginManager/Others/Actions/InternalActionsManager.cs index 2bd3a6a..8b67091 100644 --- a/PluginManager/Others/Actions/InternalActionsManager.cs +++ b/PluginManager/Others/Actions/InternalActionsManager.cs @@ -48,7 +48,7 @@ public class InternalActionManager { if (!Actions.ContainsKey(actionName)) { - Config.Logger.Log($"Action {actionName} not found", "InternalActionManager", LogLevel.WARNING, true); + Config.Logger.Log($"Action {actionName} not found", type: LogType.ERROR, source: typeof(InternalActionManager)); return "Action not found"; } @@ -59,7 +59,7 @@ public class InternalActionManager } catch (Exception e) { - Config.Logger.Log(e.Message, "InternalActionManager", LogLevel.ERROR); + Config.Logger.Log(e.Message , type: LogType.ERROR, source: typeof(InternalActionManager)); return e.Message; } } diff --git a/PluginManager/Others/ArchiveManager.cs b/PluginManager/Others/ArchiveManager.cs index d08e7e6..24f9c64 100644 --- a/PluginManager/Others/ArchiveManager.cs +++ b/PluginManager/Others/ArchiveManager.cs @@ -2,7 +2,6 @@ using System.IO; using System.IO.Compression; using System.Linq; -using System.Runtime.Serialization.Formatters.Binary; using System.Threading.Tasks; namespace PluginManager.Others; @@ -94,7 +93,7 @@ public static class ArchiveManager } catch (Exception ex) { - Config.Logger.Log(ex.Message, "Archive Manager", LogLevel.ERROR); // Write the error to a file + Config.Logger.Log(message: ex.Message, source: typeof(ArchiveManager), type: LogType.ERROR); // Write the error to a file await Task.Delay(100); return await ReadFromPakAsync(FileName, archFile); } @@ -132,8 +131,7 @@ public static class ArchiveManager } catch (Exception ex) { - Config.Logger.Log($"Failed to extract {entry.Name}. Exception: {ex.Message}", - "Archive Manager", LogLevel.ERROR); + Config.Logger.Log(ex.Message, source: typeof(ArchiveManager), type: LogType.ERROR); } currentZIPFile++; @@ -165,8 +163,7 @@ public static class ArchiveManager } catch (Exception ex) { - Config.Logger.Log($"Failed to extract {entry.Name}. Exception: {ex.Message}", - "Archive Manager", LogLevel.ERROR); + Config.Logger.Log(ex.Message, source: typeof(ArchiveManager), type: LogType.ERROR); } await Task.Delay(10); diff --git a/PluginManager/Others/Enums.cs b/PluginManager/Others/Enums.cs index 225c554..ac601dc 100644 --- a/PluginManager/Others/Enums.cs +++ b/PluginManager/Others/Enums.cs @@ -14,7 +14,7 @@ public enum OperatingSystem /// /// The output log type /// -public enum LogLevel +public enum LogType { INFO, WARNING, diff --git a/PluginManager/Others/Exceptions/ConfigFailedToLoad.cs b/PluginManager/Others/Exceptions/ConfigFailedToLoad.cs deleted file mode 100644 index 7825ae2..0000000 --- a/PluginManager/Others/Exceptions/ConfigFailedToLoad.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Generic; -using PluginManager.Interfaces.Exceptions; - -namespace PluginManager.Others.Exceptions; - -public class ConfigFailedToLoad : IException -{ - public List? Messages { get; set; } - public bool isFatal { get; private set; } - public string? File { get; } - - - public ConfigFailedToLoad(string message, bool isFatal, string file) - { - this.isFatal = isFatal; - Messages = new List() {message}; - this.File = file; - } - - public ConfigFailedToLoad(string message, bool isFatal) - { - this.isFatal = isFatal; - Messages = new List() {message}; - this.File = null; - } - - public ConfigFailedToLoad(string message) - { - this.isFatal = false; - Messages = new List() {message}; - this.File = null; - } - - public string GenerateFullMessage() - { - string messages = ""; - foreach (var message in Messages) - { - messages += message + "\n"; - } - return $"\nMessage: {messages}\nIsFatal: {isFatal}\nFile: {File ?? "null"}"; - } - - public void HandleException() - { - if (isFatal) - { - Config.Logger.Log(GenerateFullMessage(), LogLevel.CRITICAL, true); - Environment.Exit((int)ExceptionExitCode.CONFIG_FAILED_TO_LOAD); - - } - - Config.Logger.Log(GenerateFullMessage(), LogLevel.WARNING); - } - - public IException AppendError(string message) - { - Messages.Add(message); - return this; - } - - public IException AppendError(List messages) - { - Messages.AddRange(messages); - return this; - } - - public IException IsFatal(bool isFatal = true) - { - this.isFatal = isFatal; - return this; - } - - - public static ConfigFailedToLoad CreateError(string message, bool isFatal, string? file = null) - { - if (file is not null) - return new ConfigFailedToLoad(message, isFatal, file); - return new ConfigFailedToLoad(message, isFatal); - } - - public static ConfigFailedToLoad CreateError(string message) - { - return new ConfigFailedToLoad(message); - } - - - - -} \ No newline at end of file diff --git a/PluginManager/Others/Exceptions/ConfigNoKeyWasPresent.cs b/PluginManager/Others/Exceptions/ConfigNoKeyWasPresent.cs deleted file mode 100644 index ea35911..0000000 --- a/PluginManager/Others/Exceptions/ConfigNoKeyWasPresent.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections.Generic; -using PluginManager.Interfaces.Exceptions; - -namespace PluginManager.Others.Exceptions; - -public class ConfigNoKeyWasPresent: IException -{ - public List Messages { get; set; } - public bool isFatal { get; private set; } - - public ConfigNoKeyWasPresent(string message, bool isFatal) - { - this.Messages = new List() { message }; - this.isFatal = isFatal; - } - - public ConfigNoKeyWasPresent(string message) - { - this.Messages = new List() { message }; - this.isFatal = false; - } - - public string GenerateFullMessage() - { - string messages = ""; - foreach (var message in Messages) - { - messages += message + "\n"; - } - return $"\nMessage: {messages}\nIsFatal: {isFatal}"; - } - - public void HandleException() - { - if (isFatal) - { - - Config.Logger.Log(GenerateFullMessage(), LogLevel.CRITICAL, true); - Environment.Exit((int)ExceptionExitCode.CONFIG_KEY_NOT_FOUND); - - } - - Config.Logger.Log(GenerateFullMessage(), LogLevel.WARNING); - } - - public IException AppendError(string message) - { - Messages.Add(message); - return this; - } - - public IException AppendError(List messages) - { - Messages.AddRange(messages); - return this; - } - - public IException IsFatal(bool isFatal = true) - { - this.isFatal = isFatal; - return this; - } - - public static ConfigNoKeyWasPresent CreateError(string message) - { - return new ConfigNoKeyWasPresent(message); - } - - public static ConfigNoKeyWasPresent CreateError(string message, bool isFatal) - { - return new ConfigNoKeyWasPresent(message, isFatal); - } - -} \ No newline at end of file diff --git a/PluginManager/Others/Logger/DBLogger.cs b/PluginManager/Others/Logger/DBLogger.cs deleted file mode 100644 index 04fd47c..0000000 --- a/PluginManager/Others/Logger/DBLogger.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace PluginManager.Others.Logger; - -public class DBLogger -{ - public delegate void LogHandler(string message, LogLevel logType, bool isInternal = false); - - private readonly string _errFolder; - - private readonly string _logFolder; - private readonly List ErrorHistory = new(); - private readonly List LogHistory = new(); - - private readonly bool _continuousSave; - private readonly bool _LogErrorsOnly; - - public DBLogger(bool continuousSave = true, bool logErrorsOnly = true) - { - _logFolder = Config.AppSettings["LogFolder"]; - _errFolder = Config.AppSettings["ErrorFolder"]; - - _continuousSave = continuousSave; - _LogErrorsOnly = logErrorsOnly; - } - - public IReadOnlyList Logs => LogHistory; - public IReadOnlyList Errors => ErrorHistory; - - public event LogHandler? LogEvent; - - public void Log(string message, LogLevel type = LogLevel.INFO) - { - Log(new LogMessage(message, type)); - } - - public void Log(string message, LogLevel type= LogLevel.INFO, bool isInternal = false) - { - Log(new LogMessage(message, type,"unknown", isInternal)); - } - - public void Log(string message, string sender = "unknown", LogLevel type = LogLevel.INFO, bool isInternal = false) - { - Log(new LogMessage(message, type,sender,isInternal)); - } - - public void Log(string message, string sender = "unknown", LogLevel type = LogLevel.INFO) - { - Log(new LogMessage(message, type, sender)); - } - - public void Error(Exception? e) - { - Log(e.Message, e.Source, LogLevel.ERROR); - } - - private async void Log(LogMessage message) - { - LogEvent?.Invoke(message.Message, message.Type); - - if (message.Type != LogLevel.ERROR && message.Type != LogLevel.CRITICAL) - LogHistory.Add(message); - else - ErrorHistory.Add(message); - - if (_continuousSave) - await SaveToFile(); - } - - public void Log(string message, object sender, LogLevel type = LogLevel.INFO) - { - Log(message, sender.GetType().Name, type); - } - - public async Task SaveToFile() - { - await SaveToTxt(); - } - - private async Task SaveToTxt() - { - if (!_LogErrorsOnly) - { - var logFile = new LogFile(_logFolder + $"/{DateTime.Today.ToShortDateString().Replace('/', '_')}_log.txt"); - foreach (var logMessage in LogHistory) - logFile.Write(logMessage); - } - - var errFile = new LogFile(_errFolder + $"/{DateTime.Today.ToShortDateString().Replace('/', '_')}_err.txt"); - foreach (var logMessage in ErrorHistory) - errFile.Write(logMessage); - } -} diff --git a/PluginManager/Others/Logger/Log.cs b/PluginManager/Others/Logger/Log.cs new file mode 100644 index 0000000..03e2921 --- /dev/null +++ b/PluginManager/Others/Logger/Log.cs @@ -0,0 +1,78 @@ +using System; +using System.Linq; +using PluginManager.Interfaces.Logger; + +namespace PluginManager.Others.Logger; + +public class Log : ILog +{ + public string Message { get; set; } + public string OutputFile { get; set; } + public Type? Source { get; set; } + public LogType Type { get; set; } + public DateTime ThrowTime { get; set; } + + public Log(string message, string outputFile, Type? source, LogType type, DateTime throwTime) + { + Message = message; + OutputFile = outputFile; + Source = source; + Type = type; + ThrowTime = throwTime; + } + + public Log(string message, string outputFile, Type? source, LogType type) + { + Message = message; + OutputFile = outputFile; + Source = source; + Type = type; + ThrowTime = DateTime.Now; + } + + public Log(string message, string outputFile, Type? source) + { + Message = message; + OutputFile = outputFile; + Source = source; + Type = LogType.INFO; + ThrowTime = DateTime.Now; + } + + public Log(string message, string outputFile) + { + Message = message; + OutputFile = outputFile; + Source = typeof(Log); + Type = LogType.INFO; + ThrowTime = DateTime.Now; + } + + public Log(string message) + { + Message = message; + OutputFile = ""; + Source = typeof(Log); + Type = LogType.INFO; + ThrowTime = DateTime.Now; + } + + public static implicit operator Log(string message) => new (message); + + public static implicit operator string(Log log) => $"[{log.ThrowTime}] {log.Message}"; + + public string AsLongString() + { + return $"[{ThrowTime}] [{Source}] [{Type}] {Message}"; + } + + public string AsShortString() + { + return this; + } + + public string FormatedLongString() + { + return $"[{ThrowTime}]\t[{Source}]\t\t\t[{Type}]\t{Message}"; + } +} diff --git a/PluginManager/Others/Logger/LogFile.cs b/PluginManager/Others/Logger/LogFile.cs deleted file mode 100644 index 148ab17..0000000 --- a/PluginManager/Others/Logger/LogFile.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.IO; - -namespace PluginManager.Others.Logger; - -public class LogFile -{ - public FileInfo File { get; set; } - public LogFile(string path) - { - File = new FileInfo(path); - } - - public void Write(string message) - { - using var sw = File.AppendText(); - sw.WriteLine(message); - } - - public void Write(string message, LogLevel type) - { - using var sw = File.AppendText(); - sw.WriteLine($"[{type}] {message}"); - } - - public void Write(string message, string sender, LogLevel type) - { - using var sw = File.AppendText(); - sw.WriteLine($"[{type}] [{sender}] {message}"); - } - - public void Write(LogMessage logMessage) - { - using var sw = File.AppendText(); - sw.WriteLine(logMessage.ToString()); - } -} \ No newline at end of file diff --git a/PluginManager/Others/Logger/LogMessage.cs b/PluginManager/Others/Logger/LogMessage.cs deleted file mode 100644 index 1d15796..0000000 --- a/PluginManager/Others/Logger/LogMessage.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; - -namespace PluginManager.Others.Logger; - -public class LogMessage -{ - public LogMessage(string message, LogLevel type) - { - Message = message; - Type = type; - Time = DateTime.Now.ToString("HH:mm:ss"); - isInternal = false; - } - - public LogMessage(string message, LogLevel type, string sender, bool isInternal) : this(message, type) - { - Sender = sender; - this.isInternal = isInternal; - } - - public LogMessage(string message, LogLevel type, string sender) : this (message, type, sender, false) - { - - } - - public string Message { get; set; } - public LogLevel Type { get; set; } - public string Time { get; set; } - public string Sender { get; set; } - public bool isInternal { get; set; } - - public override string ToString() - { - return $"[{Time}] {Message}"; - } - - public static explicit operator LogMessage(string message) - { - return new LogMessage(message, LogLevel.INFO); - } - - public static explicit operator LogMessage((string message, LogLevel type) tuple) - { - return new LogMessage(tuple.message, tuple.type); - } - - public static explicit operator LogMessage((string message, LogLevel type, string sender) tuple) - { - return new LogMessage(tuple.message, tuple.type, tuple.sender); - } -} diff --git a/PluginManager/Others/Logger/Logger.cs b/PluginManager/Others/Logger/Logger.cs new file mode 100644 index 0000000..99efbe2 --- /dev/null +++ b/PluginManager/Others/Logger/Logger.cs @@ -0,0 +1,57 @@ +using System; +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using PluginManager.Interfaces.Logger; + +namespace PluginManager.Others.Logger; + +public sealed class Logger : ILogger +{ + public bool IsEnabled { get; init; } + public bool OutputToFile { get; init; } + + public LogType LowestLogLevel { get; set; } + private bool UseShortVersion { get; } + + public Logger(bool useShortVersion, bool outputToFile, LogType lowestLogLevel = LogType.INFO) + { + UseShortVersion = useShortVersion; + OutputToFile = outputToFile; + IsEnabled = true; + LowestLogLevel = lowestLogLevel; + } + + public event EventHandler? OnLog; + + private async Task Log(Log logMessage) + { + if (!IsEnabled) return; + + OnLog?.Invoke(this, logMessage); + + if (logMessage.Type < LowestLogLevel) return; + + if (OutputToFile) + await File.AppendAllTextAsync( + logMessage.OutputFile, + (UseShortVersion ? logMessage : logMessage.AsLongString()) + "\n"); + } + + public async Task Log(string message = "", string outputFile = "", Type? source = default, LogType type = LogType.INFO, DateTime throwTime = default) + { + if (!IsEnabled) return; + + if (type < LowestLogLevel) return; + + if (string.IsNullOrEmpty(message)) return; + + if (string.IsNullOrEmpty(outputFile)) outputFile = Config.AppSettings["LogFolder"] + "/" + DateTime.Now.ToString("yyyy-MM-dd") + ".log"; + + if(throwTime == default) throwTime = DateTime.Now; + + if (source == default) source = typeof(Log); + + await Log(new Log(message, outputFile, source, type, throwTime)); + } +} diff --git a/PluginManager/Others/SettingsDictionary.cs b/PluginManager/Others/SettingsDictionary.cs index 3cb1602..23834de 100644 --- a/PluginManager/Others/SettingsDictionary.cs +++ b/PluginManager/Others/SettingsDictionary.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; -using PluginManager.Others.Exceptions; namespace PluginManager.Others; @@ -16,10 +15,8 @@ public class SettingsDictionary : IDictionary _file = file; if (!LoadFromFile()) { - ConfigFailedToLoad.CreateError("Failed to load config") - .AppendError("The file is empty or does not exist") - .IsFatal() - .HandleException(); + _dictionary = new Dictionary(); + SaveToFile(); } } @@ -50,10 +47,6 @@ public class SettingsDictionary : IDictionary } catch { - ConfigFailedToLoad - .CreateError("Failed to load config") - .IsFatal() - .HandleException(); return false; } @@ -126,11 +119,6 @@ public class SettingsDictionary : IDictionary if(this._dictionary[key] is string s && !string.IsNullOrEmpty(s) && !string.IsNullOrWhiteSpace(s)) return this._dictionary[key]; - ConfigNoKeyWasPresent.CreateError($"Key {(key is string ? key : typeof(TKey).Name)} was not present in {_file ?? "config"}") - .AppendError("Deleting the file may fix this issue") - .IsFatal() - .HandleException(); - return default!; } set => this._dictionary![key] = value;