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)
|
||||
{
|
||||
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)
|
||||
@@ -156,7 +157,7 @@ internal static class PluginMethods
|
||||
internal static async Task<bool> LoadPlugins(string[] args)
|
||||
{
|
||||
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();
|
||||
return true;
|
||||
@@ -211,6 +212,22 @@ internal static class PluginMethods
|
||||
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();
|
||||
Console.ForegroundColor = cc;
|
||||
return true;
|
||||
|
||||
@@ -38,15 +38,15 @@ public class Help: ICommandAction
|
||||
|
||||
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 usage = new Markup($"[italic]{a.Value.Usage}[/]");
|
||||
Markup description = new Markup($"[dim]{a.Value.Description}[/]");
|
||||
Markup actionName = new Markup($"[bold]{a.ActionName}[/]");
|
||||
Markup usage = new Markup($"[italic]{a.Usage}[/]");
|
||||
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
|
||||
{
|
||||
@@ -64,13 +64,13 @@ public class Help: ICommandAction
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Application.CurrentApplication.InternalActionManager.Actions.ContainsKey(args[0]))
|
||||
if (!Application.CurrentApplication.InternalActionManager.Exists(args[0]))
|
||||
{
|
||||
Console.WriteLine("Command not found");
|
||||
return;
|
||||
}
|
||||
|
||||
var action = Application.CurrentApplication.InternalActionManager.Actions[args[0]];
|
||||
var action = Application.CurrentApplication.InternalActionManager.GetAction(args[0]);
|
||||
tableData.Columns = ["Command", "Usage", "Description"];
|
||||
tableData.AddRow([action.ActionName, action.Usage, action.Description]);
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Discord;
|
||||
@@ -31,7 +32,11 @@ public class Help: DBSlashCommand
|
||||
EmbedBuilder embedBuilder = new();
|
||||
|
||||
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 options = context.Data.Options;
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using DiscordBot.Bot.Actions.Extra;
|
||||
|
||||
using DiscordBotCore;
|
||||
using DiscordBotCore.Bot;
|
||||
using DiscordBotCore.Others;
|
||||
@@ -22,6 +24,8 @@ public class Program
|
||||
{
|
||||
await LoadComponents(args);
|
||||
await PrepareConsole();
|
||||
await PluginMethods.LoadPlugins(null);
|
||||
await Application.CurrentApplication.InternalActionManager.Initialize();
|
||||
await ConsoleInputHandler();
|
||||
}
|
||||
|
||||
@@ -30,7 +34,6 @@ public class Program
|
||||
/// </summary>
|
||||
private static async Task ConsoleInputHandler()
|
||||
{
|
||||
await Application.CurrentApplication.InternalActionManager.Execute("plugin", "load");
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -65,7 +68,7 @@ public class Program
|
||||
{
|
||||
var token = Application.CurrentApplication.ApplicationEnvironmentVariables["token"];
|
||||
var prefix = Application.CurrentApplication.ApplicationEnvironmentVariables["prefix"];
|
||||
var discordbooter = new Boot(token, prefix);
|
||||
var discordbooter = new App(token, prefix);
|
||||
await discordbooter.Awake();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -118,6 +121,8 @@ public class Program
|
||||
!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("token") ||
|
||||
!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("prefix"))
|
||||
await Installer.GenerateStartupConfig();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace DiscordBotCore
|
||||
public InternalActionManager InternalActionManager { get; private set; }
|
||||
public PluginManager PluginManager { 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()
|
||||
{
|
||||
@@ -78,7 +78,7 @@ namespace DiscordBotCore
|
||||
await CurrentApplication.PluginManager.UninstallMarkedPlugins();
|
||||
await CurrentApplication.PluginManager.CheckForUpdates();
|
||||
|
||||
CurrentApplication.InternalActionManager = new InternalActionManager(CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"], "dll");
|
||||
CurrentApplication.InternalActionManager = new InternalActionManager();
|
||||
await CurrentApplication.InternalActionManager.Initialize();
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ using DiscordBotCore.Others;
|
||||
|
||||
namespace DiscordBotCore.Bot;
|
||||
|
||||
public class Boot
|
||||
public class App
|
||||
{
|
||||
/// <summary>
|
||||
/// The bot prefix
|
||||
@@ -41,7 +41,7 @@ public class Boot
|
||||
/// </summary>
|
||||
/// <param name="botToken">The bot token</param>
|
||||
/// <param name="botPrefix">The bot prefix</param>
|
||||
public Boot(string botToken, string botPrefix)
|
||||
public App(string botToken, string botPrefix)
|
||||
{
|
||||
this.BotPrefix = botPrefix;
|
||||
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
|
||||
{
|
||||
private readonly string _SearchPath;
|
||||
private readonly string _FileExtension;
|
||||
|
||||
internal delegate void FileLoadedHandler(FileLoaderResult result);
|
||||
|
||||
@@ -20,24 +18,11 @@ internal class Loader
|
||||
internal event FileLoadedHandler? OnFileLoadedException;
|
||||
internal event PluginLoadedHandler? OnPluginLoaded;
|
||||
|
||||
internal Loader(string searchPath, string fileExtension)
|
||||
{
|
||||
_SearchPath = searchPath;
|
||||
_FileExtension = fileExtension;
|
||||
}
|
||||
|
||||
internal async Task Load()
|
||||
{
|
||||
if (!Directory.Exists(_SearchPath))
|
||||
{
|
||||
Directory.CreateDirectory(_SearchPath);
|
||||
return;
|
||||
}
|
||||
|
||||
var installedPlugins = await Application.CurrentApplication.PluginManager.GetInstalledPlugins();
|
||||
var files = installedPlugins.Select(plugin => plugin.FilePath).ToArray();
|
||||
|
||||
//var files = Directory.GetFiles(_SearchPath, $"*.{_FileExtension}", SearchOption.TopDirectoryOnly);
|
||||
foreach (var file in files)
|
||||
{
|
||||
try
|
||||
@@ -53,6 +38,7 @@ internal class Loader
|
||||
await LoadEverythingOfType<DBEvent>();
|
||||
await LoadEverythingOfType<DBCommand>();
|
||||
await LoadEverythingOfType<DBSlashCommand>();
|
||||
await LoadEverythingOfType<ICommandAction>();
|
||||
}
|
||||
|
||||
private async Task LoadEverythingOfType<T>()
|
||||
@@ -77,6 +63,7 @@ internal class Loader
|
||||
DBEvent => PluginType.EVENT,
|
||||
DBCommand => PluginType.COMMAND,
|
||||
DBSlashCommand => PluginType.SLASH_COMMAND,
|
||||
ICommandAction => PluginType.ACTION,
|
||||
_ => PluginType.UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.WebSocket;
|
||||
using DiscordBotCore.Interfaces;
|
||||
@@ -17,13 +19,17 @@ public class PluginLoader
|
||||
|
||||
public delegate void SlashCommandLoaded(PluginLoadResultData resultData);
|
||||
|
||||
public delegate void ActionLoaded(PluginLoadResultData resultData);
|
||||
|
||||
public CommandLoaded? OnCommandLoaded;
|
||||
public EventLoaded? OnEventLoaded;
|
||||
public SlashCommandLoaded? OnSlashCommandLoaded;
|
||||
public ActionLoaded? OnActionLoaded;
|
||||
|
||||
public static List<DBCommand> Commands { get; private set; } = new List<DBCommand>();
|
||||
public static List<DBEvent> Events { get; private set; } = new List<DBEvent>();
|
||||
public static List<DBSlashCommand> SlashCommands { get; private set; } = new List<DBSlashCommand>();
|
||||
public static List<ICommandAction> Actions { get; private set; } = new List<ICommandAction>();
|
||||
|
||||
public PluginLoader(DiscordSocketClient discordSocketClient)
|
||||
{
|
||||
@@ -34,9 +40,7 @@ public class PluginLoader
|
||||
{
|
||||
Application.CurrentApplication.Logger.Log("Loading plugins...", this);
|
||||
|
||||
var loader = new Loader(Application.CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"], "dll");
|
||||
|
||||
//await this.ResetSlashCommands();
|
||||
var loader = new Loader();
|
||||
|
||||
loader.OnFileLoadedException += FileLoadedException;
|
||||
loader.OnPluginLoaded += OnPluginLoaded;
|
||||
@@ -53,6 +57,17 @@ public class PluginLoader
|
||||
{
|
||||
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:
|
||||
Commands.Add((DBCommand)result.Plugin);
|
||||
OnCommandLoaded?.Invoke(result);
|
||||
|
||||
@@ -9,6 +9,44 @@ namespace DiscordBotCore.Online.Helpers;
|
||||
|
||||
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>
|
||||
/// Downloads a <see cref="Stream" /> and saves it to another <see cref="Stream" />.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -88,7 +89,11 @@ public class PluginManager
|
||||
public async Task AppendPluginToDatabase(PluginInfo pluginData)
|
||||
{
|
||||
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);
|
||||
await JsonManager.SaveToJsonFile(Application.CurrentApplication.PluginDatabase, installedPlugins);
|
||||
}
|
||||
@@ -123,15 +128,19 @@ public class PluginManager
|
||||
|
||||
public async Task<bool> MarkPluginToUninstall(string pluginName)
|
||||
{
|
||||
List<PluginInfo> installedPlugins = await GetInstalledPlugins();
|
||||
PluginInfo? info = installedPlugins.Find(info => info.PluginName == pluginName);
|
||||
IEnumerable<PluginInfo> installedPlugins = await GetInstalledPlugins();
|
||||
IEnumerable<PluginInfo> info = installedPlugins.Where(info => info.PluginName == pluginName).AsEnumerable();
|
||||
|
||||
if(info == null)
|
||||
if(!info.Any())
|
||||
return false;
|
||||
|
||||
await RemovePluginFromDatabase(pluginName);
|
||||
info.IsMarkedToUninstall = true;
|
||||
await AppendPluginToDatabase(info);
|
||||
foreach (var item in info)
|
||||
{
|
||||
await RemovePluginFromDatabase(item.PluginName);
|
||||
item.IsMarkedToUninstall = true;
|
||||
await AppendPluginToDatabase(item);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
@@ -139,11 +148,11 @@ public class PluginManager
|
||||
|
||||
public async Task UninstallMarkedPlugins()
|
||||
{
|
||||
List<PluginInfo> installedPlugins = await GetInstalledPlugins();
|
||||
foreach(PluginInfo plugin in installedPlugins)
|
||||
{
|
||||
if(!plugin.IsMarkedToUninstall) continue;
|
||||
IEnumerable<PluginInfo> installedPlugins = (await GetInstalledPlugins()).AsEnumerable();
|
||||
IEnumerable<PluginInfo> pluginsToRemove = installedPlugins.Where(plugin => plugin.IsMarkedToUninstall).AsEnumerable();
|
||||
|
||||
foreach (var plugin in pluginsToRemove)
|
||||
{
|
||||
await UninstallPlugin(plugin);
|
||||
}
|
||||
}
|
||||
@@ -171,21 +180,6 @@ public class PluginManager
|
||||
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)
|
||||
{
|
||||
return Path.Combine(Environment.CurrentDirectory, $"Libraries/{pluginName}/{dependencyName}");
|
||||
|
||||
@@ -8,31 +8,36 @@ namespace DiscordBotCore.Others.Actions;
|
||||
|
||||
public class InternalActionManager
|
||||
{
|
||||
public Dictionary<string, ICommandAction> Actions = new();
|
||||
|
||||
private readonly ActionsLoader _loader;
|
||||
|
||||
public InternalActionManager(string path, string extension)
|
||||
{
|
||||
_loader = new ActionsLoader(path, extension);
|
||||
}
|
||||
private Dictionary<string, ICommandAction> Actions = new();
|
||||
|
||||
public async Task Initialize()
|
||||
{
|
||||
var loadedActions = await _loader.Load();
|
||||
Actions.Clear();
|
||||
PluginLoader.Actions.ForEach(action =>
|
||||
{
|
||||
if (action.RunType == InternalActionRunType.ON_CALL || action.RunType == InternalActionRunType.BOTH)
|
||||
{
|
||||
if (this.Actions.ContainsKey(action.ActionName))
|
||||
return; // ingore duplicates
|
||||
|
||||
if (loadedActions == null)
|
||||
return;
|
||||
|
||||
foreach (var action in loadedActions)
|
||||
Actions.TryAdd(action.ActionName, action);
|
||||
|
||||
this.Actions.Add(action.ActionName, action);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task Refresh()
|
||||
public IReadOnlyCollection<ICommandAction> GetActions()
|
||||
{
|
||||
Actions.Clear();
|
||||
await Initialize();
|
||||
return Actions.Values;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -40,5 +40,6 @@ public enum PluginType
|
||||
UNKNOWN,
|
||||
COMMAND,
|
||||
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