diff --git a/DiscordBot/Bot/Actions/Extra/PluginMethods.cs b/DiscordBot/Bot/Actions/Extra/PluginMethods.cs index b8024a2..b3067e5 100644 --- a/DiscordBot/Bot/Actions/Extra/PluginMethods.cs +++ b/DiscordBot/Bot/Actions/Extra/PluginMethods.cs @@ -53,6 +53,9 @@ internal static class PluginMethods return; } + // rename the plugin to the name of the plugin + pluginName = pluginData.Name; + var pluginLink = pluginData.DownLoadLink; @@ -68,7 +71,7 @@ internal static class PluginMethods IProgress progress = new Progress(p => { downloadTask.Value = p; }); - await ServerCom.DownloadFileAsync(pluginLink, $"{Application.CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"]}/{pluginName}.dll", progress); + await ServerCom.DownloadFileAsync(pluginLink, $"{Application.CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"]}/{pluginData.Name}.dll", progress); downloadTask.Increment(100); @@ -84,7 +87,7 @@ internal static class PluginMethods await manager.ExecutePluginInstallScripts(pluginData.ScriptDependencies); } - PluginInfo pluginInfo = new(pluginName, pluginData.Version, new List()); + PluginInfo pluginInfo = new(pluginName, pluginData.Version, []); Console.WriteLine("Finished installing " + pluginName + " successfully"); await manager.AppendPluginToDatabase(pluginInfo); await RefreshPlugins(false); @@ -129,7 +132,8 @@ internal static class PluginMethods await Parallel.ForEachAsync(downloadTasks, options, async (tuple, token) => { tuple.Item1.IsIndeterminate = false; - await ServerCom.DownloadFileAsync(tuple.Item3, $"./{tuple.Item4}", tuple.Item2); + string downloadLocation = manager.GenerateDependencyLocation(pluginName, tuple.Item4); + await ServerCom.DownloadFileAsync(tuple.Item3, downloadLocation, tuple.Item2); } ); @@ -145,7 +149,7 @@ internal static class PluginMethods await manager.ExecutePluginInstallScripts(pluginData.ScriptDependencies); } - await manager.AppendPluginToDatabase(new PluginInfo(pluginName, pluginData.Version, pluginData.Dependencies.Select(sep => sep.DownloadLocation).ToList())); + await manager.AppendPluginToDatabase(PluginInfo.FromOnlineInfo(pluginData)); await RefreshPlugins(false); } diff --git a/DiscordBot/Bot/Actions/Help.cs b/DiscordBot/Bot/Actions/Help.cs index e9a30ce..a0ab731 100644 --- a/DiscordBot/Bot/Actions/Help.cs +++ b/DiscordBot/Bot/Actions/Help.cs @@ -21,7 +21,9 @@ public class Help: ICommandAction public string Usage => "help "; - public IEnumerable ListOfOptions => []; + public IEnumerable ListOfOptions => [ + new InternalActionOption("command", "The command to get help for") + ]; public InternalActionRunType RunType => InternalActionRunType.ON_CALL; diff --git a/DiscordBot/Entry.cs b/DiscordBot/Entry.cs index 15be462..ad1d7c1 100644 --- a/DiscordBot/Entry.cs +++ b/DiscordBot/Entry.cs @@ -69,9 +69,11 @@ public static class Entry static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args) { - var folderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "./Libraries"); + string requestingAssembly = args.RequestingAssembly?.GetName().Name; + var folderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, $"Libraries\\{requestingAssembly}"); var assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll"); - if (!File.Exists(assemblyPath)) return null; + if (!File.Exists(assemblyPath)) + return null; var assembly = Assembly.LoadFrom(assemblyPath); return assembly; diff --git a/DiscordBotCore/Interfaces/ICommandAction.cs b/DiscordBotCore/Interfaces/ICommandAction.cs index 4709bfb..3cf979e 100644 --- a/DiscordBotCore/Interfaces/ICommandAction.cs +++ b/DiscordBotCore/Interfaces/ICommandAction.cs @@ -19,4 +19,6 @@ public interface ICommandAction public InternalActionRunType RunType { get; } public Task Execute(string[]? args); + + public void ExecuteStartup() { } } diff --git a/DiscordBotCore/Loaders/ActionsLoader.cs b/DiscordBotCore/Loaders/ActionsLoader.cs index d5dc088..206d7f1 100644 --- a/DiscordBotCore/Loaders/ActionsLoader.cs +++ b/DiscordBotCore/Loaders/ActionsLoader.cs @@ -56,8 +56,8 @@ public class ActionsLoader continue; } - if (action.RunType == InternalActionRunType.ON_STARTUP) - await action.Execute(null); + if (action.RunType != InternalActionRunType.ON_CALL) + action.ExecuteStartup(); ActionLoadedEvent?.Invoke(action.ActionName, type.Name, true); actions.Add(action); diff --git a/DiscordBotCore/Online/PluginManager.cs b/DiscordBotCore/Online/PluginManager.cs index 462dce6..0d8086b 100644 --- a/DiscordBotCore/Online/PluginManager.cs +++ b/DiscordBotCore/Online/PluginManager.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using System.Threading.Tasks; using DiscordBotCore.Others; using DiscordBotCore.Plugin; @@ -58,7 +59,13 @@ public class PluginManager public async Task GetPluginDataByName(string pluginName) { List? plugins = await GetPluginsList(); - var result = plugins?.Find(p => p.Name == pluginName); + + if(plugins == null) + return null; + + // try to get the best matching plugin using the pluginName as a search query + PluginOnlineInfo? result = plugins.Find(pl => pl.Name.ToLower().Contains(pluginName.ToLower())); + if(result == null) return null; return result; } @@ -145,12 +152,45 @@ public class PluginManager { File.Delete(pluginInfo.FilePath); - foreach(string dependency in pluginInfo.ListOfDependancies) - File.Delete(dependency); + foreach (var dependency in pluginInfo.ListOfDependancies) + File.Delete(dependency.Value); await RemovePluginFromDatabase(pluginInfo.PluginName); } + public async Task GetDependencyLocation(string dependencyName) + { + List installedPlugins = await GetInstalledPlugins(); + + foreach (var plugin in installedPlugins) + { + if (plugin.ListOfDependancies.ContainsKey(dependencyName)) + return plugin.ListOfDependancies[dependencyName]; + } + + throw new Exception("Dependency not found"); + } + + public async Task GetDependencyLocation(string pluginName, string dependencyName) + { + PluginOnlineInfo? pluginData = await GetPluginDataByName(pluginName); + + if(pluginData == null) + throw new Exception("Plugin not found"); + + var dependency = pluginData.Dependencies.Find(dep => dep.DependencyName == dependencyName); + + if(dependency == null) + throw new Exception("Dependency not found"); + + return dependency.DownloadLocation; + } + + public string GenerateDependencyLocation(string pluginName, string dependencyName) + { + return Path.Combine(Environment.CurrentDirectory, $"Libraries/{pluginName}/{dependencyName}"); + } + public async Task InstallPlugin(PluginOnlineInfo pluginData, IProgress? installProgress) { installProgress?.Report(0f); @@ -171,7 +211,9 @@ public class PluginManager if (pluginData.HasFileDependencies) foreach (var dependency in pluginData.Dependencies) { - await ServerCom.DownloadFileAsync(dependency.DownloadLink, dependency.DownloadLocation, progress); + string dependencyLocation = GenerateDependencyLocation(pluginData.Name, dependency.DownloadLocation); + await ServerCom.DownloadFileAsync(dependency.DownloadLink, dependencyLocation, progress); + currentProgress += stepProgress; } @@ -186,12 +228,7 @@ public class PluginManager currentProgress += stepProgress; } - PluginInfo pluginInfo = new PluginInfo( - pluginData.Name, - pluginData.Version, - pluginData.Dependencies.Select(dep => dep.DownloadLocation) - .ToList() - ); + PluginInfo pluginInfo = PluginInfo.FromOnlineInfo(pluginData); await AppendPluginToDatabase(pluginInfo); } diff --git a/DiscordBotCore/Online/ServerCom.cs b/DiscordBotCore/Online/ServerCom.cs index 81f2dbb..382967a 100644 --- a/DiscordBotCore/Online/ServerCom.cs +++ b/DiscordBotCore/Online/ServerCom.cs @@ -48,7 +48,10 @@ public static class ServerCom using (var client = new HttpClient()) { client.Timeout = TimeSpan.FromMinutes(5); - + if(Directory.Exists(Path.GetDirectoryName(location)) == false) + { + Directory.CreateDirectory(Path.GetDirectoryName(location)); + } using (var file = new FileStream(location, FileMode.Create, FileAccess.Write, FileShare.None)) { await client.DownloadFileAsync(URL, file, progress, downloadedBytes); diff --git a/DiscordBotCore/Others/Actions/InternalActionsManager.cs b/DiscordBotCore/Others/Actions/InternalActionsManager.cs index 97420c5..f6d01de 100644 --- a/DiscordBotCore/Others/Actions/InternalActionsManager.cs +++ b/DiscordBotCore/Others/Actions/InternalActionsManager.cs @@ -45,6 +45,12 @@ public class InternalActionManager try { + if (Actions[actionName].RunType == InternalActionRunType.ON_STARTUP) + { + Application.CurrentApplication.Logger.Log($"Action {actionName} is not executable", this, LogType.ERROR); + return false; + } + await Actions[actionName].Execute(args); return true; } diff --git a/DiscordBotCore/Others/Enums.cs b/DiscordBotCore/Others/Enums.cs index 36b9d16..381daa1 100644 --- a/DiscordBotCore/Others/Enums.cs +++ b/DiscordBotCore/Others/Enums.cs @@ -22,7 +22,8 @@ public enum UnzipProgressType public enum InternalActionRunType { ON_STARTUP, - ON_CALL + ON_CALL, + BOTH } [Flags] diff --git a/DiscordBotCore/Plugin/OnlineDependencyInfo.cs b/DiscordBotCore/Plugin/OnlineDependencyInfo.cs index 345ba4e..36afdd5 100644 --- a/DiscordBotCore/Plugin/OnlineDependencyInfo.cs +++ b/DiscordBotCore/Plugin/OnlineDependencyInfo.cs @@ -1,12 +1,18 @@ + +using System.Text.Json.Serialization; + namespace DiscordBotCore.Plugin; public class OnlineDependencyInfo { + public string DependencyName { get; private set; } public string DownloadLink { get; private set; } public string DownloadLocation { get; private set; } - public OnlineDependencyInfo(string downloadLink, string downloadLocation) + [JsonConstructor] + public OnlineDependencyInfo(string dependencyName, string downloadLink, string downloadLocation) { + DependencyName = dependencyName; DownloadLink = downloadLink; DownloadLocation = downloadLocation; } diff --git a/DiscordBotCore/Plugin/PluginInfo.cs b/DiscordBotCore/Plugin/PluginInfo.cs index 90e2d17..52bb9a2 100644 --- a/DiscordBotCore/Plugin/PluginInfo.cs +++ b/DiscordBotCore/Plugin/PluginInfo.cs @@ -11,11 +11,11 @@ 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 Dictionary ListOfDependancies {get; private set;} public bool IsMarkedToUninstall {get; internal set;} [JsonConstructor] - public PluginInfo(string pluginName, PluginVersion pluginVersion, List listOfDependancies, bool isMarkedToUninstall) + public PluginInfo(string pluginName, PluginVersion pluginVersion, Dictionary listOfDependancies, bool isMarkedToUninstall) { PluginName = pluginName; PluginVersion = pluginVersion; @@ -24,7 +24,7 @@ public class PluginInfo FilePath = $"{Application.CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"]}/{pluginName}.dll"; } - public PluginInfo(string pluginName, PluginVersion pluginVersion, List listOfDependancies) + public PluginInfo(string pluginName, PluginVersion pluginVersion, Dictionary listOfDependancies) { PluginName = pluginName; PluginVersion = pluginVersion; @@ -35,6 +35,6 @@ public class PluginInfo public static PluginInfo FromOnlineInfo(PluginOnlineInfo onlineInfo) { - return new PluginInfo(onlineInfo.Name, onlineInfo.Version, onlineInfo.Dependencies.Select(dep => dep.DownloadLocation).ToList()); + return new PluginInfo(onlineInfo.Name, onlineInfo.Version, onlineInfo.Dependencies.Select(dep => new KeyValuePair(dep.DependencyName, dep.DownloadLocation)).ToDictionary()); } } diff --git a/DiscordBotUI/DiscordBotUI_Windows.csproj b/DiscordBotUI/DiscordBotUI_Windows.csproj index 2d86afd..d5aed9a 100644 --- a/DiscordBotUI/DiscordBotUI_Windows.csproj +++ b/DiscordBotUI/DiscordBotUI_Windows.csproj @@ -4,8 +4,9 @@ Library net8.0-windows enable - true + true enable + diff --git a/DiscordBotUI/Program.cs b/DiscordBotUI/Program.cs index 97c5184..d18134b 100644 --- a/DiscordBotUI/Program.cs +++ b/DiscordBotUI/Program.cs @@ -9,38 +9,7 @@ using DiscordBotUI_Windows.WindowsForms; namespace DiscordBotUI { - - public class DiscordEventUI : DBEvent - { - public string Name => "DiscordUI"; - - public bool RequireOtherThread => true; - public string Description => "Discord UI desc"; - - public async void Start(DiscordSocketClient client) - { - await Config.ApplicationSettings.LoadFromFile(); - - await Config.ThemeManager.LoadThemesFromThemesFolder(); - - if (Config.ApplicationSettings.ContainsKey("AppTheme")) - { - Config.ThemeManager.SetTheme(Config.ApplicationSettings["AppTheme"]); - } else Config.ApplicationSettings.Add("AppTheme", "Default"); - - Thread thread = new Thread(() => - { - MainWindow mainWindow = new MainWindow(); - Config.ThemeManager.SetFormTheme(Config.ThemeManager.CurrentTheme, mainWindow); - Application.Run(mainWindow); - - }); - thread.SetApartmentState(ApartmentState.STA); - thread.Start(); - } - } - - public class ConsoleStartAction : ICommandAction + public class DiscordUICommand : ICommandAction { public string ActionName => "ui"; @@ -51,19 +20,23 @@ namespace DiscordBotUI public IEnumerable ListOfOptions => [ new InternalActionOption("start", "Starts the UI") ]; + + public InternalActionRunType RunType => InternalActionRunType.BOTH; - public InternalActionRunType RunType => InternalActionRunType.ON_CALL; + public async void ExecuteStartup() + { + Directory.CreateDirectory(Path.Combine(DiscordBotCore.Application.CurrentApplication.DataFolder, "DiscordBotUI")); + await Execute(["start"]); + } public async Task Execute(string[]? args) { - if(args == null || args.Length == 0) + if (args == null || args.Length == 0) { Console.WriteLine("Please provide an option"); return; } - - if (args[0] == "theme") { if (args.Length == 1) @@ -72,7 +45,7 @@ namespace DiscordBotUI return; } - if(args[1] == "save") + if (args[1] == "save") { if (args.Length == 2) { @@ -84,7 +57,7 @@ namespace DiscordBotUI Console.WriteLine("Theme saved"); } - if(args[1] == "set") + if (args[1] == "set") { if (args.Length == 2) { @@ -106,26 +79,47 @@ namespace DiscordBotUI return; } - if(args[0] == "start") + if (args[0] == "start") { - await Config.ApplicationSettings.LoadFromFile(); - - await Config.ThemeManager.LoadThemesFromThemesFolder(); - - if (Config.ApplicationSettings.ContainsKey("AppTheme")) - { - Config.ThemeManager.SetTheme(Config.ApplicationSettings["AppTheme"]); - } - - Thread thread = new Thread(() => - { - MainWindow mainWindow = new MainWindow(); - Config.ThemeManager.SetFormTheme(Config.ThemeManager.CurrentTheme, mainWindow); - Application.Run(mainWindow); - }); - thread.SetApartmentState(ApartmentState.STA); - thread.Start(); + await StartUI(); } + } + + + private async Task StartUI() + { + await Config.ApplicationSettings.LoadFromFile(); + + await Config.ThemeManager.LoadThemesFromThemesFolder(); + + if (Config.ApplicationSettings.ContainsKey("AppTheme")) + { + Config.ThemeManager.SetTheme(Config.ApplicationSettings["AppTheme"]); + } + else Config.ApplicationSettings.Add("AppTheme", "Default"); + + await Config.ApplicationSettings.SaveToFile(); + + Thread thread = new Thread(() => + { + MainWindow mainWindow = new MainWindow(); + Config.ThemeManager.SetFormTheme(Config.ThemeManager.CurrentTheme, mainWindow); + Application.Run(mainWindow); + + }); + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + } + } + public class DiscordEventUI2 : DBEvent + { + public string Name => "DiscordUI"; + + public bool RequireOtherThread => true; + public string Description => "Discord UI desc"; + + public async void Start(DiscordSocketClient client) + { } } diff --git a/SethDiscordBot.sln b/SethDiscordBot.sln index 06e50c2..2ce2853 100644 --- a/SethDiscordBot.sln +++ b/SethDiscordBot.sln @@ -8,6 +8,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBotCore", "DiscordBo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBotUI_Windows", "DiscordBotUI\DiscordBotUI_Windows.csproj", "{95AD2D0C-D1EB-47B9-8DB4-F11CBAF15704}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{8FAEFF5E-F749-435C-BB7B-D57C0F8B17FC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MusicPlayer", "..\SethPlugins\MusicPlayer\MusicPlayer.csproj", "{F094D29D-6F1A-46BC-8B1F-88F3D98FCA84}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -26,10 +30,17 @@ Global {95AD2D0C-D1EB-47B9-8DB4-F11CBAF15704}.Debug|Any CPU.Build.0 = Debug|Any CPU {95AD2D0C-D1EB-47B9-8DB4-F11CBAF15704}.Release|Any CPU.ActiveCfg = Release|Any CPU {95AD2D0C-D1EB-47B9-8DB4-F11CBAF15704}.Release|Any CPU.Build.0 = Release|Any CPU + {F094D29D-6F1A-46BC-8B1F-88F3D98FCA84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F094D29D-6F1A-46BC-8B1F-88F3D98FCA84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F094D29D-6F1A-46BC-8B1F-88F3D98FCA84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F094D29D-6F1A-46BC-8B1F-88F3D98FCA84}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {F094D29D-6F1A-46BC-8B1F-88F3D98FCA84} = {8FAEFF5E-F749-435C-BB7B-D57C0F8B17FC} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF} EndGlobalSection