diff --git a/DiscordBot/Bot/Actions/Extra/PluginMethods.cs b/DiscordBot/Bot/Actions/Extra/PluginMethods.cs index fbf6ad2..98c6b12 100644 --- a/DiscordBot/Bot/Actions/Extra/PluginMethods.cs +++ b/DiscordBot/Bot/Actions/Extra/PluginMethods.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using DiscordBot.Utilities; using PluginManager; @@ -71,7 +72,7 @@ internal static class PluginMethods if (!pluginData.HasDependencies) { - await manager.AppendPluginToDatabase(pluginName, pluginData.Version); + await manager.AppendPluginToDatabase(new PluginManager.Plugin.PluginInfo(pluginName, pluginData.Version, [])); Console.WriteLine("Finished installing " + pluginName + " successfully"); await RefreshPlugins(false); return; @@ -126,7 +127,7 @@ internal static class PluginMethods } ); - await manager.AppendPluginToDatabase(pluginName, pluginData.Version); + await manager.AppendPluginToDatabase(new PluginManager.Plugin.PluginInfo(pluginName, pluginData.Version, pluginData.Dependencies.Select(sep => sep.DownloadLocation).ToList())); await RefreshPlugins(false); } diff --git a/DiscordBot/Bot/Actions/Plugin.cs b/DiscordBot/Bot/Actions/Plugin.cs index 59ffc8b..ea2515c 100644 --- a/DiscordBot/Bot/Actions/Plugin.cs +++ b/DiscordBot/Bot/Actions/Plugin.cs @@ -40,6 +40,13 @@ public class Plugin: ICommandAction await PluginMethods.RefreshPlugins(true); break; + case "uninstall": + string plugName = string.Join(' ', args, 1, args.Length-1); + bool result = await Config.PluginsManager.MarkPluginToUninstall(plugName); + if(result) + Console.WriteLine($"Marked to uninstall plugin {plugName}. Please restart the bot"); + break; + case "list": await PluginMethods.List(Config.PluginsManager); break; diff --git a/DiscordBot/Entry.cs b/DiscordBot/Entry.cs index b9251b1..ede5e0e 100644 --- a/DiscordBot/Entry.cs +++ b/DiscordBot/Entry.cs @@ -1,9 +1,6 @@ using System; using System.IO; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using PluginManager.UX; namespace DiscordBot; @@ -13,7 +10,7 @@ public static class Entry public static void Main(string[] args) { #if DEBUG - if (args.Length == 1 && args[0] == "/purge_plugins") + if (args.Length == 1 && args[0] == "/purge_plugins" ) { foreach (var plugin in Directory.GetFiles("./Data/Plugins", "*.dll", SearchOption.AllDirectories)) { diff --git a/DiscordBot/Installer.cs b/DiscordBot/Installer.cs index 9cd5f92..3f51ad9 100644 --- a/DiscordBot/Installer.cs +++ b/DiscordBot/Installer.cs @@ -1,7 +1,7 @@ using System; using PluginManager; -using Spectre.Console; using System.Threading.Tasks; +using Spectre.Console; namespace DiscordBot; @@ -9,15 +9,16 @@ public static class Installer { public static async Task GenerateStartupConfig() { - var token = await PluginManager.UX.UxHandler.ShowInputBox("SethBot", "Please enter the bot token:"); - var botPrefix = await PluginManager.UX.UxHandler.ShowInputBox("SethBot", "Please enter the bot prefix:"); - var serverId = await PluginManager.UX.UxHandler.ShowInputBox("SethBot", "Please enter the Server ID:"); + var token = AnsiConsole.Ask("[green]Token:[/]"); + var botPrefix = AnsiConsole.Ask("[yellow]Prefix:[/]"); + var serverId = AnsiConsole.Ask("[deeppink1]Server ID:[/]"); - if (string.IsNullOrWhiteSpace(serverId)) serverId = "NULL"; + if (string.IsNullOrWhiteSpace(serverId)) serverId = string.Empty; if (string.IsNullOrWhiteSpace(token) || string.IsNullOrWhiteSpace(botPrefix)) { - await PluginManager.UX.UxHandler.ShowMessageBox("SethBot", "Invalid token or prefix !", PluginManager.UX.MessageBoxType.Error); + AnsiConsole.MarkupLine("Invalid token or prefix !"); + Environment.Exit(-20); } diff --git a/DiscordBot/Program.cs b/DiscordBot/Program.cs index 1971a6a..abf8f01 100644 --- a/DiscordBot/Program.cs +++ b/DiscordBot/Program.cs @@ -7,7 +7,6 @@ using DiscordBot.Utilities; using PluginManager.Bot; using PluginManager.Others; using PluginManager.Others.Actions; -using PluginManager.UX; using Spectre.Console; using static PluginManager.Config; @@ -100,11 +99,6 @@ public class Program { if (ex.Message == "No process is on the other end of the pipe." || (uint)ex.HResult == 0x800700E9) { - UxHandler.ShowMessageBox("SethBot", "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 !", MessageBoxType.Error - ).Wait(); - - 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 !", typeof(Program), LogType.ERROR @@ -130,7 +124,6 @@ public class Program if (logMessage.Message.Contains('[')) { - // If the message contains a tag, just print it as it is. No need to format it Console.WriteLine(logMessage.Message); return; } diff --git a/PluginManager/Bot/Boot.cs b/PluginManager/Bot/Boot.cs index df3c07c..1e706a8 100644 --- a/PluginManager/Bot/Boot.cs +++ b/PluginManager/Bot/Boot.cs @@ -4,7 +4,7 @@ using Discord; using Discord.Commands; using Discord.WebSocket; using PluginManager.Others; -using PluginManager.UX; + namespace PluginManager.Bot; @@ -91,6 +91,7 @@ public class Boot while (!isReady) ; } + private void CommonTasks() { if (client == null) return; @@ -122,7 +123,7 @@ public class Boot private Task Ready() { isReady = true; - UxHandler.ShowNotification("SethBot", "Seth Discord Bot is now up and running !").Wait(); + // UxHandler.ShowNotification("SethBot", "Seth Discord Bot is now up and running !").Wait(); return Task.CompletedTask; } diff --git a/PluginManager/Config.cs b/PluginManager/Config.cs index 0afbed5..87eaf72 100644 --- a/PluginManager/Config.cs +++ b/PluginManager/Config.cs @@ -7,15 +7,14 @@ using PluginManager.Online; using PluginManager.Others; using PluginManager.Others.Logger; using PluginManager.Plugin; -using OperatingSystem = System.OperatingSystem; namespace PluginManager; public class Config { - private static bool _isLoaded; - public static Logger Logger; - public static SettingsDictionary AppSettings; + private static bool _isLoaded; + public static Logger Logger; + public static SettingsDictionary AppSettings; public static PluginsManager PluginsManager; @@ -48,29 +47,15 @@ public class Config await JsonManager.SaveToJsonFile(AppSettings["PluginDatabase"], plugins); } - if (OperatingSystem.IsLinux()) - { - var windowManager = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP"); - AppSettings["UI"] = windowManager switch - { - "KDE" => "KDE", - "GNOME" => "GNOME", - _ => "CONSOLE" - }; - } - else AppSettings["UI"] = "CONSOLE"; - - Logger = new Logger(false, true, - AppSettings["LogFolder"] + $"/{DateTime.Today.ToShortDateString().Replace("/", "")}.log" - ); + Logger = new Logger(false, true, AppSettings["LogFolder"] + $"/{DateTime.Today.ToShortDateString().Replace("/", "")}.log"); - - UX.UxHandler.Init(); _isLoaded = true; PluginsManager = new PluginsManager("releases"); + await PluginsManager.UninstallMarkedPlugins(); + await PluginsManager.CheckForUpdates(); Logger.Log("Config initialized", typeof(Config)); diff --git a/PluginManager/Online/PluginsManager.cs b/PluginManager/Online/PluginsManager.cs index e531e77..e303774 100644 --- a/PluginManager/Online/PluginsManager.cs +++ b/PluginManager/Online/PluginsManager.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.IO; +using System.Linq; using System.Threading.Tasks; using PluginManager.Online.Helpers; using PluginManager.Others; @@ -68,11 +70,11 @@ public class PluginsManager await JsonManager.SaveToJsonFile( Config.AppSettings["PluginDatabase"],installedPlugins); } - public async Task AppendPluginToDatabase(string pluginName, PluginVersion version) + public async Task AppendPluginToDatabase(PluginInfo pluginData) { List installedPlugins = await JsonManager.ConvertFromJson>(await File.ReadAllTextAsync(Config.AppSettings["PluginDatabase"])); - installedPlugins.Add(new PluginInfo(pluginName, version)); + installedPlugins.Add(pluginData); await JsonManager.SaveToJsonFile( Config.AppSettings["PluginDatabase"],installedPlugins); } @@ -96,6 +98,43 @@ public class PluginsManager } } } + + public async Task MarkPluginToUninstall(string pluginName) + { + List installedPlugins = await GetInstalledPlugins(); + PluginInfo? info = installedPlugins.Find(info => info.PluginName == pluginName); + + if(info == null) + return false; + + await RemovePluginFromDatabase(pluginName); + info.IsMarkedToUninstall = true; + await AppendPluginToDatabase(info); + + return true; + + } + + public async Task UninstallMarkedPlugins() + { + List installedPlugins = await GetInstalledPlugins(); + foreach(PluginInfo plugin in installedPlugins) + { + if(!plugin.IsMarkedToUninstall) continue; + + await UninstallPlugin(plugin); + } + } + + private async Task UninstallPlugin(PluginInfo pluginInfo) + { + File.Delete(pluginInfo.FilePath); + + foreach(string dependency in pluginInfo.ListOfDependancies) + File.Delete(dependency); + + await RemovePluginFromDatabase(pluginInfo.PluginName); + } } diff --git a/PluginManager/Others/Actions/InternalActionsManager.cs b/PluginManager/Others/Actions/InternalActionsManager.cs index 8c8563b..e752e94 100644 --- a/PluginManager/Others/Actions/InternalActionsManager.cs +++ b/PluginManager/Others/Actions/InternalActionsManager.cs @@ -18,13 +18,12 @@ public class InternalActionManager public async Task Initialize() { - //loader.ActionLoadedEvent += OnActionLoaded; var m_actions = await loader.Load(); - if (m_actions == null) return; + if (m_actions == null) + return; foreach (var action in m_actions) - { Actions.TryAdd(action.ActionName, action); - } + } public async Task Refresh() @@ -33,34 +32,23 @@ public class InternalActionManager await Initialize(); } - // private void OnActionLoaded(string name, string typeName, bool success, Exception? e) - // { - // if (!success) - // { - // Config.Logger.Error(e); - // return; - // } - // - // Config.Logger.Log($"Action {name} loaded successfully", LogLevel.INFO, true); - // } - - public async Task Execute(string actionName, params string[]? args) + public async Task Execute(string actionName, params string[]? args) { if (!Actions.ContainsKey(actionName)) { Config.Logger.Log($"Action {actionName} not found", type: LogType.ERROR, source: typeof(InternalActionManager)); - return "Action not found"; + return false; } try { await Actions[actionName].Execute(args); - return "Action executed"; + return true; } catch (Exception e) { Config.Logger.Log(e.Message, type: LogType.ERROR, source: typeof(InternalActionManager)); - return e.Message; + return false; } } } diff --git a/PluginManager/Others/ArchiveManager.cs b/PluginManager/Others/ArchiveManager.cs index db62acc..ea12787 100644 --- a/PluginManager/Others/ArchiveManager.cs +++ b/PluginManager/Others/ArchiveManager.cs @@ -8,7 +8,7 @@ namespace PluginManager.Others; public static class ArchiveManager { - private static string? _archiveFolder; + private static string? _ArchiveFolder; private static bool IsInitialized { get; set; } public static void Initialize() @@ -19,7 +19,7 @@ public static class ArchiveManager if (!Config.AppSettings.ContainsKey("ArchiveFolder")) Config.AppSettings["ArchiveFolder"] = "./Data/Archives/"; - _archiveFolder = Config.AppSettings["ArchiveFolder"]; + _ArchiveFolder = Config.AppSettings["ArchiveFolder"]; IsInitialized = true; } @@ -52,7 +52,7 @@ public static class ArchiveManager { if (!IsInitialized) throw new Exception("ArchiveManager is not initialized"); - archName = _archiveFolder + archName; + archName = _ArchiveFolder + archName; if (!File.Exists(archName)) throw new Exception("Failed to load file !"); @@ -81,7 +81,7 @@ public static class ArchiveManager public static async Task ReadFromPakAsync(string fileName, string archFile) { if (!IsInitialized) throw new Exception("ArchiveManager is not initialized"); - archFile = _archiveFolder + archFile; + archFile = _ArchiveFolder + archFile; if (!File.Exists(archFile)) throw new Exception("Failed to load file !"); diff --git a/PluginManager/Plugin/PluginInfo.cs b/PluginManager/Plugin/PluginInfo.cs index 4280e3a..9023dfd 100644 --- a/PluginManager/Plugin/PluginInfo.cs +++ b/PluginManager/Plugin/PluginInfo.cs @@ -1,5 +1,6 @@ -using System.IO; -using PluginManager.Interfaces.Updater; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; using PluginManager.Online.Helpers; namespace PluginManager.Plugin; @@ -9,17 +10,30 @@ public class PluginInfo public string PluginName { get; private set; } public PluginVersion PluginVersion { get; private set; } public string FilePath { get; private set; } + public List ListOfDependancies {get; private set;} + public bool IsMarkedToUninstall {get; internal set;} - public PluginInfo(string pluginName, PluginVersion pluginVersion) + [JsonConstructor] + public PluginInfo(string pluginName, PluginVersion pluginVersion, List listOfDependancies, bool isMarkedToUninstall) + { + PluginName = pluginName; + PluginVersion = pluginVersion; + ListOfDependancies = listOfDependancies; + IsMarkedToUninstall = isMarkedToUninstall; + FilePath = $"{Config.AppSettings["PluginFolder"]}/{pluginName}.dll"; + } + + public PluginInfo(string pluginName, PluginVersion pluginVersion, List listOfDependancies) { PluginName = pluginName; PluginVersion = pluginVersion; - + ListOfDependancies = listOfDependancies; + IsMarkedToUninstall = false; FilePath = $"{Config.AppSettings["PluginFolder"]}/{pluginName}.dll"; } public static PluginInfo FromOnlineInfo(PluginOnlineInfo onlineInfo) { - return new PluginInfo(onlineInfo.Name, onlineInfo.Version); + return new PluginInfo(onlineInfo.Name, onlineInfo.Version, onlineInfo.Dependencies.Select(dep => dep.DownloadLocation).ToList()); } } diff --git a/PluginManager/PluginManager.csproj b/PluginManager/PluginManager.csproj index 12af348..35db0a2 100644 --- a/PluginManager/PluginManager.csproj +++ b/PluginManager/PluginManager.csproj @@ -1,31 +1,30 @@ - - net8.0 - enable - - - 512 - none - false - - - - - - - - - - - - - - - - ..\..\..\.nuget\packages\spectre.console\0.47.0\lib\net7.0\Spectre.Console.dll - - - - - + + net8.0 + enable + + + 512 + none + false + + + + + + + + + + + + + + + ..\..\..\.nuget\packages\spectre.console\0.47.0\lib\net7.0\Spectre.Console.dll + + + + + \ No newline at end of file diff --git a/PluginManager/UX/IOutputModel.cs b/PluginManager/UX/IOutputModel.cs deleted file mode 100644 index a202388..0000000 --- a/PluginManager/UX/IOutputModel.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading.Tasks; - -namespace PluginManager.UX; - -public enum MessageBoxType -{ - Info, - Warning, - Error -} - -public enum MessageBoxButtons -{ - YesNo, - YesNoCancel, - ContinueCancel -} - -internal interface IOutputModel -{ - - internal Task ShowMessageBox(string title, string message, MessageBoxType type); - - internal Task ShowInputBox(string title, string message); - - internal Task ShowMessageBox(string message); - - internal Task ShowMessageBox(string title, string message, MessageBoxButtons buttons, bool isWarning); - - internal Task ShowNotification(string title, string message, int timeout_seconds = 5); -} diff --git a/PluginManager/UX/Linux/KDE.cs b/PluginManager/UX/Linux/KDE.cs deleted file mode 100644 index 42551a5..0000000 --- a/PluginManager/UX/Linux/KDE.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System.Diagnostics; -using System.Threading.Tasks; - -namespace PluginManager.UX.Linux; - -internal class KDE: IOutputModel -{ - internal string KdeDialogApplication { get; } = "kdialog"; - - public async Task ShowMessageBox(string title, string message, MessageBoxType type) - { - var process = new Process(); - process.StartInfo.FileName = KdeDialogApplication; - - var typeStr = type switch - { - MessageBoxType.Info => "msgbox", - MessageBoxType.Warning => "sorry", - MessageBoxType.Error => "error", - _ => "info" - }; - - process.StartInfo.Arguments = $"--title \"{title}\" --{typeStr} \"{message}\""; - process.Start(); - await process.WaitForExitAsync(); - } - - public async Task ShowInputBox(string title, string message) - { - var process = new Process(); - process.StartInfo.FileName = KdeDialogApplication; - process.StartInfo.Arguments = $"--title \"{title}\" --inputbox \"{message}\""; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.RedirectStandardInput = true; - process.Start(); - - await process.WaitForExitAsync(); - return await process.StandardOutput.ReadToEndAsync(); - } - - public async Task ShowMessageBox(string message) - { - var process = new Process(); - process.StartInfo.FileName = KdeDialogApplication; - process.StartInfo.Arguments = $"--msgbox \"{message}\""; - process.Start(); - await process.WaitForExitAsync(); - } - - public async Task ShowMessageBox(string title, string message, MessageBoxButtons buttons, bool isWarning) - { - var process = new Process(); - process.StartInfo.FileName = KdeDialogApplication; - - var buttonsStr = buttons switch - { - MessageBoxButtons.YesNo => "yesno", - MessageBoxButtons.YesNoCancel => "yesnocancel", - MessageBoxButtons.ContinueCancel => "continuecancel", - _ => "yesno" - }; - var typeStr = isWarning ? "warning" : ""; - process.StartInfo.Arguments = $"--title \"{title}\" --{typeStr}{buttonsStr} \"{message}\""; - process.Start(); - await process.WaitForExitAsync(); - return process.ExitCode; - } - - public async Task ShowNotification(string title, string message, int timeout_seconds = 5) - { - var process = new Process(); - process.StartInfo.FileName = KdeDialogApplication; - process.StartInfo.Arguments = $"--title \"{title}\" --passivepopup \"{message}\" {timeout_seconds}"; - process.Start(); - await process.WaitForExitAsync(); - } -} diff --git a/PluginManager/UX/Other/Console.cs b/PluginManager/UX/Other/Console.cs deleted file mode 100644 index 23757fe..0000000 --- a/PluginManager/UX/Other/Console.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Threading.Tasks; -using Spectre.Console; - -namespace PluginManager.UX.Other; - -internal class Console: IOutputModel -{ - - public Task ShowMessageBox(string title, string message, MessageBoxType type) - { - AnsiConsole.Markup(title); - AnsiConsole.Markup(message); - - - return Task.CompletedTask; - } - - public Task ShowInputBox(string title, string message) - { - AnsiConsole.MarkupLine(title); - - var input = AnsiConsole.Ask(message); - - return Task.FromResult(input); - } - - public Task ShowMessageBox(string message) - { - AnsiConsole.MarkupLine(message); - return Task.CompletedTask; - } - - public Task ShowMessageBox(string title, string message, MessageBoxButtons buttons, bool isWarning) - { - AnsiConsole.MarkupLine(title); - AnsiConsole.MarkupLine(message); - - return Task.FromResult(0); - } - - public Task ShowNotification(string title, string message, int timeout_seconds = 5) - { - return Task.CompletedTask; - } -} diff --git a/PluginManager/UX/UxHandler.cs b/PluginManager/UX/UxHandler.cs deleted file mode 100644 index 72372e6..0000000 --- a/PluginManager/UX/UxHandler.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Threading.Tasks; - -namespace PluginManager.UX; - -public static class UxHandler -{ - private static IOutputModel? _model; - - public static void Init() - { - _model = Config.AppSettings["UI"] switch - { - "KDE" => new Linux.KDE(), - "CONSOLE" => new Other.Console(), - _ => null - }; - - } - - public static async Task ShowMessageBox(string title, string message, MessageBoxType type = MessageBoxType.Info) - { - await _model.ShowMessageBox(title, message, type); - } - - public static async Task ShowInputBox(string title, string message) - { - return await _model.ShowInputBox(title, message); - } - - public static async Task ShowMessageBox(string message) - { - await _model.ShowMessageBox(message); - } - - public static async Task ShowMessageBox(string title, string message, MessageBoxButtons buttons, bool isWarning) - { - return await _model.ShowMessageBox(title, message, buttons, isWarning); - } - - public static async Task ShowNotification(string title, string message, int timeout_seconds = 5) - { - await _model.ShowNotification(title, message, timeout_seconds); - } - -} diff --git a/PluginManager/Updater/Plugins/PluginUpdater.cs b/PluginManager/Updater/Plugins/PluginUpdater.cs index 5b23c02..9cda048 100644 --- a/PluginManager/Updater/Plugins/PluginUpdater.cs +++ b/PluginManager/Updater/Plugins/PluginUpdater.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Threading.Tasks; using PluginManager.Online; using PluginManager.Plugin; @@ -41,7 +42,7 @@ public class PluginUpdater await ServerCom.DownloadFileAsync(dependency.DownloadLocation, dependency.DownloadLocation, progressMeter); await _PluginManager.RemovePluginFromDatabase(pluginName); - await _PluginManager.AppendPluginToDatabase(pluginName, pluginInfo.Version); + await _PluginManager.AppendPluginToDatabase(PluginInfo.FromOnlineInfo(pluginInfo)); } public async Task HasUpdate(string pluginName)