Actions are now loaded together with all plugins. Called the LoadPlugins at startup
This commit is contained in:
@@ -40,8 +40,9 @@ internal static class PluginMethods
|
|||||||
|
|
||||||
internal static async Task RefreshPlugins(bool quiet)
|
internal static async Task RefreshPlugins(bool quiet)
|
||||||
{
|
{
|
||||||
await Application.CurrentApplication.InternalActionManager.Execute("plugin", "load", quiet ? "-q" : string.Empty);
|
|
||||||
await Application.CurrentApplication.InternalActionManager.Refresh();
|
await LoadPlugins(quiet ? ["-q"] : null);
|
||||||
|
await Application.CurrentApplication.InternalActionManager.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task DownloadPlugin(PluginManager manager, string pluginName)
|
internal static async Task DownloadPlugin(PluginManager manager, string pluginName)
|
||||||
@@ -156,7 +157,7 @@ internal static class PluginMethods
|
|||||||
internal static async Task<bool> LoadPlugins(string[] args)
|
internal static async Task<bool> LoadPlugins(string[] args)
|
||||||
{
|
{
|
||||||
var loader = new PluginLoader(Application.CurrentApplication.DiscordBotClient.Client);
|
var loader = new PluginLoader(Application.CurrentApplication.DiscordBotClient.Client);
|
||||||
if (args.Length == 2 && args[1] == "-q")
|
if (args != null && (args.Length == 2 && args[1] == "-q"))
|
||||||
{
|
{
|
||||||
await loader.LoadPlugins();
|
await loader.LoadPlugins();
|
||||||
return true;
|
return true;
|
||||||
@@ -211,6 +212,22 @@ internal static class PluginMethods
|
|||||||
Console.ForegroundColor = cc;
|
Console.ForegroundColor = cc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
loader.OnActionLoaded += (data) =>
|
||||||
|
{
|
||||||
|
if (data.IsSuccess)
|
||||||
|
{
|
||||||
|
Application.CurrentApplication.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,
|
||||||
|
typeof(PluginMethods), LogType.ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.ForegroundColor = cc;
|
||||||
|
};
|
||||||
|
|
||||||
await loader.LoadPlugins();
|
await loader.LoadPlugins();
|
||||||
Console.ForegroundColor = cc;
|
Console.ForegroundColor = cc;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -38,15 +38,15 @@ public class Help: ICommandAction
|
|||||||
|
|
||||||
tableData.Columns = ["Command", "Usage", "Description", "Options"];
|
tableData.Columns = ["Command", "Usage", "Description", "Options"];
|
||||||
|
|
||||||
foreach (var a in Application.CurrentApplication.InternalActionManager.Actions)
|
foreach (var a in Application.CurrentApplication.InternalActionManager.GetActions())
|
||||||
{
|
{
|
||||||
Markup actionName = new Markup($"[bold]{a.Key}[/]");
|
Markup actionName = new Markup($"[bold]{a.ActionName}[/]");
|
||||||
Markup usage = new Markup($"[italic]{a.Value.Usage}[/]");
|
Markup usage = new Markup($"[italic]{a.Usage}[/]");
|
||||||
Markup description = new Markup($"[dim]{a.Value.Description}[/]");
|
Markup description = new Markup($"[dim]{a.Description}[/]");
|
||||||
|
|
||||||
if (a.Value.ListOfOptions.Any())
|
if (a.ListOfOptions.Any())
|
||||||
{
|
{
|
||||||
tableData.AddRow([actionName, usage, description, CreateTableWithSubOptions(a.Value.ListOfOptions)]);
|
tableData.AddRow([actionName, usage, description, CreateTableWithSubOptions(a.ListOfOptions)]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -64,13 +64,13 @@ public class Help: ICommandAction
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Application.CurrentApplication.InternalActionManager.Actions.ContainsKey(args[0]))
|
if (!Application.CurrentApplication.InternalActionManager.Exists(args[0]))
|
||||||
{
|
{
|
||||||
Console.WriteLine("Command not found");
|
Console.WriteLine("Command not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var action = Application.CurrentApplication.InternalActionManager.Actions[args[0]];
|
var action = Application.CurrentApplication.InternalActionManager.GetAction(args[0]);
|
||||||
tableData.Columns = ["Command", "Usage", "Description"];
|
tableData.Columns = ["Command", "Usage", "Description"];
|
||||||
tableData.AddRow([action.ActionName, action.Usage, action.Description]);
|
tableData.AddRow([action.ActionName, action.Usage, action.Description]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Discord;
|
using Discord;
|
||||||
@@ -31,7 +32,11 @@ public class Help: DBSlashCommand
|
|||||||
EmbedBuilder embedBuilder = new();
|
EmbedBuilder embedBuilder = new();
|
||||||
|
|
||||||
embedBuilder.WithTitle("Help Command");
|
embedBuilder.WithTitle("Help Command");
|
||||||
embedBuilder.WithColor(Functions.RandomColor);
|
|
||||||
|
var random = new Random();
|
||||||
|
Color c = new Color(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255));
|
||||||
|
|
||||||
|
embedBuilder.WithColor(c);
|
||||||
var slashCommands = PluginLoader.SlashCommands;
|
var slashCommands = PluginLoader.SlashCommands;
|
||||||
var options = context.Data.Options;
|
var options = context.Data.Options;
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using DiscordBot.Bot.Actions.Extra;
|
||||||
|
|
||||||
using DiscordBotCore;
|
using DiscordBotCore;
|
||||||
using DiscordBotCore.Bot;
|
using DiscordBotCore.Bot;
|
||||||
using DiscordBotCore.Others;
|
using DiscordBotCore.Others;
|
||||||
@@ -22,6 +24,8 @@ public class Program
|
|||||||
{
|
{
|
||||||
await LoadComponents(args);
|
await LoadComponents(args);
|
||||||
await PrepareConsole();
|
await PrepareConsole();
|
||||||
|
await PluginMethods.LoadPlugins(null);
|
||||||
|
await Application.CurrentApplication.InternalActionManager.Initialize();
|
||||||
await ConsoleInputHandler();
|
await ConsoleInputHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +34,6 @@ public class Program
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static async Task ConsoleInputHandler()
|
private static async Task ConsoleInputHandler()
|
||||||
{
|
{
|
||||||
await Application.CurrentApplication.InternalActionManager.Execute("plugin", "load");
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@@ -65,7 +68,7 @@ public class Program
|
|||||||
{
|
{
|
||||||
var token = Application.CurrentApplication.ApplicationEnvironmentVariables["token"];
|
var token = Application.CurrentApplication.ApplicationEnvironmentVariables["token"];
|
||||||
var prefix = Application.CurrentApplication.ApplicationEnvironmentVariables["prefix"];
|
var prefix = Application.CurrentApplication.ApplicationEnvironmentVariables["prefix"];
|
||||||
var discordbooter = new Boot(token, prefix);
|
var discordbooter = new App(token, prefix);
|
||||||
await discordbooter.Awake();
|
await discordbooter.Awake();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -118,6 +121,8 @@ public class Program
|
|||||||
!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("token") ||
|
!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("token") ||
|
||||||
!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("prefix"))
|
!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("prefix"))
|
||||||
await Installer.GenerateStartupConfig();
|
await Installer.GenerateStartupConfig();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace DiscordBotCore
|
|||||||
public InternalActionManager InternalActionManager { get; private set; }
|
public InternalActionManager InternalActionManager { get; private set; }
|
||||||
public PluginManager PluginManager { get; private set; }
|
public PluginManager PluginManager { get; private set; }
|
||||||
public Logger Logger { get; private set; }
|
public Logger Logger { get; private set; }
|
||||||
public Bot.Boot DiscordBotClient { get; internal set; }
|
public Bot.App DiscordBotClient { get; internal set; }
|
||||||
|
|
||||||
public static async Task CreateApplication()
|
public static async Task CreateApplication()
|
||||||
{
|
{
|
||||||
@@ -78,7 +78,7 @@ namespace DiscordBotCore
|
|||||||
await CurrentApplication.PluginManager.UninstallMarkedPlugins();
|
await CurrentApplication.PluginManager.UninstallMarkedPlugins();
|
||||||
await CurrentApplication.PluginManager.CheckForUpdates();
|
await CurrentApplication.PluginManager.CheckForUpdates();
|
||||||
|
|
||||||
CurrentApplication.InternalActionManager = new InternalActionManager(CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"], "dll");
|
CurrentApplication.InternalActionManager = new InternalActionManager();
|
||||||
await CurrentApplication.InternalActionManager.Initialize();
|
await CurrentApplication.InternalActionManager.Initialize();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ using DiscordBotCore.Others;
|
|||||||
|
|
||||||
namespace DiscordBotCore.Bot;
|
namespace DiscordBotCore.Bot;
|
||||||
|
|
||||||
public class Boot
|
public class App
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The bot prefix
|
/// The bot prefix
|
||||||
@@ -41,7 +41,7 @@ public class Boot
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="botToken">The bot token</param>
|
/// <param name="botToken">The bot token</param>
|
||||||
/// <param name="botPrefix">The bot prefix</param>
|
/// <param name="botPrefix">The bot prefix</param>
|
||||||
public Boot(string botToken, string botPrefix)
|
public App(string botToken, string botPrefix)
|
||||||
{
|
{
|
||||||
this.BotPrefix = botPrefix;
|
this.BotPrefix = botPrefix;
|
||||||
this.BotToken = botToken;
|
this.BotToken = botToken;
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using DiscordBotCore.Interfaces;
|
|
||||||
using DiscordBotCore.Others;
|
|
||||||
|
|
||||||
namespace DiscordBotCore.Loaders;
|
|
||||||
|
|
||||||
public class ActionsLoader
|
|
||||||
{
|
|
||||||
public delegate void ActionLoaded(string name, string typeName, bool success, Exception? e = null);
|
|
||||||
|
|
||||||
private readonly string _actionExtension;
|
|
||||||
|
|
||||||
private readonly string _actionFolder;
|
|
||||||
|
|
||||||
public ActionsLoader(string path, string extension)
|
|
||||||
{
|
|
||||||
_actionFolder = path;
|
|
||||||
_actionExtension = extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
public event ActionLoaded? ActionLoadedEvent;
|
|
||||||
|
|
||||||
public async Task<List<ICommandAction>?> Load()
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(_actionFolder);
|
|
||||||
var files = Directory.GetFiles(_actionFolder, $"*.{_actionExtension}", SearchOption.AllDirectories);
|
|
||||||
|
|
||||||
var actions = new List<ICommandAction>();
|
|
||||||
|
|
||||||
foreach (var file in files)
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assembly.LoadFrom(file);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ActionLoadedEvent?.Invoke(file, "", false, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
var types = AppDomain.CurrentDomain.GetAssemblies()
|
|
||||||
.SelectMany(s => s.GetTypes())
|
|
||||||
.Where(p => typeof(ICommandAction).IsAssignableFrom(p) && !p.IsInterface);
|
|
||||||
|
|
||||||
foreach (var type in types)
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var action = (ICommandAction)Activator.CreateInstance(type);
|
|
||||||
if (action.ActionName == null)
|
|
||||||
{
|
|
||||||
ActionLoadedEvent?.Invoke(action.ActionName, type.Name, false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (action.RunType != InternalActionRunType.ON_CALL)
|
|
||||||
action.ExecuteStartup();
|
|
||||||
|
|
||||||
ActionLoadedEvent?.Invoke(action.ActionName, type.Name, true);
|
|
||||||
actions.Add(action);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ActionLoadedEvent?.Invoke(type.Name, type.Name, false, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return actions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,8 +10,6 @@ namespace DiscordBotCore.Loaders;
|
|||||||
|
|
||||||
internal class Loader
|
internal class Loader
|
||||||
{
|
{
|
||||||
private readonly string _SearchPath;
|
|
||||||
private readonly string _FileExtension;
|
|
||||||
|
|
||||||
internal delegate void FileLoadedHandler(FileLoaderResult result);
|
internal delegate void FileLoadedHandler(FileLoaderResult result);
|
||||||
|
|
||||||
@@ -20,24 +18,11 @@ internal class Loader
|
|||||||
internal event FileLoadedHandler? OnFileLoadedException;
|
internal event FileLoadedHandler? OnFileLoadedException;
|
||||||
internal event PluginLoadedHandler? OnPluginLoaded;
|
internal event PluginLoadedHandler? OnPluginLoaded;
|
||||||
|
|
||||||
internal Loader(string searchPath, string fileExtension)
|
|
||||||
{
|
|
||||||
_SearchPath = searchPath;
|
|
||||||
_FileExtension = fileExtension;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal async Task Load()
|
internal async Task Load()
|
||||||
{
|
{
|
||||||
if (!Directory.Exists(_SearchPath))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(_SearchPath);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var installedPlugins = await Application.CurrentApplication.PluginManager.GetInstalledPlugins();
|
var installedPlugins = await Application.CurrentApplication.PluginManager.GetInstalledPlugins();
|
||||||
var files = installedPlugins.Select(plugin => plugin.FilePath).ToArray();
|
var files = installedPlugins.Select(plugin => plugin.FilePath).ToArray();
|
||||||
|
|
||||||
//var files = Directory.GetFiles(_SearchPath, $"*.{_FileExtension}", SearchOption.TopDirectoryOnly);
|
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -53,6 +38,7 @@ internal class Loader
|
|||||||
await LoadEverythingOfType<DBEvent>();
|
await LoadEverythingOfType<DBEvent>();
|
||||||
await LoadEverythingOfType<DBCommand>();
|
await LoadEverythingOfType<DBCommand>();
|
||||||
await LoadEverythingOfType<DBSlashCommand>();
|
await LoadEverythingOfType<DBSlashCommand>();
|
||||||
|
await LoadEverythingOfType<ICommandAction>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadEverythingOfType<T>()
|
private async Task LoadEverythingOfType<T>()
|
||||||
@@ -77,6 +63,7 @@ internal class Loader
|
|||||||
DBEvent => PluginType.EVENT,
|
DBEvent => PluginType.EVENT,
|
||||||
DBCommand => PluginType.COMMAND,
|
DBCommand => PluginType.COMMAND,
|
||||||
DBSlashCommand => PluginType.SLASH_COMMAND,
|
DBSlashCommand => PluginType.SLASH_COMMAND,
|
||||||
|
ICommandAction => PluginType.ACTION,
|
||||||
_ => PluginType.UNKNOWN
|
_ => PluginType.UNKNOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using DiscordBotCore.Interfaces;
|
using DiscordBotCore.Interfaces;
|
||||||
@@ -17,13 +19,17 @@ public class PluginLoader
|
|||||||
|
|
||||||
public delegate void SlashCommandLoaded(PluginLoadResultData resultData);
|
public delegate void SlashCommandLoaded(PluginLoadResultData resultData);
|
||||||
|
|
||||||
|
public delegate void ActionLoaded(PluginLoadResultData resultData);
|
||||||
|
|
||||||
public CommandLoaded? OnCommandLoaded;
|
public CommandLoaded? OnCommandLoaded;
|
||||||
public EventLoaded? OnEventLoaded;
|
public EventLoaded? OnEventLoaded;
|
||||||
public SlashCommandLoaded? OnSlashCommandLoaded;
|
public SlashCommandLoaded? OnSlashCommandLoaded;
|
||||||
|
public ActionLoaded? OnActionLoaded;
|
||||||
|
|
||||||
public static List<DBCommand> Commands { get; private set; } = new List<DBCommand>();
|
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<DBEvent> Events { get; private set; } = new List<DBEvent>();
|
||||||
public static List<DBSlashCommand> SlashCommands { get; private set; } = new List<DBSlashCommand>();
|
public static List<DBSlashCommand> SlashCommands { get; private set; } = new List<DBSlashCommand>();
|
||||||
|
public static List<ICommandAction> Actions { get; private set; } = new List<ICommandAction>();
|
||||||
|
|
||||||
public PluginLoader(DiscordSocketClient discordSocketClient)
|
public PluginLoader(DiscordSocketClient discordSocketClient)
|
||||||
{
|
{
|
||||||
@@ -34,9 +40,7 @@ public class PluginLoader
|
|||||||
{
|
{
|
||||||
Application.CurrentApplication.Logger.Log("Loading plugins...", this);
|
Application.CurrentApplication.Logger.Log("Loading plugins...", this);
|
||||||
|
|
||||||
var loader = new Loader(Application.CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"], "dll");
|
var loader = new Loader();
|
||||||
|
|
||||||
//await this.ResetSlashCommands();
|
|
||||||
|
|
||||||
loader.OnFileLoadedException += FileLoadedException;
|
loader.OnFileLoadedException += FileLoadedException;
|
||||||
loader.OnPluginLoaded += OnPluginLoaded;
|
loader.OnPluginLoaded += OnPluginLoaded;
|
||||||
@@ -53,6 +57,17 @@ public class PluginLoader
|
|||||||
{
|
{
|
||||||
switch (result.PluginType)
|
switch (result.PluginType)
|
||||||
{
|
{
|
||||||
|
case PluginType.ACTION:
|
||||||
|
ICommandAction action = (ICommandAction)result.Plugin;
|
||||||
|
if (action.RunType == InternalActionRunType.ON_STARTUP || action.RunType == InternalActionRunType.BOTH)
|
||||||
|
action.ExecuteStartup();
|
||||||
|
|
||||||
|
if(action.RunType == InternalActionRunType.ON_CALL || action.RunType == InternalActionRunType.BOTH)
|
||||||
|
Actions.Add(action);
|
||||||
|
|
||||||
|
OnActionLoaded?.Invoke(result);
|
||||||
|
|
||||||
|
break;
|
||||||
case PluginType.COMMAND:
|
case PluginType.COMMAND:
|
||||||
Commands.Add((DBCommand)result.Plugin);
|
Commands.Add((DBCommand)result.Plugin);
|
||||||
OnCommandLoaded?.Invoke(result);
|
OnCommandLoaded?.Invoke(result);
|
||||||
|
|||||||
@@ -9,6 +9,44 @@ namespace DiscordBotCore.Online.Helpers;
|
|||||||
|
|
||||||
internal static class OnlineFunctions
|
internal static class OnlineFunctions
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copy one Stream to another <see langword="async" />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream">The base stream</param>
|
||||||
|
/// <param name="destination">The destination stream</param>
|
||||||
|
/// <param name="bufferSize">The buffer to read</param>
|
||||||
|
/// <param name="progress">The progress</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token</param>
|
||||||
|
/// <exception cref="ArgumentNullException">Triggered if any <see cref="Stream" /> is empty</exception>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">Triggered if <paramref name="bufferSize" /> is less then or equal to 0</exception>
|
||||||
|
/// <exception cref="InvalidOperationException">Triggered if <paramref name="stream" /> is not readable</exception>
|
||||||
|
/// <exception cref="ArgumentException">Triggered in <paramref name="destination" /> is not writable</exception>
|
||||||
|
public static async Task CopyToOtherStreamAsync(
|
||||||
|
this Stream stream, Stream destination, int bufferSize,
|
||||||
|
IProgress<long>? progress = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
if (stream == null) throw new ArgumentNullException(nameof(stream));
|
||||||
|
if (destination == null) throw new ArgumentNullException(nameof(destination));
|
||||||
|
if (bufferSize <= 0) throw new ArgumentOutOfRangeException(nameof(bufferSize));
|
||||||
|
if (!stream.CanRead) throw new InvalidOperationException("The stream is not readable.");
|
||||||
|
if (!destination.CanWrite)
|
||||||
|
throw new ArgumentException("Destination stream is not writable", nameof(destination));
|
||||||
|
|
||||||
|
var buffer = new byte[bufferSize];
|
||||||
|
long totalBytesRead = 0;
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken)
|
||||||
|
.ConfigureAwait(false)) != 0)
|
||||||
|
{
|
||||||
|
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
|
||||||
|
totalBytesRead += bytesRead;
|
||||||
|
progress?.Report(totalBytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Downloads a <see cref="Stream" /> and saves it to another <see cref="Stream" />.
|
/// Downloads a <see cref="Stream" /> and saves it to another <see cref="Stream" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Frozen;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -88,6 +89,10 @@ public class PluginManager
|
|||||||
public async Task AppendPluginToDatabase(PluginInfo pluginData)
|
public async Task AppendPluginToDatabase(PluginInfo pluginData)
|
||||||
{
|
{
|
||||||
List<PluginInfo> installedPlugins = await JsonManager.ConvertFromJson<List<PluginInfo>>(await File.ReadAllTextAsync(Application.CurrentApplication.PluginDatabase));
|
List<PluginInfo> installedPlugins = await JsonManager.ConvertFromJson<List<PluginInfo>>(await File.ReadAllTextAsync(Application.CurrentApplication.PluginDatabase));
|
||||||
|
foreach (var dependency in pluginData.ListOfDependancies)
|
||||||
|
{
|
||||||
|
pluginData.ListOfDependancies[dependency.Key] = GenerateDependencyLocation(pluginData.PluginName, dependency.Value);
|
||||||
|
}
|
||||||
|
|
||||||
installedPlugins.Add(pluginData);
|
installedPlugins.Add(pluginData);
|
||||||
await JsonManager.SaveToJsonFile(Application.CurrentApplication.PluginDatabase, installedPlugins);
|
await JsonManager.SaveToJsonFile(Application.CurrentApplication.PluginDatabase, installedPlugins);
|
||||||
@@ -123,15 +128,19 @@ public class PluginManager
|
|||||||
|
|
||||||
public async Task<bool> MarkPluginToUninstall(string pluginName)
|
public async Task<bool> MarkPluginToUninstall(string pluginName)
|
||||||
{
|
{
|
||||||
List<PluginInfo> installedPlugins = await GetInstalledPlugins();
|
IEnumerable<PluginInfo> installedPlugins = await GetInstalledPlugins();
|
||||||
PluginInfo? info = installedPlugins.Find(info => info.PluginName == pluginName);
|
IEnumerable<PluginInfo> info = installedPlugins.Where(info => info.PluginName == pluginName).AsEnumerable();
|
||||||
|
|
||||||
if(info == null)
|
if(!info.Any())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
await RemovePluginFromDatabase(pluginName);
|
foreach (var item in info)
|
||||||
info.IsMarkedToUninstall = true;
|
{
|
||||||
await AppendPluginToDatabase(info);
|
await RemovePluginFromDatabase(item.PluginName);
|
||||||
|
item.IsMarkedToUninstall = true;
|
||||||
|
await AppendPluginToDatabase(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -139,11 +148,11 @@ public class PluginManager
|
|||||||
|
|
||||||
public async Task UninstallMarkedPlugins()
|
public async Task UninstallMarkedPlugins()
|
||||||
{
|
{
|
||||||
List<PluginInfo> installedPlugins = await GetInstalledPlugins();
|
IEnumerable<PluginInfo> installedPlugins = (await GetInstalledPlugins()).AsEnumerable();
|
||||||
foreach(PluginInfo plugin in installedPlugins)
|
IEnumerable<PluginInfo> pluginsToRemove = installedPlugins.Where(plugin => plugin.IsMarkedToUninstall).AsEnumerable();
|
||||||
{
|
|
||||||
if(!plugin.IsMarkedToUninstall) continue;
|
|
||||||
|
|
||||||
|
foreach (var plugin in pluginsToRemove)
|
||||||
|
{
|
||||||
await UninstallPlugin(plugin);
|
await UninstallPlugin(plugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,21 +180,6 @@ public class PluginManager
|
|||||||
throw new Exception("Dependency not found");
|
throw new Exception("Dependency not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> 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)
|
public string GenerateDependencyLocation(string pluginName, string dependencyName)
|
||||||
{
|
{
|
||||||
return Path.Combine(Environment.CurrentDirectory, $"Libraries/{pluginName}/{dependencyName}");
|
return Path.Combine(Environment.CurrentDirectory, $"Libraries/{pluginName}/{dependencyName}");
|
||||||
|
|||||||
@@ -8,31 +8,36 @@ namespace DiscordBotCore.Others.Actions;
|
|||||||
|
|
||||||
public class InternalActionManager
|
public class InternalActionManager
|
||||||
{
|
{
|
||||||
public Dictionary<string, ICommandAction> Actions = new();
|
private Dictionary<string, ICommandAction> Actions = new();
|
||||||
|
|
||||||
private readonly ActionsLoader _loader;
|
|
||||||
|
|
||||||
public InternalActionManager(string path, string extension)
|
|
||||||
{
|
|
||||||
_loader = new ActionsLoader(path, extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task Initialize()
|
public async Task Initialize()
|
||||||
{
|
{
|
||||||
var loadedActions = await _loader.Load();
|
Actions.Clear();
|
||||||
|
PluginLoader.Actions.ForEach(action =>
|
||||||
if (loadedActions == null)
|
{
|
||||||
return;
|
if (action.RunType == InternalActionRunType.ON_CALL || action.RunType == InternalActionRunType.BOTH)
|
||||||
|
{
|
||||||
foreach (var action in loadedActions)
|
if (this.Actions.ContainsKey(action.ActionName))
|
||||||
Actions.TryAdd(action.ActionName, action);
|
return; // ingore duplicates
|
||||||
|
|
||||||
|
this.Actions.Add(action.ActionName, action);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Refresh()
|
public IReadOnlyCollection<ICommandAction> GetActions()
|
||||||
{
|
{
|
||||||
Actions.Clear();
|
return Actions.Values;
|
||||||
await Initialize();
|
}
|
||||||
|
|
||||||
|
public bool Exists(string actionName)
|
||||||
|
{
|
||||||
|
return Actions.ContainsKey(actionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICommandAction GetAction(string actionName)
|
||||||
|
{
|
||||||
|
return Actions[actionName];
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> Execute(string actionName, params string[]? args)
|
public async Task<bool> Execute(string actionName, params string[]? args)
|
||||||
|
|||||||
@@ -40,5 +40,6 @@ public enum PluginType
|
|||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
COMMAND,
|
COMMAND,
|
||||||
EVENT,
|
EVENT,
|
||||||
SLASH_COMMAND
|
SLASH_COMMAND,
|
||||||
|
ACTION
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Discord;
|
|
||||||
|
|
||||||
namespace DiscordBotCore.Others;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A special class with functions
|
|
||||||
/// </summary>
|
|
||||||
public static class Functions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The location for the Resources folder
|
|
||||||
/// String: ./Data/Resources/
|
|
||||||
/// </summary>
|
|
||||||
public static string dataFolder => Application.CurrentApplication.DataFolder;
|
|
||||||
|
|
||||||
public static Color RandomColor
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var random = new Random();
|
|
||||||
return new Color(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Copy one Stream to another <see langword="async" />
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">The base stream</param>
|
|
||||||
/// <param name="destination">The destination stream</param>
|
|
||||||
/// <param name="bufferSize">The buffer to read</param>
|
|
||||||
/// <param name="progress">The progress</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token</param>
|
|
||||||
/// <exception cref="ArgumentNullException">Triggered if any <see cref="Stream" /> is empty</exception>
|
|
||||||
/// <exception cref="ArgumentOutOfRangeException">Triggered if <paramref name="bufferSize" /> is less then or equal to 0</exception>
|
|
||||||
/// <exception cref="InvalidOperationException">Triggered if <paramref name="stream" /> is not readable</exception>
|
|
||||||
/// <exception cref="ArgumentException">Triggered in <paramref name="destination" /> is not writable</exception>
|
|
||||||
public static async Task CopyToOtherStreamAsync(
|
|
||||||
this Stream stream, Stream destination, int bufferSize,
|
|
||||||
IProgress<long>? progress = null,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
if (stream == null) throw new ArgumentNullException(nameof(stream));
|
|
||||||
if (destination == null) throw new ArgumentNullException(nameof(destination));
|
|
||||||
if (bufferSize <= 0) throw new ArgumentOutOfRangeException(nameof(bufferSize));
|
|
||||||
if (!stream.CanRead) throw new InvalidOperationException("The stream is not readable.");
|
|
||||||
if (!destination.CanWrite)
|
|
||||||
throw new ArgumentException("Destination stream is not writable", nameof(destination));
|
|
||||||
|
|
||||||
var buffer = new byte[bufferSize];
|
|
||||||
long totalBytesRead = 0;
|
|
||||||
int bytesRead;
|
|
||||||
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken)
|
|
||||||
.ConfigureAwait(false)) != 0)
|
|
||||||
{
|
|
||||||
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
|
|
||||||
totalBytesRead += bytesRead;
|
|
||||||
progress?.Report(totalBytesRead);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static T SelectRandomValueOf<T>()
|
|
||||||
{
|
|
||||||
var enums = Enum.GetValues(typeof(T));
|
|
||||||
var random = new Random();
|
|
||||||
return (T)enums.GetValue(random.Next(enums.Length));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static T RandomValue<T>(this T[] values)
|
|
||||||
{
|
|
||||||
Random random = new();
|
|
||||||
return values[random.Next(values.Length)];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ToResourcesPath(this string path)
|
|
||||||
{
|
|
||||||
return Path.Combine(dataFolder, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user