Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3858156393 | |||
| 6279c5c3a9 | |||
| f58a57c6cd | |||
| d00ebfd7ed | |||
| ab279bd284 | |||
| 89c4932cd7 | |||
| c577f625c2 | |||
| 58624f4037 | |||
| c9249dc71b | |||
| 5e4f1ca35f | |||
| 0d8fdb5904 | |||
| 92a18e3495 | |||
| e929646e8e | |||
| 6315d13d18 | |||
| ee527bb36f | |||
| 86514d1770 | |||
| 9e8ed1e911 | |||
| f3c3c7939c | |||
| 361ed37362 | |||
| ed3128b940 | |||
| 6bbd68a135 | |||
| 06d322b5b3 | |||
| 5497ee9119 | |||
| 0aa78e3560 | |||
| 41ad37b3bb | |||
| 0104d09509 | |||
| b4f5e40f12 | |||
| 7107b17f19 | |||
| 42e1fd917e | |||
| 9e6fcdbe6f | |||
| a24d8aa222 | |||
| 0e5c9ff14b | |||
| f8977d8840 | |||
| bb9768f3a1 | |||
| b3d6930142 | |||
| 5254be44be | |||
| 207e0d6abd | |||
| 968d23380f | |||
| fff9e2e897 | |||
| 3e4e777d8d | |||
| 7f906d400f | |||
| c1161a3bca | |||
| ac512e3a27 | |||
| 730b628fe3 | |||
| 701edc5c6a | |||
| e7688762b8 | |||
| a7a71bf49a | |||
| ac7212ca00 | |||
| 298e557260 | |||
| 7ba791f906 | |||
| 4a6a12baae | |||
| f1dda5da3c | |||
| 3ab96e2d0d | |||
| 970c519a32 | |||
| 188920ec7f | |||
| dcfc4ea32f | |||
| a8c02176d3 | |||
| 1665d47a25 | |||
| 0b2f1e6ab6 | |||
| bcd9245502 | |||
| 59da9b295b | |||
| 99d7d5e7e7 | |||
| e4c60f1606 | |||
| 77f1bef862 | |||
| f16c139362 | |||
| c94cdca6eb | |||
| dcdf80112d | |||
| eb836c5b74 | |||
| de680c6771 | |||
|
|
bcef58a46b | ||
|
|
0dc8cdbce5 | ||
|
|
dbdbaa9802 | ||
|
|
5edcf93371 | ||
|
|
b0be76c62b | ||
| 75a77389a8 | |||
| 0bbced3d58 | |||
| 244209093e | |||
| 54a68d635d | |||
| d7a5cb5a64 | |||
| 6124f89cb0 | |||
| 810a527cc1 | |||
| 0a2dff0c6d | |||
| 382c376c03 | |||
| 84b7d663bc | |||
| 623232b67e | |||
| d5df6cfb9d | |||
| 10b9548c29 | |||
| fa1a136ef1 | |||
| d20cb62139 | |||
| f2418d0395 | |||
| 460a85944a | |||
| 7e2fa02d07 | |||
| 873855937f | |||
| 1cdd2644df | |||
| 532540b74f | |||
| 9ba4ca43e2 | |||
| 8bcaf3f254 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -371,3 +371,6 @@ FodyWeavers.xsd
|
|||||||
/DiscordBot.rar
|
/DiscordBot.rar
|
||||||
/DiscordBot/Data/
|
/DiscordBot/Data/
|
||||||
/DiscordBot/Updater/
|
/DiscordBot/Updater/
|
||||||
|
.idea/
|
||||||
|
DiscordBot/Launcher.exe
|
||||||
|
DiscordBotUI/*
|
||||||
|
|||||||
26
.vscode/launch.json
vendored
Normal file
26
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
// Use IntelliSense to find out which attributes exist for C# debugging
|
||||||
|
// Use hover for the description of the existing attributes
|
||||||
|
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
||||||
|
"name": ".NET Core Launch (console)",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "build",
|
||||||
|
// If you have changed target frameworks, make sure to update the program path.
|
||||||
|
"program": "${workspaceFolder}/DiscordBot/bin/Debug/net6.0/DiscordBot.dll",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}/DiscordBot/bin/Debug/net6.0/",
|
||||||
|
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||||
|
"console": "externalTerminal",
|
||||||
|
"stopAtEntry": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": ".NET Core Attach",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "attach"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
41
.vscode/tasks.json
vendored
Normal file
41
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "build",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"${workspaceFolder}/DiscordBot/DiscordBot.csproj",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "publish",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"publish",
|
||||||
|
"${workspaceFolder}/DiscordBot/DiscordBot.csproj",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "watch",
|
||||||
|
"command": "dotnet",
|
||||||
|
"type": "process",
|
||||||
|
"args": [
|
||||||
|
"watch",
|
||||||
|
"run",
|
||||||
|
"--project",
|
||||||
|
"${workspaceFolder}/DiscordBot/DiscordBot.csproj"
|
||||||
|
],
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
23
DiscordBot/Bot/Actions/Clear.cs
Normal file
23
DiscordBot/Bot/Actions/Clear.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
using PluginManager.Others;
|
||||||
|
|
||||||
|
namespace DiscordBot.Bot.Actions;
|
||||||
|
|
||||||
|
public class Clear : ICommandAction
|
||||||
|
{
|
||||||
|
public string ActionName => "clear";
|
||||||
|
public string Description => "Clears the console";
|
||||||
|
public string Usage => "clear";
|
||||||
|
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
|
||||||
|
|
||||||
|
public Task Execute(string[] args)
|
||||||
|
{
|
||||||
|
Console.Clear();
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Console.WriteLine("===== Seth Discord Bot =====");
|
||||||
|
Console.ResetColor();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
46
DiscordBot/Bot/Actions/Exit.cs
Normal file
46
DiscordBot/Bot/Actions/Exit.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using PluginManager;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
using PluginManager.Others;
|
||||||
|
|
||||||
|
namespace DiscordBot.Bot.Actions;
|
||||||
|
|
||||||
|
public class Exit : ICommandAction
|
||||||
|
{
|
||||||
|
public string ActionName => "exit";
|
||||||
|
public string Description => "Exits the bot and saves the config. Use exit help for more info.";
|
||||||
|
public string Usage => "exit [help|force (-f)]";
|
||||||
|
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
|
||||||
|
|
||||||
|
public async Task Execute(string[] args)
|
||||||
|
{
|
||||||
|
if (args is null || args.Length == 0)
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Exiting...", source: typeof(ICommandAction), type: LogType.WARNING);
|
||||||
|
await Config.AppSettings.SaveToFile();
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch ( args[0] )
|
||||||
|
{
|
||||||
|
case "help":
|
||||||
|
Console.WriteLine("Usage : exit [help|force]");
|
||||||
|
Console.WriteLine("help : Displays this message");
|
||||||
|
Console.WriteLine("force | -f : Exits the bot without saving the config");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "-f":
|
||||||
|
case "force":
|
||||||
|
Config.Logger.Log("Exiting (FORCE)...", source: typeof(ICommandAction), type: LogType.WARNING);
|
||||||
|
Environment.Exit(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Console.WriteLine("Invalid argument !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
204
DiscordBot/Bot/Actions/Extra/PluginMethods.cs
Normal file
204
DiscordBot/Bot/Actions/Extra/PluginMethods.cs
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using DiscordBot.Utilities;
|
||||||
|
using PluginManager;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
using PluginManager.Loaders;
|
||||||
|
using PluginManager.Online;
|
||||||
|
using PluginManager.Others;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace DiscordBot.Bot.Actions.Extra;
|
||||||
|
|
||||||
|
internal static class PluginMethods
|
||||||
|
{
|
||||||
|
private static readonly PluginsManager PluginsManager = new();
|
||||||
|
|
||||||
|
internal static async Task List()
|
||||||
|
{
|
||||||
|
var data = await ConsoleUtilities.ExecuteWithProgressBar(PluginsManager.GetAvailablePlugins(), "Loading plugins...");
|
||||||
|
|
||||||
|
TableData tableData = new(new List<string> { "Name", "Description", "Type", "Version" });
|
||||||
|
foreach (var plugin in data) tableData.AddRow(plugin);
|
||||||
|
|
||||||
|
tableData.HasRoundBorders = false;
|
||||||
|
tableData.PrintAsTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static async Task RefreshPlugins(bool quiet)
|
||||||
|
{
|
||||||
|
await Program.internalActionManager.Execute("plugin", "load", quiet ? "-q" : string.Empty);
|
||||||
|
await Program.internalActionManager.Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static async Task DownloadPlugin(PluginsManager manager, string pluginName)
|
||||||
|
{
|
||||||
|
var pluginData = await manager.GetPluginLinkByName(pluginName);
|
||||||
|
if (pluginData.Length == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Plugin {pluginName} not found. Please check the spelling and try again.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pluginType = pluginData[0];
|
||||||
|
var pluginLink = pluginData[1];
|
||||||
|
var pluginRequirements = pluginData[2];
|
||||||
|
|
||||||
|
|
||||||
|
await AnsiConsole.Progress()
|
||||||
|
.Columns(new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(),
|
||||||
|
new ProgressBarColumn(),
|
||||||
|
new PercentageColumn()
|
||||||
|
})
|
||||||
|
.StartAsync(async ctx =>
|
||||||
|
{
|
||||||
|
var downloadTask = ctx.AddTask("Downloading plugin...");
|
||||||
|
|
||||||
|
IProgress<float> progress = new Progress<float>(p => { downloadTask.Value = p; });
|
||||||
|
|
||||||
|
await ServerCom.DownloadFileAsync(pluginLink, $"./Data/{pluginType}s/{pluginName}.dll", progress);
|
||||||
|
|
||||||
|
downloadTask.Increment(100);
|
||||||
|
|
||||||
|
ctx.Refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (pluginRequirements == string.Empty)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Finished installing " + pluginName + " successfully");
|
||||||
|
await RefreshPlugins(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<string> requirementsUrLs = new();
|
||||||
|
|
||||||
|
await AnsiConsole.Progress()
|
||||||
|
.Columns(new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(),
|
||||||
|
new ProgressBarColumn(),
|
||||||
|
new PercentageColumn()
|
||||||
|
})
|
||||||
|
.StartAsync(async ctx =>
|
||||||
|
{
|
||||||
|
var gatherInformationTask = ctx.AddTask("Gathering info...");
|
||||||
|
gatherInformationTask.IsIndeterminate = true;
|
||||||
|
requirementsUrLs = await ServerCom.ReadTextFromURL(pluginRequirements);
|
||||||
|
await Task.Delay(2000);
|
||||||
|
gatherInformationTask.Increment(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
await AnsiConsole.Progress()
|
||||||
|
.Columns(new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(),
|
||||||
|
new ProgressBarColumn(),
|
||||||
|
new PercentageColumn()
|
||||||
|
})
|
||||||
|
.StartAsync(async ctx =>
|
||||||
|
{
|
||||||
|
List<Tuple<ProgressTask, IProgress<float>, Task>> downloadTasks = new();
|
||||||
|
|
||||||
|
foreach (var info in requirementsUrLs)
|
||||||
|
{
|
||||||
|
if (info.Length < 2) continue;
|
||||||
|
string[] data = info.Split(',');
|
||||||
|
string url = data[0];
|
||||||
|
string fileName = data[1];
|
||||||
|
|
||||||
|
var task = ctx.AddTask($"Downloading {fileName}...");
|
||||||
|
IProgress<float> progress = new Progress<float>(p =>
|
||||||
|
{
|
||||||
|
task.Value = p;
|
||||||
|
});
|
||||||
|
|
||||||
|
var downloadTask = ServerCom.DownloadFileAsync(url, $"./{fileName}", progress);
|
||||||
|
downloadTasks.Add(new Tuple<ProgressTask, IProgress<float>, Task>(task, progress, downloadTask));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var task in downloadTasks)
|
||||||
|
{
|
||||||
|
await task.Item3;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
await RefreshPlugins(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static async Task<bool> LoadPlugins(string[] args)
|
||||||
|
{
|
||||||
|
var loader = new PluginLoader(Config.DiscordBot.client);
|
||||||
|
if (args.Length == 2 && args[1] == "-q")
|
||||||
|
{
|
||||||
|
loader.LoadPlugins();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cc = Console.ForegroundColor;
|
||||||
|
loader.onCMDLoad += (name, typeName, success, exception) =>
|
||||||
|
{
|
||||||
|
if (name == null || name.Length < 2)
|
||||||
|
name = typeName;
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Successfully loaded command : " + name, source: typeof(ICommandAction),
|
||||||
|
type: LogType.INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Failed to load command : " + name + " because " + exception?.Message,
|
||||||
|
source: typeof(ICommandAction), type: LogType.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.ForegroundColor = cc;
|
||||||
|
};
|
||||||
|
loader.onEVELoad += (name, typeName, success, exception) =>
|
||||||
|
{
|
||||||
|
if (name == null || name.Length < 2)
|
||||||
|
name = typeName;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Successfully loaded event : " + name, source: typeof(ICommandAction),
|
||||||
|
type: LogType.INFO);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Failed to load event : " + name + " because " + exception?.Message,
|
||||||
|
source: typeof(ICommandAction), type: LogType.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.ForegroundColor = cc;
|
||||||
|
};
|
||||||
|
|
||||||
|
loader.onSLSHLoad += (name, typeName, success, exception) =>
|
||||||
|
{
|
||||||
|
if (name == null || name.Length < 2)
|
||||||
|
name = typeName;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Successfully loaded slash command : " + name, source: typeof(ICommandAction),
|
||||||
|
type: LogType.INFO);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Failed to load slash command : " + name + " because " + exception?.Message,
|
||||||
|
source: typeof(ICommandAction), type: LogType.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.ForegroundColor = cc;
|
||||||
|
};
|
||||||
|
|
||||||
|
loader.LoadPlugins();
|
||||||
|
Console.ForegroundColor = cc;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
43
DiscordBot/Bot/Actions/Extra/SettingsConfigExtra.cs
Normal file
43
DiscordBot/Bot/Actions/Extra/SettingsConfigExtra.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using PluginManager;
|
||||||
|
|
||||||
|
namespace DiscordBot.Bot.Actions.Extra;
|
||||||
|
|
||||||
|
internal static class SettingsConfigExtra
|
||||||
|
{
|
||||||
|
internal static void SetSettings(string key, params string[] value)
|
||||||
|
{
|
||||||
|
if (key is null) return;
|
||||||
|
|
||||||
|
if (value is null) return;
|
||||||
|
|
||||||
|
if (!Config.AppSettings.ContainsKey(key))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Config.AppSettings[key] = string.Join(' ', value);
|
||||||
|
// Config.AppSettings.SaveToFile().Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void RemoveSettings(string key)
|
||||||
|
{
|
||||||
|
if (key is null) return;
|
||||||
|
|
||||||
|
if(!Config.AppSettings.ContainsKey(key))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Config.AppSettings.Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void AddSettings(string key, params string[] value)
|
||||||
|
{
|
||||||
|
if (key is null) return;
|
||||||
|
|
||||||
|
if (value is null) return;
|
||||||
|
|
||||||
|
if (Config.AppSettings.ContainsKey(key))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Config.AppSettings.Add(key, string.Join(' ', value));
|
||||||
|
// Config.AppSettings.SaveToFile().Wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
62
DiscordBot/Bot/Actions/Help.cs
Normal file
62
DiscordBot/Bot/Actions/Help.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using DiscordBot.Utilities;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
using PluginManager.Others;
|
||||||
|
|
||||||
|
namespace DiscordBot.Bot.Actions;
|
||||||
|
|
||||||
|
public class Help : ICommandAction
|
||||||
|
{
|
||||||
|
public string ActionName => "help";
|
||||||
|
|
||||||
|
public string Description => "Shows the list of commands and their usage";
|
||||||
|
|
||||||
|
public string Usage => "help [command]";
|
||||||
|
|
||||||
|
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
|
||||||
|
|
||||||
|
public async Task Execute(string[] args)
|
||||||
|
{
|
||||||
|
if (args == null || args.Length == 0)
|
||||||
|
{
|
||||||
|
var items = new List<string[]>
|
||||||
|
{
|
||||||
|
new[] { "-", "-", "-" },
|
||||||
|
new[] { "Command", "Usage", "Description" },
|
||||||
|
new[] { "-", "-", "-" }
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var a in Program.internalActionManager.Actions)
|
||||||
|
items.Add(new[] { a.Key, a.Value.Usage, a.Value.Description });
|
||||||
|
|
||||||
|
items.Add(new[] { "-", "-", "-" });
|
||||||
|
|
||||||
|
ConsoleUtilities.FormatAndAlignTable(items,
|
||||||
|
TableFormat.CENTER_EACH_COLUMN_BASED
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Program.internalActionManager.Actions.ContainsKey(args[0]))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Command not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var action = Program.internalActionManager.Actions[args[0]];
|
||||||
|
var actionData = new List<string[]>
|
||||||
|
{
|
||||||
|
new[] { "-", "-", "-" },
|
||||||
|
new[] { "Command", "Usage", "Description" },
|
||||||
|
new[] { "-", "-", "-" },
|
||||||
|
new[] { action.ActionName, action.Usage, action.Description },
|
||||||
|
new[] { "-", "-", "-" }
|
||||||
|
};
|
||||||
|
|
||||||
|
ConsoleUtilities.FormatAndAlignTable(actionData,
|
||||||
|
TableFormat.CENTER_EACH_COLUMN_BASED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
82
DiscordBot/Bot/Actions/Plugin.cs
Normal file
82
DiscordBot/Bot/Actions/Plugin.cs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using DiscordBot.Bot.Actions.Extra;
|
||||||
|
using PluginManager;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
using PluginManager.Loaders;
|
||||||
|
using PluginManager.Online;
|
||||||
|
using PluginManager.Others;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace DiscordBot.Bot.Actions;
|
||||||
|
|
||||||
|
public class Plugin : ICommandAction
|
||||||
|
{
|
||||||
|
private bool pluginsLoaded;
|
||||||
|
public string ActionName => "plugin";
|
||||||
|
public string Description => "Manages plugins. Use plugin help for more info.";
|
||||||
|
public string Usage => "plugin [help|list|load|install|refresh]";
|
||||||
|
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
|
||||||
|
|
||||||
|
public async Task Execute(string[] args)
|
||||||
|
{
|
||||||
|
if (args is null || args.Length == 0 || args[0] == "help")
|
||||||
|
{
|
||||||
|
Console.WriteLine("Usage : plugin [help|list|load|install]");
|
||||||
|
Console.WriteLine("help : Displays this message");
|
||||||
|
Console.WriteLine("list : Lists all plugins");
|
||||||
|
Console.WriteLine("load : Loads all plugins");
|
||||||
|
Console.WriteLine("install : Installs a plugin");
|
||||||
|
Console.WriteLine("refresh : Refreshes the plugin list");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var manager = new PluginsManager();
|
||||||
|
|
||||||
|
switch (args[0])
|
||||||
|
{
|
||||||
|
case "refresh":
|
||||||
|
await PluginMethods.RefreshPlugins(true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "list":
|
||||||
|
await PluginMethods.List();
|
||||||
|
break;
|
||||||
|
case "load":
|
||||||
|
if (pluginsLoaded)
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Plugins already loaded", source: typeof(ICommandAction), type: LogType.WARNING);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Config.DiscordBot is null)
|
||||||
|
{
|
||||||
|
Config.Logger.Log("DiscordBot is null", source: typeof(ICommandAction), type: LogType.WARNING);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginsLoaded = await PluginMethods.LoadPlugins(args);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "install":
|
||||||
|
var pluginName = string.Join(' ', args, 1, args.Length - 1);
|
||||||
|
if (string.IsNullOrEmpty(pluginName) || pluginName.Length < 2)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Please specify a plugin name");
|
||||||
|
Console.Write("Plugin name : ");
|
||||||
|
pluginName = Console.ReadLine();
|
||||||
|
if (string.IsNullOrEmpty(pluginName) || pluginName.Length < 2)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Invalid plugin name");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await PluginMethods.DownloadPlugin(manager, pluginName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
67
DiscordBot/Bot/Actions/SettingsConfig.cs
Normal file
67
DiscordBot/Bot/Actions/SettingsConfig.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using DiscordBot.Bot.Actions.Extra;
|
||||||
|
using PluginManager;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
using PluginManager.Others;
|
||||||
|
|
||||||
|
namespace DiscordBot.Bot.Actions;
|
||||||
|
|
||||||
|
public class SettingsConfig : ICommandAction
|
||||||
|
{
|
||||||
|
public string ActionName => "config";
|
||||||
|
public string Description => "Change the settings of the bot";
|
||||||
|
public string Usage => "config [options] <setting?> <value?>";
|
||||||
|
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
|
||||||
|
public Task Execute(string[] args)
|
||||||
|
{
|
||||||
|
if (args is null)
|
||||||
|
{
|
||||||
|
foreach (var settings in Config.AppSettings)
|
||||||
|
Console.WriteLine(settings.Key + ": " + settings.Value);
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (args[0])
|
||||||
|
{
|
||||||
|
case "-s":
|
||||||
|
case "set":
|
||||||
|
if(args.Length < 3)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
SettingsConfigExtra.SetSettings(args[1],args[2..]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "-r":
|
||||||
|
case "remove":
|
||||||
|
if(args.Length < 2)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
SettingsConfigExtra.RemoveSettings(args[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "-a":
|
||||||
|
case "add":
|
||||||
|
if(args.Length < 3)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
SettingsConfigExtra.AddSettings(args[1], args[2..]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "-h":
|
||||||
|
case "-help":
|
||||||
|
Console.WriteLine("Options:");
|
||||||
|
Console.WriteLine("-s <settingName> <newValue>: Set a setting");
|
||||||
|
Console.WriteLine("-r <settingName>: Remove a setting");
|
||||||
|
Console.WriteLine("-a <settingName> <newValue>: Add a setting");
|
||||||
|
Console.WriteLine("-h: Show this help message");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Console.WriteLine("Invalid option");
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,11 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
|
||||||
using PluginManager;
|
using PluginManager;
|
||||||
using PluginManager.Interfaces;
|
using PluginManager.Interfaces;
|
||||||
using PluginManager.Loaders;
|
using PluginManager.Loaders;
|
||||||
using PluginManager.Others;
|
using PluginManager.Others;
|
||||||
|
|
||||||
namespace DiscordBot.Discord.Commands;
|
namespace DiscordBot.Bot.Commands;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The help command
|
/// The help command
|
||||||
@@ -41,7 +38,7 @@ internal class Help : DBCommand
|
|||||||
/// The main body of the command
|
/// The main body of the command
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">The command context</param>
|
/// <param name="context">The command context</param>
|
||||||
public void ExecuteServer(CmdArgs args)
|
public void ExecuteServer(DBCommandExecutingArguments args)
|
||||||
{
|
{
|
||||||
if (args.arguments is not null)
|
if (args.arguments is not null)
|
||||||
{
|
{
|
||||||
@@ -60,16 +57,16 @@ internal class Help : DBCommand
|
|||||||
var adminCommands = "";
|
var adminCommands = "";
|
||||||
var normalCommands = "";
|
var normalCommands = "";
|
||||||
|
|
||||||
foreach (var cmd in PluginLoader.Commands!)
|
foreach (var cmd in PluginLoader.Commands)
|
||||||
if (cmd.requireAdmin)
|
if (cmd.requireAdmin)
|
||||||
adminCommands += cmd.Command + " ";
|
adminCommands += cmd.Command + " ";
|
||||||
else
|
else
|
||||||
normalCommands += cmd.Command + " ";
|
normalCommands += cmd.Command + " ";
|
||||||
|
|
||||||
|
|
||||||
if(adminCommands.Length > 0)
|
if (adminCommands.Length > 0)
|
||||||
embedBuilder.AddField("Admin Commands", adminCommands);
|
embedBuilder.AddField("Admin Commands", adminCommands);
|
||||||
if(normalCommands.Length > 0)
|
if (normalCommands.Length > 0)
|
||||||
embedBuilder.AddField("Normal Commands", normalCommands);
|
embedBuilder.AddField("Normal Commands", normalCommands);
|
||||||
args.context.Channel.SendMessageAsync(embed: embedBuilder.Build());
|
args.context.Channel.SendMessageAsync(embed: embedBuilder.Build());
|
||||||
}
|
}
|
||||||
@@ -77,11 +74,12 @@ internal class Help : DBCommand
|
|||||||
private EmbedBuilder GenerateHelpCommand(string command)
|
private EmbedBuilder GenerateHelpCommand(string command)
|
||||||
{
|
{
|
||||||
var embedBuilder = new EmbedBuilder();
|
var embedBuilder = new EmbedBuilder();
|
||||||
var cmd = PluginLoader.Commands!.Find(p => p.Command == command ||
|
var cmd = PluginLoader.Commands.Find(p => p.Command == command ||
|
||||||
(p.Aliases is not null && p.Aliases.Contains(command)));
|
p.Aliases is not null && p.Aliases.Contains(command)
|
||||||
|
);
|
||||||
if (cmd == null) return null;
|
if (cmd == null) return null;
|
||||||
|
|
||||||
embedBuilder.AddField("Usage", Config.Variables.GetValue("prefix") + cmd.Usage);
|
embedBuilder.AddField("Usage", Config.AppSettings["prefix"] + cmd.Usage);
|
||||||
embedBuilder.AddField("Description", cmd.Description);
|
embedBuilder.AddField("Description", cmd.Description);
|
||||||
if (cmd.Aliases is null)
|
if (cmd.Aliases is null)
|
||||||
return embedBuilder;
|
return embedBuilder;
|
||||||
57
DiscordBot/Bot/Commands/SlashCommands/Help.cs
Normal file
57
DiscordBot/Bot/Commands/SlashCommands/Help.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
using PluginManager.Loaders;
|
||||||
|
using PluginManager.Others;
|
||||||
|
|
||||||
|
namespace DiscordBot.Bot.Commands.SlashCommands;
|
||||||
|
|
||||||
|
public class Help : DBSlashCommand
|
||||||
|
{
|
||||||
|
public string Name => "help";
|
||||||
|
public string Description => "This command allows you to check all loaded commands";
|
||||||
|
public bool canUseDM => true;
|
||||||
|
|
||||||
|
public List<SlashCommandOptionBuilder> Options =>
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
new SlashCommandOptionBuilder()
|
||||||
|
.WithName("command")
|
||||||
|
.WithDescription("The command you want to get help for")
|
||||||
|
.WithRequired(false)
|
||||||
|
.WithType(ApplicationCommandOptionType.String)
|
||||||
|
};
|
||||||
|
|
||||||
|
public async void ExecuteServer(SocketSlashCommand context)
|
||||||
|
{
|
||||||
|
EmbedBuilder embedBuilder = new();
|
||||||
|
|
||||||
|
embedBuilder.WithTitle("Help Command");
|
||||||
|
embedBuilder.WithColor(Functions.RandomColor);
|
||||||
|
var slashCommands = PluginLoader.SlashCommands;
|
||||||
|
var options = context.Data.Options;
|
||||||
|
|
||||||
|
//Console.WriteLine("Options: " + options.Count);
|
||||||
|
if (options is null || options.Count == 0)
|
||||||
|
foreach (var slashCommand in slashCommands)
|
||||||
|
embedBuilder.AddField(slashCommand.Name, slashCommand.Description);
|
||||||
|
|
||||||
|
if (options.Count > 0)
|
||||||
|
{
|
||||||
|
var commandName = options.First().Name;
|
||||||
|
var slashCommand = slashCommands.FirstOrDefault(x => x.Name == commandName);
|
||||||
|
if (slashCommand is null)
|
||||||
|
{
|
||||||
|
await context.RespondAsync("Unknown Command " + commandName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
embedBuilder.AddField(slashCommand.Name, slashCommand.canUseDM)
|
||||||
|
.WithDescription(slashCommand.Description);
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.RespondAsync(embed: embedBuilder.Build());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,48 +1,43 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Nullable>disable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
<ApplicationIcon />
|
<ApplicationIcon/>
|
||||||
<StartupObject />
|
<StartupObject/>
|
||||||
<SignAssembly>False</SignAssembly>
|
<SignAssembly>False</SignAssembly>
|
||||||
<IsPublishable>True</IsPublishable>
|
<IsPublishable>True</IsPublishable>
|
||||||
<AssemblyVersion>1.0.1.2</AssemblyVersion>
|
<AssemblyVersion>1.0.3.1</AssemblyVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="Data\**" />
|
<Compile Remove="Data\**"/>
|
||||||
<Compile Remove="obj\**" />
|
<Compile Remove="obj\**"/>
|
||||||
<Compile Remove="Output\**" />
|
<Compile Remove="Output\**"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Remove="Data\**" />
|
<EmbeddedResource Remove="Data\**"/>
|
||||||
<EmbeddedResource Remove="obj\**" />
|
<EmbeddedResource Remove="obj\**"/>
|
||||||
<EmbeddedResource Remove="Output\**" />
|
<EmbeddedResource Remove="Output\**"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Data\**" />
|
<None Remove="Data\**"/>
|
||||||
<None Remove="obj\**" />
|
<None Remove="obj\**"/>
|
||||||
<None Remove="Output\**" />
|
<None Remove="Output\**"/>
|
||||||
|
<None Remove="builder.bat" />
|
||||||
|
<None Remove="builder.sh" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Discord.Net" Version="3.9.0" />
|
<PackageReference Include="Discord.Net" Version="3.11.0"/>
|
||||||
|
<PackageReference Include="pythonnet" Version="3.0.1" />
|
||||||
|
<PackageReference Include="Spectre.Console" Version="0.47.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\PluginManager\PluginManager.csproj" />
|
<ProjectReference Include="..\PluginManager\PluginManager.csproj"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,32 +1,38 @@
|
|||||||
using PluginManager.Others;
|
using System;
|
||||||
using System;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace DiscordBot
|
namespace DiscordBot;
|
||||||
|
|
||||||
|
public static class Entry
|
||||||
{
|
{
|
||||||
|
|
||||||
public class Entry
|
|
||||||
{
|
|
||||||
internal static StartupArguments startupArguments;
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
AppDomain currentDomain = AppDomain.CurrentDomain;
|
#if DEBUG
|
||||||
currentDomain.AssemblyResolve += new ResolveEventHandler(LoadFromSameFolder);
|
if (args.Length == 1 && args[0] == "/purge_plugins")
|
||||||
|
{
|
||||||
|
foreach (var plugin in Directory.GetFiles("./Data/Plugins", "*.dll", SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
File.Delete(plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
var currentDomain = AppDomain.CurrentDomain;
|
||||||
|
currentDomain.AssemblyResolve += LoadFromSameFolder;
|
||||||
|
|
||||||
static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args)
|
static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args)
|
||||||
{
|
{
|
||||||
string folderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "./Libraries");
|
var folderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "./Libraries");
|
||||||
string assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll");
|
var assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll");
|
||||||
if (!File.Exists(assemblyPath)) return null;
|
if (!File.Exists(assemblyPath)) return null;
|
||||||
Assembly assembly = Assembly.LoadFrom(assemblyPath);
|
var assembly = Assembly.LoadFrom(assemblyPath);
|
||||||
|
|
||||||
return assembly;
|
return assembly;
|
||||||
}
|
}
|
||||||
|
|
||||||
Program.Startup(args);
|
Program.Startup(args);
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
28
DiscordBot/Installer.cs
Normal file
28
DiscordBot/Installer.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using PluginManager;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace DiscordBot;
|
||||||
|
|
||||||
|
public static class Installer
|
||||||
|
{
|
||||||
|
public static void GenerateStartupConfig()
|
||||||
|
{
|
||||||
|
AnsiConsole.MarkupLine("Welcome to the [bold]SethBot[/] installer !");
|
||||||
|
AnsiConsole.MarkupLine("First, we need to configure the bot. Don't worry, it will be quick !");
|
||||||
|
|
||||||
|
var token = AnsiConsole.Ask<string>("Please enter the bot [yellow]token[/]:");
|
||||||
|
var prefix = AnsiConsole.Ask<string>("Please enter the bot [yellow]prefix[/]:");
|
||||||
|
var serverId = AnsiConsole.Ask<string>("Please enter the [yellow]Server ID[/]:");
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(serverId)) serverId = "NULL";
|
||||||
|
Config.AppSettings.Add("token", token);
|
||||||
|
Config.AppSettings.Add("prefix", prefix);
|
||||||
|
Config.AppSettings.Add("ServerID", serverId);
|
||||||
|
|
||||||
|
Config.AppSettings.SaveToFile();
|
||||||
|
|
||||||
|
AnsiConsole.MarkupLine("[bold]Config saved ![/]");
|
||||||
|
|
||||||
|
Config.Logger.Log("Config Saved", source: typeof(Installer));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,51 +1,32 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using DiscordBot.Utilities;
|
||||||
using DiscordBot.Discord.Core;
|
using PluginManager.Bot;
|
||||||
|
|
||||||
using PluginManager;
|
|
||||||
using PluginManager.Database;
|
|
||||||
using PluginManager.Items;
|
|
||||||
using PluginManager.Online;
|
|
||||||
using PluginManager.Online.Helpers;
|
|
||||||
using PluginManager.Others;
|
using PluginManager.Others;
|
||||||
|
using PluginManager.Others.Actions;
|
||||||
using Terminal.Gui;
|
using Spectre.Console;
|
||||||
|
using static PluginManager.Config;
|
||||||
using OperatingSystem = PluginManager.Others.OperatingSystem;
|
|
||||||
|
|
||||||
namespace DiscordBot;
|
namespace DiscordBot;
|
||||||
|
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
private static bool loadPluginsOnStartup;
|
public static InternalActionManager internalActionManager;
|
||||||
private static ConsoleCommandsHandler consoleCommandsHandler;
|
|
||||||
//private static bool isUI_ON;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main entry point for the application.
|
/// The main entry point for the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[STAThread]
|
|
||||||
public static void Startup(string[] args)
|
public static void Startup(string[] args)
|
||||||
{
|
{
|
||||||
PreLoadComponents(args).Wait();
|
PreLoadComponents(args).Wait();
|
||||||
|
|
||||||
if (!Config.Variables.Exists("ServerID") || !Config.Variables.Exists("token") ||
|
if (!AppSettings.ContainsKey("ServerID") || !AppSettings.ContainsKey("token") || !AppSettings.ContainsKey("prefix"))
|
||||||
Config.Variables.GetValue("token") == null ||
|
Installer.GenerateStartupConfig();
|
||||||
(Config.Variables.GetValue("token")?.Length != 70 && Config.Variables.GetValue("token")?.Length != 59) ||
|
|
||||||
!Config.Variables.Exists("prefix") || Config.Variables.GetValue("prefix") == null ||
|
|
||||||
Config.Variables.GetValue("prefix")?.Length != 1 ||
|
|
||||||
(args.Length == 1 && args[0] == "/reset"))
|
|
||||||
{
|
|
||||||
GenerateStartUI("First time setup. Please fill the following with your discord bot data.\nThis are saved ONLY on YOUR computer.");
|
|
||||||
}
|
|
||||||
|
|
||||||
HandleInput(args).Wait();
|
HandleInput().Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -53,25 +34,21 @@ public class Program
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static void NoGUI()
|
private static void NoGUI()
|
||||||
{
|
{
|
||||||
#if DEBUG
|
internalActionManager.Initialize().Wait();
|
||||||
Logger.WriteLine();
|
internalActionManager.Execute("plugin", "load").Wait();
|
||||||
Logger.WriteLine("Debug mode enabled");
|
internalActionManager.Refresh().Wait();
|
||||||
Logger.WriteLine();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
if (loadPluginsOnStartup)
|
|
||||||
consoleCommandsHandler.HandleCommand("lp");
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var cmd = Console.ReadLine();
|
var cmd = Console.ReadLine();
|
||||||
if (!consoleCommandsHandler.HandleCommand(cmd!
|
var args = cmd.Split(' ');
|
||||||
#if DEBUG
|
var command = args[0];
|
||||||
, false
|
args = args.Skip(1).ToArray();
|
||||||
#endif
|
if (args.Length == 0)
|
||||||
|
args = null;
|
||||||
|
|
||||||
) && cmd.Length > 0)
|
internalActionManager.Execute(command, args).Wait(); // Execute the command
|
||||||
Logger.WriteLine("Failed to run command " + cmd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,52 +56,31 @@ public class Program
|
|||||||
/// Start the bot without user interface
|
/// Start the bot without user interface
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns the boot loader for the Discord Bot</returns>
|
/// <returns>Returns the boot loader for the Discord Bot</returns>
|
||||||
private static async Task<Boot> StartNoGui()
|
private static async Task StartNoGui()
|
||||||
{
|
{
|
||||||
Console.Clear();
|
Console.Clear();
|
||||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||||
|
|
||||||
var startupMessageList =
|
Console.WriteLine($"Running on version: {Assembly.GetExecutingAssembly().GetName().Version}");
|
||||||
await ServerCom.ReadTextFromURL(
|
Console.WriteLine("Git SethBot: https://github.com/andreitdr/SethDiscordBot");
|
||||||
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/StartupMessage");
|
Console.WriteLine("Git Plugins: https://github.com/andreitdr/SethPlugins");
|
||||||
|
|
||||||
foreach (var message in startupMessageList)
|
ConsoleUtilities.WriteColorText("&rRemember to close the bot using the ShutDown command (&yexit&r) or some settings won't be saved");
|
||||||
Logger.WriteLine(message);
|
|
||||||
|
|
||||||
Logger.WriteLine(
|
ConsoleUtilities.WriteColorText($"Running on &m{Functions.GetOperatingSystem()}");
|
||||||
$"Running on version: {Assembly.GetExecutingAssembly().GetName().Version}");
|
Console.WriteLine("============================ LOG ============================");
|
||||||
Logger.WriteLine($"Git URL: {Settings.Variables.WebsiteURL}");
|
|
||||||
|
|
||||||
Utilities.WriteColorText(
|
|
||||||
"&rRemember to close the bot using the ShutDown command (&ysd&r) or some settings won't be saved\n");
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
|
|
||||||
if (Config.Variables.Exists("LaunchMessage"))
|
|
||||||
Utilities.WriteColorText(Config.Variables.GetValue("LaunchMessage"));
|
|
||||||
|
|
||||||
|
|
||||||
Utilities.WriteColorText(
|
|
||||||
"Please note that the bot saves a backup save file every time you are using the shudown command (&ysd&c)");
|
|
||||||
Logger.WriteLine("============================ LOG ============================");
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string token = "";
|
var token = AppSettings["token"];
|
||||||
#if DEBUG
|
var prefix = AppSettings["prefix"];
|
||||||
if (File.Exists("./Data/Resources/token.txt")) token = File.ReadAllText("./Data/Resources/token.txt");
|
|
||||||
else token = Config.Variables.GetValue("token");
|
|
||||||
#else
|
|
||||||
token = Config.Variables.GetValue("token");
|
|
||||||
#endif
|
|
||||||
var prefix = Config.Variables.GetValue("prefix");
|
|
||||||
var discordbooter = new Boot(token, prefix);
|
var discordbooter = new Boot(token, prefix);
|
||||||
await discordbooter.Awake();
|
await discordbooter.Awake();
|
||||||
return discordbooter;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch ( Exception ex )
|
||||||
{
|
{
|
||||||
Logger.LogError(ex);
|
Logger.Log(ex.ToString(), source: typeof(Program), type: LogType.CRITICAL);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,369 +88,55 @@ public class Program
|
|||||||
/// Handle user input arguments from the startup of the application
|
/// Handle user input arguments from the startup of the application
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">The arguments</param>
|
/// <param name="args">The arguments</param>
|
||||||
private static async Task HandleInput(string[] args)
|
private static async Task HandleInput()
|
||||||
{
|
|
||||||
var len = args.Length;
|
|
||||||
|
|
||||||
var b = await StartNoGui();
|
|
||||||
consoleCommandsHandler = new ConsoleCommandsHandler(b.client);
|
|
||||||
|
|
||||||
if (Entry.startupArguments.loadPluginsAtStartup) { loadPluginsOnStartup = true; }
|
|
||||||
|
|
||||||
if (len > 0 && args[0] == "/remplug")
|
|
||||||
{
|
|
||||||
var plugName = string.Join(' ', args, 1, args.Length - 1);
|
|
||||||
Logger.WriteLine("Starting to remove " + plugName);
|
|
||||||
await ConsoleCommandsHandler.ExecuteCommad("remplug " + plugName);
|
|
||||||
loadPluginsOnStartup = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var mainThread = new Thread(() =>
|
|
||||||
{
|
{
|
||||||
|
await StartNoGui();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
internalActionManager = new InternalActionManager("./Data/Plugins", "*.dll");
|
||||||
NoGUI();
|
NoGUI();
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch ( IOException ex )
|
||||||
{
|
{
|
||||||
if (ex.Message == "No process is on the other end of the pipe." || (uint)ex.HResult == 0x800700E9)
|
if (ex.Message == "No process is on the other end of the pipe." || (uint)ex.HResult == 0x800700E9)
|
||||||
{
|
{
|
||||||
if (Config.Variables.Exists("LaunchMessage"))
|
if (AppSettings.ContainsKey("LaunchMessage"))
|
||||||
Config.Variables.Add("LaunchMessage",
|
AppSettings.Add("LaunchMessage",
|
||||||
"An error occured while closing the bot last time. Please consider closing the bot using the &rsd&c method !\nThere is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !",
|
"An error occured while closing the bot last time. Please consider closing the bot using the &rexit&c method !\n" +
|
||||||
false);
|
"There is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !");
|
||||||
Logger.WriteErrFile(ex.ToString());
|
|
||||||
|
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 !",
|
||||||
|
source: typeof(Program), type: LogType.ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
mainThread.Start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task PreLoadComponents(string[] args)
|
private static async Task PreLoadComponents(string[] args)
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory("./Data/Resources");
|
await Initialize();
|
||||||
Directory.CreateDirectory("./Data/Plugins");
|
|
||||||
Directory.CreateDirectory("./Data/PAKS");
|
|
||||||
|
|
||||||
if (!File.Exists(Functions.dataFolder + "loader.json"))
|
Logger.OnLog += (sender, logMessage) =>
|
||||||
{
|
{
|
||||||
Entry.startupArguments = new StartupArguments();
|
string messageColor = logMessage.Type switch
|
||||||
await Functions.SaveToJsonFile(Functions.dataFolder + "loader.json", Entry.startupArguments);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Entry.startupArguments = await Functions.ConvertFromJson<StartupArguments>(Functions.dataFolder + "loader.json");
|
|
||||||
|
|
||||||
|
|
||||||
Settings.sqlDatabase = new SqlDatabase("SetDB.dat");
|
|
||||||
|
|
||||||
await Settings.sqlDatabase.Open();
|
|
||||||
await Config.Initialize();
|
|
||||||
Logger.Initialize(true);
|
|
||||||
ArchiveManager.Initialize();
|
|
||||||
|
|
||||||
|
|
||||||
Logger.LogEvent += (message) => { Console.Write(message); };
|
|
||||||
|
|
||||||
Logger.WriteLine("Loading resources ...");
|
|
||||||
var main = new Utilities.ProgressBar(ProgressBarType.NO_END);
|
|
||||||
main.Start();
|
|
||||||
|
|
||||||
if (await Config.Variables.ExistsAsync("DeleteLogsAtStartup"))
|
|
||||||
if (await Config.Variables.GetValueAsync("DeleteLogsAtStartup") == "true")
|
|
||||||
foreach (var file in Directory.GetFiles("./Output/Logs/"))
|
|
||||||
File.Delete(file);
|
|
||||||
var OnlineDefaultKeys =
|
|
||||||
await ServerCom.ReadTextFromURL(
|
|
||||||
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/SetupKeys");
|
|
||||||
|
|
||||||
|
|
||||||
if (!await Config.Variables.ExistsAsync("Version"))
|
|
||||||
await Config.Variables.AddAsync("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString(),
|
|
||||||
false);
|
|
||||||
else
|
|
||||||
await Config.Variables.SetValueAsync(
|
|
||||||
"Version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var key in OnlineDefaultKeys)
|
|
||||||
{
|
{
|
||||||
if (key.Length <= 3 || !key.Contains(' ')) continue;
|
LogType.INFO => "[green]",
|
||||||
var s = key.Split(' ');
|
LogType.WARNING => "[yellow]",
|
||||||
try
|
LogType.ERROR => "[red]",
|
||||||
{
|
LogType.CRITICAL => "[red]",
|
||||||
if (await Config.Variables.ExistsAsync(s[0])) await Config.Variables.SetValueAsync(s[0], s[1]);
|
_ => "[white]"
|
||||||
else
|
|
||||||
await Config.Variables.AddAsync(s[0], s[1], s[2].ToLower() == "true");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.WriteErrFile(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var onlineSettingsList =
|
|
||||||
await ServerCom.ReadTextFromURL(
|
|
||||||
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/OnlineData");
|
|
||||||
main.Stop("Loaded online settings. Loading updates ...");
|
|
||||||
foreach (var key in onlineSettingsList)
|
|
||||||
{
|
|
||||||
if (key.Length <= 3 || !key.Contains(' ')) continue;
|
|
||||||
|
|
||||||
var s = key.Split(' ');
|
|
||||||
switch (s[0])
|
|
||||||
{
|
|
||||||
case "CurrentVersion":
|
|
||||||
var newVersion = s[1];
|
|
||||||
if (!newVersion.Equals(await Config.Variables.GetValueAsync("Version")))
|
|
||||||
{
|
|
||||||
var nVer = new VersionString(newVersion.Substring(2));
|
|
||||||
var cVer = new VersionString((await Config.Variables.GetValueAsync("Version")).Substring(2));
|
|
||||||
if (cVer > nVer)
|
|
||||||
{
|
|
||||||
await Config.Variables.SetValueAsync("Version", "1." + cVer.ToShortString() + " (Beta)");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.Clear();
|
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
|
||||||
Logger.WriteLine("A new version of the bot is available !");
|
|
||||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
|
||||||
Logger.WriteLine("Current version : " +
|
|
||||||
Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
|
||||||
Logger.WriteLine("New version : " + newVersion);
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
|
||||||
|
|
||||||
Logger.WriteLine("Changelog :");
|
|
||||||
|
|
||||||
List<string> changeLog = await ServerCom.ReadTextFromURL(
|
|
||||||
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/VersionData/DiscordBot");
|
|
||||||
foreach (var item in changeLog)
|
|
||||||
Utilities.WriteColorText(item);
|
|
||||||
Logger.WriteLine("Do you want to update the bot ? (y/n)");
|
|
||||||
if (Console.ReadKey().Key == ConsoleKey.Y)
|
|
||||||
{
|
|
||||||
if (Functions.GetOperatingSystem() == OperatingSystem.WINDOWS)
|
|
||||||
{
|
|
||||||
var url =
|
|
||||||
$"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0.zip";
|
|
||||||
Process.Start($"{Functions.dataFolder}Applications/Updater.exe",
|
|
||||||
$"{newVersion} {url} {Process.GetCurrentProcess().ProcessName}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var url =
|
|
||||||
$"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0_linux.zip";
|
|
||||||
if (Logger.isConsole)
|
|
||||||
Console.SetCursorPosition(0, Console.CursorTop);
|
|
||||||
Logger.WriteLine($"executing: download_file {url}");
|
|
||||||
|
|
||||||
await ServerCom.DownloadFileAsync(url, "./update.zip", new Progress<float>(percent => { Logger.Write($"\rProgress: {percent}% "); }));
|
|
||||||
await File.WriteAllTextAsync("Install.sh",
|
|
||||||
"#!/bin/bash\nunzip -qq -o update.zip \nrm update.zip\nchmod a+x DiscordBot");
|
|
||||||
Logger.WriteLine();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Logger.WriteLine("executing: chmod a+x Install.sh");
|
|
||||||
Process.Start("chmod", "a+x Install.sh").WaitForExit();
|
|
||||||
Process.Start("Install.sh").WaitForExit();
|
|
||||||
|
|
||||||
Logger.WriteLine("executing: rm Install.sh");
|
|
||||||
Process.Start("rm", "Install.sh").WaitForExit();
|
|
||||||
|
|
||||||
Logger.WriteLine("The new version of the bot has been installed.");
|
|
||||||
Logger.WriteLine("Please restart the bot.");
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.WriteErrFile(ex.Message);
|
|
||||||
if (ex.Message.Contains("Access de"))
|
|
||||||
Logger.WriteLine("Please run the bot as root.");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Process.Start(Functions.dataFolder + "Applications/Updater", $"{url}");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case "UpdaterVersion":
|
|
||||||
var updaternewversion = s[1];
|
|
||||||
if (Functions.GetOperatingSystem() == OperatingSystem.LINUX)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!await Config.Variables.ExistsAsync("UpdaterVersion"))
|
|
||||||
await Config.Variables.AddAsync("UpdaterVersion", "0.0.0.0", false);
|
|
||||||
if (await Config.Variables.GetValueAsync("UpdaterVersion") != updaternewversion ||
|
|
||||||
!File.Exists(Functions.dataFolder+"Applications/Updater.exe"))
|
|
||||||
{
|
|
||||||
Console.Clear();
|
|
||||||
Logger.WriteLine("Installing updater ...\nDo NOT close the bot during update !");
|
|
||||||
var bar = new Utilities.ProgressBar(ProgressBarType.NO_END);
|
|
||||||
bar.Start();
|
|
||||||
await ServerCom.DownloadFileNoProgressAsync(
|
|
||||||
"https://github.com/Wizzy69/installer/releases/download/release-1-discordbot/Updater.exe",
|
|
||||||
$"{Functions.dataFolder}Applications/Updater.exe");
|
|
||||||
//await ArchiveManager.ExtractArchive("./Updater.zip", "./", null,
|
|
||||||
// UnzipProgressType.PercentageFromTotalSize);
|
|
||||||
await Config.Variables.SetValueAsync("UpdaterVersion", updaternewversion);
|
|
||||||
// File.Delete("Updater.zip");
|
|
||||||
bar.Stop("Updater has been updated !");
|
|
||||||
Console.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void GenerateStartUI(string titleMessage)
|
|
||||||
{
|
|
||||||
Application.Init();
|
|
||||||
var top = Application.Top;
|
|
||||||
var win = new Window("Discord Bot Config - " + Assembly.GetExecutingAssembly().GetName().Version)
|
|
||||||
{
|
|
||||||
X = 0,
|
|
||||||
Y = 1,
|
|
||||||
Width = Dim.Fill(),
|
|
||||||
Height = Dim.Fill()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
top.Add(win);
|
if (logMessage.Message.Contains('['))
|
||||||
|
|
||||||
var labelInfo = new Label(titleMessage)
|
|
||||||
{
|
{
|
||||||
X = Pos.Center(),
|
// If the message contains a tag, just print it as it is. No need to format it
|
||||||
Y = 2
|
Console.WriteLine(logMessage.Message);
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
var labelToken = new Label("Please insert your token here: ")
|
|
||||||
{
|
|
||||||
X = 5,
|
|
||||||
Y = 5
|
|
||||||
};
|
|
||||||
|
|
||||||
var textFiledToken = new TextField(Config.Variables.GetValue("token") ?? "")
|
|
||||||
{
|
|
||||||
X = Pos.Left(labelToken) + labelToken.Text.Length + 2,
|
|
||||||
Y = labelToken.Y,
|
|
||||||
Width = 70
|
|
||||||
};
|
|
||||||
|
|
||||||
var labelPrefix = new Label("Please insert your prefix here: ")
|
|
||||||
{
|
|
||||||
X = 5,
|
|
||||||
Y = 8
|
|
||||||
};
|
|
||||||
var textFiledPrefix = new TextField(Config.Variables.GetValue("prefix") ?? "")
|
|
||||||
{
|
|
||||||
X = Pos.Left(labelPrefix) + labelPrefix.Text.Length + 2,
|
|
||||||
Y = labelPrefix.Y,
|
|
||||||
Width = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
var labelServerid = new Label("Please insert your server id here (optional): ")
|
|
||||||
{
|
|
||||||
X = 5,
|
|
||||||
Y = 11
|
|
||||||
};
|
|
||||||
var textFiledServerID = new TextField(Config.Variables.GetValue("ServerID") ?? "")
|
|
||||||
{
|
|
||||||
X = Pos.Left(labelServerid) + labelServerid.Text.Length + 2,
|
|
||||||
Y = labelServerid.Y,
|
|
||||||
Width = 18
|
|
||||||
};
|
|
||||||
|
|
||||||
var button = new Button("Submit")
|
|
||||||
{
|
|
||||||
X = Pos.Center() - 10,
|
|
||||||
Y = 16
|
|
||||||
};
|
|
||||||
|
|
||||||
var button2 = new Button("License")
|
|
||||||
{
|
|
||||||
X = Pos.Center() + 10,
|
|
||||||
Y = 16
|
|
||||||
};
|
|
||||||
|
|
||||||
var button3 = new Button("ⓘ")
|
|
||||||
{
|
|
||||||
X = Pos.Left(textFiledServerID) + 20,
|
|
||||||
Y = textFiledServerID.Y
|
|
||||||
};
|
|
||||||
|
|
||||||
Console.CancelKeyPress += (sender, e) => { top.Running = false; };
|
|
||||||
|
|
||||||
button.Clicked += () =>
|
|
||||||
{
|
|
||||||
var passMessage = "";
|
|
||||||
if (textFiledToken.Text.Length != 70 && textFiledToken.Text.Length != 59)
|
|
||||||
passMessage += "Invalid token, ";
|
|
||||||
if (textFiledPrefix.Text.ContainsAny("0123456789/\\ ") || textFiledPrefix.Text.Length != 1)
|
|
||||||
passMessage += "Invalid prefix, ";
|
|
||||||
if (textFiledServerID.Text.Length != 18 && textFiledServerID.Text.Length > 0)
|
|
||||||
passMessage += "Invalid serverID";
|
|
||||||
|
|
||||||
if (passMessage != "")
|
|
||||||
{
|
|
||||||
MessageBox.ErrorQuery("Discord Bot Settings",
|
|
||||||
"Failed to pass check. Invalid information given:\n" + passMessage, "Retry");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnsiConsole.MarkupLine($"{messageColor}{logMessage.ThrowTime} {logMessage.Message} [/]");
|
||||||
Config.Variables.Add("ServerID", (string)textFiledServerID.Text, true);
|
|
||||||
Config.Variables.Add("token", (string)textFiledToken.Text, true);
|
|
||||||
Config.Variables.Add("prefix", (string)textFiledPrefix.Text, true);
|
|
||||||
|
|
||||||
MessageBox.Query("Discord Bot Settings", "Successfully saved config !\nJust start the bot :D",
|
|
||||||
"Start :D");
|
|
||||||
top.Running = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
button2.Clicked += async () =>
|
AppSettings["Version"] = Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||||
{
|
|
||||||
var license =
|
|
||||||
await ServerCom.ReadTextFromURL(
|
|
||||||
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/LICENSE.txt");
|
|
||||||
var ProductLicense =
|
|
||||||
"Seth Discord Bot\n\nDeveloped by Wizzy#9181\nThis application can be used and modified by anyone. Plugin development for this application is also free and supported";
|
|
||||||
var r = MessageBox.Query("Discord Bot Settings", ProductLicense, "Close", "Read about libraries used");
|
|
||||||
if (r == 1)
|
|
||||||
{
|
|
||||||
var i = 0;
|
|
||||||
while (i < license.Count)
|
|
||||||
{
|
|
||||||
var print_message = license[i++] + "\n";
|
|
||||||
for (; i < license.Count && !license[i].StartsWith("-----------"); i++)
|
|
||||||
print_message += license[i] + "\n";
|
|
||||||
if (print_message.Contains("https://"))
|
|
||||||
print_message += "\n\nCTRL + Click on a link to open it";
|
|
||||||
if (MessageBox.Query("Licenses", print_message, "Next", "Quit") == 1) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
button3.Clicked += () =>
|
|
||||||
{
|
|
||||||
MessageBox.Query("Discord Bot Settings",
|
|
||||||
"Server ID can be found in Server settings => Widget => Server ID",
|
|
||||||
"Close");
|
|
||||||
};
|
|
||||||
|
|
||||||
win.Add(labelInfo, labelPrefix, labelServerid, labelToken);
|
|
||||||
win.Add(textFiledToken, textFiledPrefix, textFiledServerID, button3);
|
|
||||||
win.Add(button, button2);
|
|
||||||
Application.Run();
|
|
||||||
Application.Shutdown();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace DiscordBot
|
|
||||||
{
|
|
||||||
internal class StartupArguments
|
|
||||||
{
|
|
||||||
public string runArgs { get; } = "";
|
|
||||||
public bool loadPluginsAtStartup { get; } = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
342
DiscordBot/Utilities/Console Utilities.cs
Normal file
342
DiscordBot/Utilities/Console Utilities.cs
Normal file
@@ -0,0 +1,342 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace DiscordBot.Utilities;
|
||||||
|
|
||||||
|
public class TableData
|
||||||
|
{
|
||||||
|
public List<string> Columns;
|
||||||
|
public List<string[]> Rows;
|
||||||
|
|
||||||
|
public bool IsEmpty => Rows.Count == 0;
|
||||||
|
public bool HasRoundBorders { get; set; } = true;
|
||||||
|
|
||||||
|
public TableData(List<string> columns)
|
||||||
|
{
|
||||||
|
Columns = columns;
|
||||||
|
Rows = new List<string[]>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TableData(string[] columns)
|
||||||
|
{
|
||||||
|
Columns = columns.ToList();
|
||||||
|
Rows = new List<string[]>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRow(string[] row)
|
||||||
|
{
|
||||||
|
Rows.Add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConsoleUtilities
|
||||||
|
{
|
||||||
|
|
||||||
|
public static async Task<T> ExecuteWithProgressBar<T>(Task<T> function, string message)
|
||||||
|
{
|
||||||
|
T result = default;
|
||||||
|
await AnsiConsole.Progress()
|
||||||
|
.Columns(
|
||||||
|
new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(),
|
||||||
|
new ProgressBarColumn(),
|
||||||
|
new PercentageColumn(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.StartAsync(
|
||||||
|
async ctx =>
|
||||||
|
{
|
||||||
|
var task = ctx.AddTask(message);
|
||||||
|
task.IsIndeterminate = true;
|
||||||
|
result = await function;
|
||||||
|
task.Increment(100);
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task ExecuteWithProgressBar(Task function, string message)
|
||||||
|
{
|
||||||
|
await AnsiConsole.Progress()
|
||||||
|
.Columns(new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(),
|
||||||
|
new ProgressBarColumn(),
|
||||||
|
new PercentageColumn(),
|
||||||
|
})
|
||||||
|
.StartAsync(async ctx =>
|
||||||
|
{
|
||||||
|
var task = ctx.AddTask(message);
|
||||||
|
task.IsIndeterminate = true;
|
||||||
|
await function;
|
||||||
|
task.Increment(100);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Dictionary<char, ConsoleColor> Colors = new()
|
||||||
|
{
|
||||||
|
{ 'g', ConsoleColor.Green },
|
||||||
|
{ 'b', ConsoleColor.Blue },
|
||||||
|
{ 'r', ConsoleColor.Red },
|
||||||
|
{ 'm', ConsoleColor.Magenta },
|
||||||
|
{ 'y', ConsoleColor.Yellow }
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly char ColorPrefix = '&';
|
||||||
|
|
||||||
|
private static bool CanAproximateTo(this float f, float y)
|
||||||
|
{
|
||||||
|
return MathF.Abs(f - y) < 0.000001;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PrintAsTable(this TableData tableData)
|
||||||
|
{
|
||||||
|
var table = new Table();
|
||||||
|
table.Border(tableData.HasRoundBorders ? TableBorder.Rounded : TableBorder.Square);
|
||||||
|
table.AddColumns(tableData.Columns.ToArray());
|
||||||
|
foreach (var row in tableData.Rows)
|
||||||
|
table.AddRow(row);
|
||||||
|
|
||||||
|
AnsiConsole.Write(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A way to create a table based on input data
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">The List of arrays of string that represent the rows.</param>
|
||||||
|
public static void FormatAndAlignTable(List<string[]> data, TableFormat format)
|
||||||
|
{
|
||||||
|
if (format == TableFormat.SPECTRE_CONSOLE)
|
||||||
|
{
|
||||||
|
var table = new Table();
|
||||||
|
table.Border(TableBorder.Rounded);
|
||||||
|
table.AddColumns(data[0]);
|
||||||
|
data.RemoveAt(0);
|
||||||
|
foreach (var row in data)
|
||||||
|
table.AddRow(row);
|
||||||
|
|
||||||
|
AnsiConsole.Write(table);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format == TableFormat.CENTER_EACH_COLUMN_BASED)
|
||||||
|
{
|
||||||
|
var tableLine = '-';
|
||||||
|
var tableCross = '+';
|
||||||
|
var tableWall = '|';
|
||||||
|
|
||||||
|
var len = new int[data[0].Length];
|
||||||
|
foreach (var line in data)
|
||||||
|
for (var i = 0; i < line.Length; i++)
|
||||||
|
if (line[i].Length > len[i])
|
||||||
|
len[i] = line[i].Length;
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var row in data)
|
||||||
|
{
|
||||||
|
if (row[0][0] == tableLine)
|
||||||
|
Console.Write(tableCross);
|
||||||
|
else
|
||||||
|
Console.Write(tableWall);
|
||||||
|
for (var l = 0; l < row.Length; l++)
|
||||||
|
{
|
||||||
|
if (row[l][0] == tableLine)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < len[l] + 4; ++i)
|
||||||
|
Console.Write(tableLine);
|
||||||
|
}
|
||||||
|
else if (row[l].Length == len[l])
|
||||||
|
{
|
||||||
|
Console.Write(" ");
|
||||||
|
Console.Write(row[l]);
|
||||||
|
Console.Write(" ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var lenHalf = row[l].Length / 2;
|
||||||
|
for (var i = 0; i < (len[l] + 4) / 2 - lenHalf; ++i)
|
||||||
|
Console.Write(" ");
|
||||||
|
Console.Write(row[l]);
|
||||||
|
for (var i = (len[l] + 4) / 2 + lenHalf + 1; i < len[l] + 4; ++i)
|
||||||
|
Console.Write(" ");
|
||||||
|
if (row[l].Length % 2 == 0)
|
||||||
|
Console.Write(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.Write(row[l][0] == tableLine ? tableCross : tableWall);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(); //end line
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format == TableFormat.CENTER_OVERALL_LENGTH)
|
||||||
|
{
|
||||||
|
var maxLen = 0;
|
||||||
|
foreach (var row in data)
|
||||||
|
foreach (var s in row)
|
||||||
|
if (s.Length > maxLen)
|
||||||
|
maxLen = s.Length;
|
||||||
|
|
||||||
|
var div = (maxLen + 4) / 2;
|
||||||
|
|
||||||
|
foreach (var row in data)
|
||||||
|
{
|
||||||
|
Console.Write("\t");
|
||||||
|
if (row[0] == "-")
|
||||||
|
Console.Write("+");
|
||||||
|
else
|
||||||
|
Console.Write("|");
|
||||||
|
|
||||||
|
foreach (var s in row)
|
||||||
|
{
|
||||||
|
if (s == "-")
|
||||||
|
{
|
||||||
|
for (var i = 0; i < maxLen + 4; ++i)
|
||||||
|
Console.Write("-");
|
||||||
|
}
|
||||||
|
else if (s.Length == maxLen)
|
||||||
|
{
|
||||||
|
Console.Write(" ");
|
||||||
|
Console.Write(s);
|
||||||
|
Console.Write(" ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var lenHalf = s.Length / 2;
|
||||||
|
for (var i = 0; i < div - lenHalf; ++i)
|
||||||
|
Console.Write(" ");
|
||||||
|
Console.Write(s);
|
||||||
|
for (var i = div + lenHalf + 1; i < maxLen + 4; ++i)
|
||||||
|
Console.Write(" ");
|
||||||
|
if (s.Length % 2 == 0)
|
||||||
|
Console.Write(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s == "-")
|
||||||
|
Console.Write("+");
|
||||||
|
else
|
||||||
|
Console.Write("|");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(); //end line
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format == TableFormat.DEFAULT)
|
||||||
|
{
|
||||||
|
var widths = new int[data[0].Length];
|
||||||
|
var space_between_columns = 3;
|
||||||
|
for (var i = 0; i < data.Count; i++)
|
||||||
|
for (var j = 0; j < data[i].Length; j++)
|
||||||
|
if (data[i][j].Length > widths[j])
|
||||||
|
widths[j] = data[i][j].Length;
|
||||||
|
|
||||||
|
for (var i = 0; i < data.Count; i++)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < data[i].Length; j++)
|
||||||
|
{
|
||||||
|
if (data[i][j] == "-")
|
||||||
|
data[i][j] = " ";
|
||||||
|
Console.Write(data[i][j]);
|
||||||
|
for (var k = 0; k < widths[j] - data[i][j].Length + 1 + space_between_columns; k++)
|
||||||
|
Console.Write(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("Unknown type of table");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void WriteColorText(string text, bool appendNewLineAtEnd = true)
|
||||||
|
{
|
||||||
|
var initialForeGround = Console.ForegroundColor;
|
||||||
|
var input = text.ToCharArray();
|
||||||
|
for (var i = 0; i < input.Length; i++)
|
||||||
|
if (input[i] == ColorPrefix)
|
||||||
|
{
|
||||||
|
if (i + 1 < input.Length)
|
||||||
|
{
|
||||||
|
if (Colors.ContainsKey(input[i + 1]))
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = Colors[input[i + 1]];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if (input[i + 1] == 'c')
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = initialForeGround;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.Write(input[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.ForegroundColor = initialForeGround;
|
||||||
|
if (appendNewLineAtEnd)
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class Spinner
|
||||||
|
{
|
||||||
|
private readonly string[] Sequence;
|
||||||
|
private bool isRunning;
|
||||||
|
public string Message;
|
||||||
|
private int position;
|
||||||
|
private Thread thread;
|
||||||
|
|
||||||
|
public Spinner()
|
||||||
|
{
|
||||||
|
Sequence = new[] { "|", "/", "-", "\\" };
|
||||||
|
position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
Console.CursorVisible = false;
|
||||||
|
isRunning = true;
|
||||||
|
thread = new Thread(() =>
|
||||||
|
{
|
||||||
|
while (isRunning)
|
||||||
|
{
|
||||||
|
Console.SetCursorPosition(0, Console.CursorTop);
|
||||||
|
Console.Write(" " + Sequence[position] + " " + Message + " ");
|
||||||
|
position++;
|
||||||
|
if (position >= Sequence.Length)
|
||||||
|
position = 0;
|
||||||
|
Thread.Sleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
thread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
isRunning = false;
|
||||||
|
Console.CursorVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
DiscordBot/Utilities/Enums.cs
Normal file
9
DiscordBot/Utilities/Enums.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace DiscordBot.Utilities;
|
||||||
|
|
||||||
|
public enum TableFormat
|
||||||
|
{
|
||||||
|
SPECTRE_CONSOLE,
|
||||||
|
CENTER_EACH_COLUMN_BASED,
|
||||||
|
CENTER_OVERALL_LENGTH,
|
||||||
|
DEFAULT
|
||||||
|
}
|
||||||
35
DiscordBot/builder.bat
Normal file
35
DiscordBot/builder.bat
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
@echo off
|
||||||
|
echo "Building..."
|
||||||
|
|
||||||
|
echo "Building linux-x64 not self-contained"
|
||||||
|
dotnet publish -r linux-x64 -p:PublishSingleFile=false --self-contained true -c Release -o ../publish/linux-x64
|
||||||
|
|
||||||
|
echo "Building win-x64 not self-contained"
|
||||||
|
dotnet publish -r win-x64 -p:PublishSingleFile=false --self-contained true -c Release -o ../publish/win-x64
|
||||||
|
|
||||||
|
echo "Building osx-x64 not self-contained"
|
||||||
|
dotnet publish -r osx-x64 -p:PublishSingleFile=false --self-contained true -c Release -o ../publish/osx-x64
|
||||||
|
|
||||||
|
|
||||||
|
echo "Building linux-x64 self-contained"
|
||||||
|
dotnet publish -r linux-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ../publish/linux-x64-selfcontained
|
||||||
|
|
||||||
|
echo "Building win-x64 self-contained"
|
||||||
|
dotnet publish -r win-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ../publish/win-x64-selfcontained
|
||||||
|
|
||||||
|
echo "Building osx-x64 self-contained"
|
||||||
|
dotnet publish -r osx-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ../publish/osx-x64-selfcontained
|
||||||
|
|
||||||
|
echo "Zipping..."
|
||||||
|
mkdir ../publish/zip
|
||||||
|
|
||||||
|
|
||||||
|
zip -r ../publish/zip/linux-x64.zip ../publish/linux-x64
|
||||||
|
zip -r ../publish/zip/win-x64.zip ../publish/win-x64
|
||||||
|
zip -r ../publish/zip/osx-x64.zip ../publish/osx-x64
|
||||||
|
|
||||||
|
zip -r ../publish/zip/linux-x64-selfcontained.zip ../publish/linux-x64-selfcontained
|
||||||
|
zip -r ../publish/zip/win-x64-selfcontained.zip ../publish/win-x64-selfcontained
|
||||||
|
zip -r ../publish/zip/osx-x64-selfcontained.zip ../publish/osx-x64-selfcontained
|
||||||
|
|
||||||
|
echo "Done!"
|
||||||
36
DiscordBot/builder.sh
Normal file
36
DiscordBot/builder.sh
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# All files in this directory will be copied to the root of the container
|
||||||
|
|
||||||
|
echo "Building..."
|
||||||
|
|
||||||
|
echo "Building linux-x64 not self-contained"
|
||||||
|
dotnet publish -r linux-x64 -p:PublishSingleFile=false --self-contained true -c Release -o ./publish/linux-x64
|
||||||
|
|
||||||
|
echo "Building win-x64 not self-contained"
|
||||||
|
dotnet publish -r win-x64 -p:PublishSingleFile=false --self-contained true -c Release -o ./publish/win-x64
|
||||||
|
|
||||||
|
echo "Building osx-x64 not self-contained"
|
||||||
|
dotnet publish -r osx-x64 -p:PublishSingleFile=false --self-contained true -c Release -o ./publish/osx-x64
|
||||||
|
|
||||||
|
#One file per platform
|
||||||
|
echo "Building linux-x64 self-contained"
|
||||||
|
dotnet publish -r linux-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./publish/linux-x64-selfcontained
|
||||||
|
|
||||||
|
echo "Building win-x64 self-contained"
|
||||||
|
dotnet publish -r win-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./publish/win-x64-selfcontained
|
||||||
|
|
||||||
|
echo "Building osx-x64 self-contained"
|
||||||
|
dotnet publish -r osx-x64 -p:PublishSingleFile=true --self-contained true -c Release -o ./publish/osx-x64-selfcontained
|
||||||
|
|
||||||
|
echo "Zipping..."
|
||||||
|
mkdir ./publish/zip
|
||||||
|
|
||||||
|
|
||||||
|
zip -r ./publish/zip/linux-x64.zip ./publish/linux-x64
|
||||||
|
zip -r ./publish/zip/win-x64.zip ./publish/win-x64
|
||||||
|
zip -r ./publish/zip/osx-x64.zip ./publish/osx-x64
|
||||||
|
|
||||||
|
zip -r ./publish/zip/linux-x64-selfcontained.zip ./publish/linux-x64-selfcontained
|
||||||
|
zip -r ./publish/zip/win-x64-selfcontained.zip ./publish/win-x64-selfcontained
|
||||||
|
zip -r ./publish/zip/osx-x64-selfcontained.zip ./publish/osx-x64-selfcontained
|
||||||
|
|
||||||
|
echo "Done!"
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using PluginManager.Others;
|
||||||
|
|
||||||
using PluginManager;
|
namespace PluginManager.Bot;
|
||||||
|
|
||||||
namespace DiscordBot.Discord.Core;
|
public class Boot
|
||||||
|
|
||||||
internal class Boot
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The bot prefix
|
/// The bot prefix
|
||||||
@@ -51,23 +49,26 @@ internal class Boot
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the bot is ready
|
/// Checks if the bot is ready
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value> true if the bot is ready, othwerwise false </value>
|
/// <value> true if the bot is ready, otherwise false </value>
|
||||||
public bool isReady { get; private set; }
|
public bool isReady { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The start method for the bot. This method is used to load the bot
|
/// The start method for the bot. This method is used to load the bot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="config">
|
||||||
|
/// The discord socket config. If null then the default one will be applied (AlwaysDownloadUsers=true,
|
||||||
|
/// UseInteractionSnowflakeDate=false, GatewayIntents=GatewayIntents.All)
|
||||||
|
/// </param>
|
||||||
/// <returns>Task</returns>
|
/// <returns>Task</returns>
|
||||||
public async Task Awake()
|
public async Task Awake(DiscordSocketConfig? config = null)
|
||||||
{
|
{
|
||||||
var config = new DiscordSocketConfig
|
if (config is null)
|
||||||
|
config = new DiscordSocketConfig
|
||||||
{
|
{
|
||||||
|
|
||||||
AlwaysDownloadUsers = true,
|
AlwaysDownloadUsers = true,
|
||||||
|
|
||||||
//Disable system clock checkup (for responses at slash commands)
|
//Disable system clock checkup (for responses at slash commands)
|
||||||
UseInteractionSnowflakeDate = false,
|
UseInteractionSnowflakeDate = false,
|
||||||
|
|
||||||
GatewayIntents = GatewayIntents.All
|
GatewayIntents = GatewayIntents.All
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -84,9 +85,8 @@ internal class Boot
|
|||||||
|
|
||||||
await commandServiceHandler.InstallCommandsAsync();
|
await commandServiceHandler.InstallCommandsAsync();
|
||||||
|
|
||||||
|
Config._DiscordBotClient = this;
|
||||||
|
|
||||||
|
|
||||||
await Task.Delay(2000);
|
|
||||||
while (!isReady) ;
|
while (!isReady) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,37 +100,33 @@ internal class Boot
|
|||||||
client.Disconnected += Client_Disconnected;
|
client.Disconnected += Client_Disconnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task Client_Disconnected(Exception arg)
|
private async Task Client_Disconnected(Exception arg)
|
||||||
{
|
{
|
||||||
if (arg.Message.Contains("401"))
|
if (arg.Message.Contains("401"))
|
||||||
{
|
{
|
||||||
Config.Variables.RemoveKey("token");
|
Config.AppSettings.Remove("token");
|
||||||
Program.GenerateStartUI("The token is invalid");
|
Config.Logger.Log("The token is invalid. Please restart the bot and enter a valid token.", source:typeof(Boot), type: LogType.CRITICAL);
|
||||||
|
await Config.AppSettings.SaveToFile();
|
||||||
|
await Task.Delay(4000);
|
||||||
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.WriteErrFile(arg);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Client_LoggedOut()
|
private async Task Client_LoggedOut()
|
||||||
{
|
{
|
||||||
Logger.WriteLine("Successfully Logged Out");
|
Config.Logger.Log("Successfully Logged Out", source: typeof(Boot));
|
||||||
await Log(new LogMessage(LogSeverity.Info, "Boot", "Successfully logged out from discord !"));
|
await Log(new LogMessage(LogSeverity.Info, "Boot", "Successfully logged out from discord !"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task Ready()
|
private Task Ready()
|
||||||
{
|
{
|
||||||
Console.Title = "ONLINE";
|
|
||||||
isReady = true;
|
isReady = true;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task LoggedIn()
|
private Task LoggedIn()
|
||||||
{
|
{
|
||||||
Console.Title = "CONNECTED";
|
Config.Logger.Log("Successfully Logged In", source: typeof(Boot));
|
||||||
Logger.WriteLine("The bot has been logged in at " + DateTime.Now.ToShortDateString() + " (" +
|
|
||||||
DateTime.Now.ToShortTimeString() + ")"
|
|
||||||
);
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,21 +136,12 @@ internal class Boot
|
|||||||
{
|
{
|
||||||
case LogSeverity.Error:
|
case LogSeverity.Error:
|
||||||
case LogSeverity.Critical:
|
case LogSeverity.Critical:
|
||||||
Logger.WriteErrFile(message.Message);
|
Config.Logger.Log(message.Message, source: typeof(Boot), type: LogType.ERROR);
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
|
||||||
Console.WriteLine("[ERROR] " + message.Message);
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LogSeverity.Info:
|
case LogSeverity.Info:
|
||||||
case LogSeverity.Debug:
|
case LogSeverity.Debug:
|
||||||
Logger.WriteLogFile(message.Message);
|
Config.Logger.Log(message.Message, source: typeof(Boot), type: LogType.INFO);
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
|
||||||
Console.WriteLine("[INFO] " + message.Message);
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using PluginManager.Interfaces;
|
using PluginManager.Interfaces;
|
||||||
@@ -10,9 +9,7 @@ using PluginManager.Loaders;
|
|||||||
using PluginManager.Others;
|
using PluginManager.Others;
|
||||||
using PluginManager.Others.Permissions;
|
using PluginManager.Others.Permissions;
|
||||||
|
|
||||||
using static PluginManager.Logger;
|
namespace PluginManager.Bot;
|
||||||
|
|
||||||
namespace DiscordBot.Discord.Core;
|
|
||||||
|
|
||||||
internal class CommandHandler
|
internal class CommandHandler
|
||||||
{
|
{
|
||||||
@@ -31,7 +28,6 @@ internal class CommandHandler
|
|||||||
this.client = client;
|
this.client = client;
|
||||||
this.commandService = commandService;
|
this.commandService = commandService;
|
||||||
this.botPrefix = botPrefix;
|
this.botPrefix = botPrefix;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -49,9 +45,7 @@ internal class CommandHandler
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var plugin = PluginLoader.SlashCommands!
|
var plugin = PluginLoader.SlashCommands!.FirstOrDefault(p => p.Name == arg.Data.Name);
|
||||||
.Where(p => p.Name == arg.Data.Name)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (plugin is null)
|
if (plugin is null)
|
||||||
throw new Exception("Failed to run command. !");
|
throw new Exception("Failed to run command. !");
|
||||||
@@ -63,13 +57,10 @@ internal class CommandHandler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
Config.Logger.Log(ex.Message, type: LogType.ERROR, source: typeof(CommandHandler));
|
||||||
Console.WriteLine(ex.ToString());
|
|
||||||
ex.WriteErrFile();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -79,7 +70,6 @@ internal class CommandHandler
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task MessageHandler(SocketMessage Message)
|
private async Task MessageHandler(SocketMessage Message)
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (Message.Author.IsBot)
|
if (Message.Author.IsBot)
|
||||||
@@ -102,23 +92,23 @@ internal class CommandHandler
|
|||||||
|
|
||||||
await commandService.ExecuteAsync(context, argPos, null);
|
await commandService.ExecuteAsync(context, argPos, null);
|
||||||
|
|
||||||
DBCommand plugin;
|
DBCommand? plugin;
|
||||||
string cleanMessage = "";
|
var cleanMessage = "";
|
||||||
|
|
||||||
if (message.HasMentionPrefix(client.CurrentUser, ref argPos))
|
if (message.HasMentionPrefix(client.CurrentUser, ref argPos))
|
||||||
{
|
{
|
||||||
string mentionPrefix = "<@" + client.CurrentUser.Id + ">";
|
var mentionPrefix = "<@" + client.CurrentUser.Id + ">";
|
||||||
|
|
||||||
plugin = PluginLoader.Commands!
|
plugin = PluginLoader.Commands!
|
||||||
.Where
|
.FirstOrDefault(plug => plug.Command ==
|
||||||
(
|
message.Content.Substring(mentionPrefix.Length + 1)
|
||||||
plug => plug.Command == message.Content.Substring(mentionPrefix.Length+1).Split(' ')[0] ||
|
.Split(' ')[0] ||
|
||||||
(
|
(
|
||||||
plug.Aliases is not null &&
|
plug.Aliases is not null &&
|
||||||
plug.Aliases.Contains(message.CleanContent.Substring(mentionPrefix.Length+1).Split(' ')[0])
|
plug.Aliases.Contains(message.CleanContent
|
||||||
)
|
.Substring(mentionPrefix.Length + 1)
|
||||||
)
|
.Split(' ')[0])
|
||||||
.FirstOrDefault();
|
));
|
||||||
|
|
||||||
cleanMessage = message.Content.Substring(mentionPrefix.Length + 1);
|
cleanMessage = message.Content.Substring(mentionPrefix.Length + 1);
|
||||||
}
|
}
|
||||||
@@ -126,32 +116,34 @@ internal class CommandHandler
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
plugin = PluginLoader.Commands!
|
plugin = PluginLoader.Commands!
|
||||||
.Where(
|
.FirstOrDefault(p => p.Command ==
|
||||||
p => p.Command == message.Content.Split(' ')[0].Substring(botPrefix.Length) ||
|
message.Content.Split(' ')[0].Substring(botPrefix.Length) ||
|
||||||
(p.Aliases is not null &&
|
(p.Aliases is not null &&
|
||||||
p.Aliases.Contains(
|
p.Aliases.Contains(
|
||||||
message.Content.Split(' ')[0].Substring(botPrefix.Length))))
|
message.Content.Split(' ')[0]
|
||||||
.FirstOrDefault();
|
.Substring(botPrefix.Length))));
|
||||||
cleanMessage = message.Content.Substring(botPrefix.Length);
|
cleanMessage = message.Content.Substring(botPrefix.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plugin is null)
|
if (plugin is null)
|
||||||
throw new Exception($"Failed to run command ! " + message.CleanContent);
|
return;
|
||||||
|
|
||||||
if (plugin.requireAdmin && !context.Message.Author.isAdmin())
|
if (plugin.requireAdmin && !context.Message.Author.isAdmin())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string[] split = cleanMessage.Split(' ');
|
var split = cleanMessage.Split(' ');
|
||||||
|
|
||||||
string[] argsClean = null;
|
string[]? argsClean = null;
|
||||||
if(split.Length > 1)
|
if (split.Length > 1)
|
||||||
argsClean = string.Join(' ', split, 1, split.Length-1).Split(' ');
|
argsClean = string.Join(' ', split, 1, split.Length - 1).Split(' ');
|
||||||
|
|
||||||
CmdArgs cmd = new() {
|
DBCommandExecutingArguments cmd = new(context, cleanMessage, split[0], argsClean);
|
||||||
context = context,
|
|
||||||
cleanContent = cleanMessage,
|
Config.Logger.Log(
|
||||||
commandUsed = split[0],
|
message: $"User ({context.User.Username}) from Guild \"{context.Guild.Name}\" executed command \"{cmd.cleanContent}\"",
|
||||||
arguments = argsClean
|
source: typeof(CommandHandler),
|
||||||
};
|
type: LogType.INFO
|
||||||
|
);
|
||||||
|
|
||||||
if (context.Channel is SocketDMChannel)
|
if (context.Channel is SocketDMChannel)
|
||||||
plugin.ExecuteDM(cmd);
|
plugin.ExecuteDM(cmd);
|
||||||
@@ -159,9 +151,7 @@ internal class CommandHandler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
ex.WriteErrFile();
|
Config.Logger.Log(ex.Message, type: LogType.ERROR, source: typeof(CommandHandler));
|
||||||
|
|
||||||
Console.WriteLine(ex.ToString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,202 +1,43 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using PluginManager.Bot;
|
||||||
using PluginManager.Online.Helpers;
|
using PluginManager.Others;
|
||||||
|
using PluginManager.Others.Logger;
|
||||||
|
|
||||||
namespace PluginManager;
|
namespace PluginManager;
|
||||||
|
|
||||||
public static class Config
|
public class Config
|
||||||
{
|
{
|
||||||
private static bool IsLoaded = false;
|
private static bool _isLoaded;
|
||||||
|
public static Logger Logger;
|
||||||
|
public static SettingsDictionary<string, string> AppSettings;
|
||||||
|
|
||||||
|
internal static Boot? _DiscordBotClient;
|
||||||
|
|
||||||
|
public static Boot? DiscordBot => _DiscordBotClient;
|
||||||
|
|
||||||
public static async Task Initialize()
|
public static async Task Initialize()
|
||||||
{
|
{
|
||||||
if (IsLoaded)
|
if (_isLoaded) return;
|
||||||
return;
|
|
||||||
|
|
||||||
if (!await Settings.sqlDatabase.TableExistsAsync("Plugins"))
|
Directory.CreateDirectory("./Data/Resources");
|
||||||
await Settings.sqlDatabase.CreateTableAsync("Plugins", "PluginName", "Version");
|
Directory.CreateDirectory("./Data/Plugins");
|
||||||
if (!await Settings.sqlDatabase.TableExistsAsync("Variables"))
|
Directory.CreateDirectory("./Data/PAKS");
|
||||||
await Settings.sqlDatabase.CreateTableAsync("Variables", "VarName", "Value", "ReadOnly");
|
Directory.CreateDirectory("./Data/Logs/Logs");
|
||||||
|
Directory.CreateDirectory("./Data/Logs/Errors");
|
||||||
|
|
||||||
IsLoaded = true;
|
AppSettings = new SettingsDictionary<string, string>("./Data/Resources/config.json");
|
||||||
|
|
||||||
|
AppSettings["LogFolder"] = "./Data/Logs/Logs";
|
||||||
|
|
||||||
|
Logger = new Logger(false, true);
|
||||||
|
|
||||||
|
ArchiveManager.Initialize();
|
||||||
|
|
||||||
|
_isLoaded = true;
|
||||||
|
|
||||||
|
Logger.Log(message: "Config initialized", source: typeof(Config));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Variables
|
|
||||||
{
|
|
||||||
public static async Task<string> GetValueAsync(string VarName)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
return await Settings.sqlDatabase.GetValueAsync("Variables", "VarName", VarName, "Value");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetValue(string VarName)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
return Settings.sqlDatabase.GetValue("Variables", "VarName", VarName, "Value");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static async Task SetValueAsync(string VarName, string Value)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
|
|
||||||
if (await IsReadOnlyAsync(VarName))
|
|
||||||
throw new Exception($"Variable ({VarName}) is read only and can not be changed to {Value}");
|
|
||||||
|
|
||||||
await Settings.sqlDatabase.SetValueAsync("Variables", "VarName", VarName, "Value", Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetValue(string VarName, string Value)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
if (IsReadOnly(VarName))
|
|
||||||
throw new Exception($"Variable ({VarName}) is read only and can not be changed to {Value}");
|
|
||||||
Settings.sqlDatabase.SetValue("Variables", "VarName", VarName, "Value", Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static async Task<bool> IsReadOnlyAsync(string VarName)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
return (await Settings.sqlDatabase.GetValueAsync("Variables", "VarName", VarName, "ReadOnly")).Equals("true", StringComparison.CurrentCultureIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsReadOnly(string VarName)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
return (Settings.sqlDatabase.GetValue("Variables", "VarName", VarName, "ReadOnly")).Equals("true", StringComparison.CurrentCultureIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task SetReadOnlyAsync(string VarName, bool ReadOnly)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
await Settings.sqlDatabase.SetValueAsync("Variables", "VarName", VarName, "ReadOnly", ReadOnly ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetReadOnly(string VarName, bool ReadOnly)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
Settings.sqlDatabase.SetValue("Variables", "VarName", VarName, "ReadOnly", ReadOnly ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<bool> ExistsAsync(string VarName)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
return await Settings.sqlDatabase.KeyExistsAsync("Variables", "VarName", VarName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Exists(string VarName)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
return Settings.sqlDatabase.KeyExists("Variables", "VarName", VarName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task AddAsync(string VarName, string Value, bool ReadOnly = false)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
if (await ExistsAsync(VarName))
|
|
||||||
{
|
|
||||||
await SetValueAsync(VarName, Value);
|
|
||||||
await SetReadOnlyAsync(VarName, ReadOnly);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await Settings.sqlDatabase.InsertAsync("Variables", VarName, Value, ReadOnly ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Add(string VarName, string Value, bool ReadOnly = false)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
if (Exists(VarName))
|
|
||||||
{
|
|
||||||
if (GetValue(VarName) == Value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetValue(VarName, Value);
|
|
||||||
SetReadOnly(VarName, ReadOnly);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Settings.sqlDatabase.Insert("Variables", VarName, Value, ReadOnly ? "true" : "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task RemoveKeyAsync(string VarName)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
await Settings.sqlDatabase.RemoveKeyAsync("Variables", "VarName", VarName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void RemoveKey(string VarName)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded");
|
|
||||||
Settings.sqlDatabase.RemoveKey("Variables", "VarName", VarName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Plugins
|
|
||||||
{
|
|
||||||
public static async Task<string> GetVersionAsync(string pluginName)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded yet");
|
|
||||||
|
|
||||||
string result = await Settings.sqlDatabase.GetValueAsync("Plugins", "PluginName", pluginName, "Version");
|
|
||||||
if (result is null)
|
|
||||||
return "0.0.0";
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetVersion(string pluginName)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded yet");
|
|
||||||
|
|
||||||
string result = Settings.sqlDatabase.GetValue("Plugins", "PluginName", pluginName, "Version");
|
|
||||||
if (result is null)
|
|
||||||
return "0.0.0";
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task SetVersionAsync(string pluginName, VersionString version)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded yet");
|
|
||||||
|
|
||||||
if (!await Settings.sqlDatabase.KeyExistsAsync("Plugins", "PluginName", pluginName))
|
|
||||||
{
|
|
||||||
await Settings.sqlDatabase.InsertAsync("Plugins", pluginName, version.ToShortString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await Settings.sqlDatabase.SetValueAsync("Plugins", "PluginName", pluginName, "Version", version.ToShortString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetVersion(string pluginName, VersionString version)
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
throw new Exception("Config is not loaded yet");
|
|
||||||
|
|
||||||
if (!Settings.sqlDatabase.KeyExists("Plugins", "PluginName", pluginName))
|
|
||||||
{
|
|
||||||
Settings.sqlDatabase.Insert("Plugins", pluginName, version.ToShortString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Settings.sqlDatabase.SetValue("Plugins", "PluginName", pluginName, "Version", version.ToShortString());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,37 +1,52 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
using System.Data.SQLite;
|
using System.Data.SQLite;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PluginManager.Database
|
namespace PluginManager.Database;
|
||||||
{
|
|
||||||
public class SqlDatabase
|
|
||||||
{
|
|
||||||
private string ConnectionString;
|
|
||||||
private SQLiteConnection Connection;
|
|
||||||
|
|
||||||
|
public class SqlDatabase
|
||||||
|
{
|
||||||
|
private readonly SQLiteConnection Connection;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize a SQL connection by specifing its private path
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileName">The path to the database (it is starting from ./Data/Resources/)</param>
|
||||||
public SqlDatabase(string fileName)
|
public SqlDatabase(string fileName)
|
||||||
{
|
{
|
||||||
if (!fileName.StartsWith("./Data/Resources/"))
|
if (!fileName.StartsWith("./Data/Resources/"))
|
||||||
fileName = Path.Combine("./Data/Resources", fileName);
|
fileName = Path.Combine("./Data/Resources", fileName);
|
||||||
if (!File.Exists(fileName))
|
if (!File.Exists(fileName))
|
||||||
SQLiteConnection.CreateFile(fileName);
|
SQLiteConnection.CreateFile(fileName);
|
||||||
ConnectionString = $"URI=file:{fileName}";
|
var connectionString = $"URI=file:{fileName}";
|
||||||
Connection = new SQLiteConnection(ConnectionString);
|
Connection = new SQLiteConnection(connectionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Open the SQL Connection. To close use the Stop() method
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task Open()
|
public async Task Open()
|
||||||
{
|
{
|
||||||
await Connection.OpenAsync();
|
await Connection.OpenAsync();
|
||||||
|
|
||||||
//Console.WriteLine("Opened database successfully");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>
|
||||||
|
/// Insert into a specified table some values
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="values">The values to be inserted (in the correct order and number)</param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task InsertAsync(string tableName, params string[] values)
|
public async Task InsertAsync(string tableName, params string[] values)
|
||||||
{
|
{
|
||||||
string query = $"INSERT INTO {tableName} VALUES (";
|
var query = $"INSERT INTO {tableName} VALUES (";
|
||||||
for (int i = 0; i < values.Length; i++)
|
for (var i = 0; i < values.Length; i++)
|
||||||
{
|
{
|
||||||
query += $"'{values[i]}'";
|
query += $"'{values[i]}'";
|
||||||
if (i != values.Length - 1)
|
if (i != values.Length - 1)
|
||||||
@@ -40,14 +55,22 @@ namespace PluginManager.Database
|
|||||||
|
|
||||||
query += ")";
|
query += ")";
|
||||||
|
|
||||||
SQLiteCommand command = new SQLiteCommand(query, Connection);
|
var command = new SQLiteCommand(query, Connection);
|
||||||
await command.ExecuteNonQueryAsync();
|
await command.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>
|
||||||
|
/// Insert into a specified table some values
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="values">The values to be inserted (in the correct order and number)</param>
|
||||||
|
/// <returns></returns>
|
||||||
public void Insert(string tableName, params string[] values)
|
public void Insert(string tableName, params string[] values)
|
||||||
{
|
{
|
||||||
string query = $"INSERT INTO {tableName} VALUES (";
|
var query = $"INSERT INTO {tableName} VALUES (";
|
||||||
for (int i = 0; i < values.Length; i++)
|
for (var i = 0; i < values.Length; i++)
|
||||||
{
|
{
|
||||||
query += $"'{values[i]}'";
|
query += $"'{values[i]}'";
|
||||||
if (i != values.Length - 1)
|
if (i != values.Length - 1)
|
||||||
@@ -56,30 +79,50 @@ namespace PluginManager.Database
|
|||||||
|
|
||||||
query += ")";
|
query += ")";
|
||||||
|
|
||||||
SQLiteCommand command = new SQLiteCommand(query, Connection);
|
var command = new SQLiteCommand(query, Connection);
|
||||||
command.ExecuteNonQuery();
|
command.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove every row in a table that has a certain propery
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="KeyName">The column name that the search is made by</param>
|
||||||
|
/// <param name="KeyValue">The value that is searched in the specified column</param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task RemoveKeyAsync(string tableName, string KeyName, string KeyValue)
|
public async Task RemoveKeyAsync(string tableName, string KeyName, string KeyValue)
|
||||||
{
|
{
|
||||||
string query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
|
var query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
|
||||||
|
|
||||||
SQLiteCommand command = new SQLiteCommand(query, Connection);
|
var command = new SQLiteCommand(query, Connection);
|
||||||
await command.ExecuteNonQueryAsync();
|
await command.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove every row in a table that has a certain propery
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="KeyName">The column name that the search is made by</param>
|
||||||
|
/// <param name="KeyValue">The value that is searched in the specified column</param>
|
||||||
|
/// <returns></returns>
|
||||||
public void RemoveKey(string tableName, string KeyName, string KeyValue)
|
public void RemoveKey(string tableName, string KeyName, string KeyValue)
|
||||||
{
|
{
|
||||||
string query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
|
var query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
|
||||||
|
|
||||||
SQLiteCommand command = new SQLiteCommand(query, Connection);
|
var command = new SQLiteCommand(query, Connection);
|
||||||
command.ExecuteNonQuery();
|
command.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if the key exists in the table
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="keyName">The column that the search is made by</param>
|
||||||
|
/// <param name="KeyValue">The value that is searched in the specified column</param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task<bool> KeyExistsAsync(string tableName, string keyName, string KeyValue)
|
public async Task<bool> KeyExistsAsync(string tableName, string keyName, string KeyValue)
|
||||||
{
|
{
|
||||||
string query = $"SELECT * FROM {tableName} where {keyName} = '{KeyValue}'";
|
var query = $"SELECT * FROM {tableName} where {keyName} = '{KeyValue}'";
|
||||||
|
|
||||||
if (await ReadDataAsync(query) is not null)
|
if (await ReadDataAsync(query) is not null)
|
||||||
return true;
|
return true;
|
||||||
@@ -87,9 +130,16 @@ namespace PluginManager.Database
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if the key exists in the table
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="keyName">The column that the search is made by</param>
|
||||||
|
/// <param name="KeyValue">The value that is searched in the specified column</param>
|
||||||
|
/// <returns></returns>
|
||||||
public bool KeyExists(string tableName, string keyName, string KeyValue)
|
public bool KeyExists(string tableName, string keyName, string KeyValue)
|
||||||
{
|
{
|
||||||
string query = $"SELECT * FROM {tableName} where {keyName} = '{KeyValue}'";
|
var query = $"SELECT * FROM {tableName} where {keyName} = '{KeyValue}'";
|
||||||
|
|
||||||
if (ReadData(query) is not null)
|
if (ReadData(query) is not null)
|
||||||
return true;
|
return true;
|
||||||
@@ -97,87 +147,139 @@ namespace PluginManager.Database
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
public async Task SetValueAsync(string tableName, string keyName, string KeyValue, string ResultColumnName,
|
/// Set value of a column in a table
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="keyName">The column that the search is made by</param>
|
||||||
|
/// <param name="KeyValue">The value that is searched in the column specified</param>
|
||||||
|
/// <param name="ResultColumnName">The column that has to be modified</param>
|
||||||
|
/// <param name="ResultColumnValue">The new value that will replace the old value from the column specified</param>
|
||||||
|
public async Task SetValueAsync(
|
||||||
|
string tableName, string keyName, string KeyValue, string ResultColumnName,
|
||||||
string ResultColumnValue)
|
string ResultColumnValue)
|
||||||
{
|
{
|
||||||
if (!await TableExistsAsync(tableName))
|
if (!await TableExistsAsync(tableName))
|
||||||
throw new System.Exception($"Table {tableName} does not exist");
|
throw new Exception($"Table {tableName} does not exist");
|
||||||
|
|
||||||
await ExecuteAsync(
|
await ExecuteAsync(
|
||||||
$"UPDATE {tableName} SET {ResultColumnName}='{ResultColumnValue}' WHERE {keyName}='{KeyValue}'");
|
$"UPDATE {tableName} SET {ResultColumnName}='{ResultColumnValue}' WHERE {keyName}='{KeyValue}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetValue(string tableName, string keyName, string KeyValue, string ResultColumnName,
|
/// <summary>
|
||||||
|
/// Set value of a column in a table
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="keyName">The column that the search is made by</param>
|
||||||
|
/// <param name="KeyValue">The value that is searched in the column specified</param>
|
||||||
|
/// <param name="ResultColumnName">The column that has to be modified</param>
|
||||||
|
/// <param name="ResultColumnValue">The new value that will replace the old value from the column specified</param>
|
||||||
|
public void SetValue(
|
||||||
|
string tableName, string keyName, string KeyValue, string ResultColumnName,
|
||||||
string ResultColumnValue)
|
string ResultColumnValue)
|
||||||
{
|
{
|
||||||
if (!TableExists(tableName))
|
if (!TableExists(tableName))
|
||||||
throw new System.Exception($"Table {tableName} does not exist");
|
throw new Exception($"Table {tableName} does not exist");
|
||||||
|
|
||||||
Execute($"UPDATE {tableName} SET {ResultColumnName}='{ResultColumnValue}' WHERE {keyName}='{KeyValue}'");
|
Execute($"UPDATE {tableName} SET {ResultColumnName}='{ResultColumnValue}' WHERE {keyName}='{KeyValue}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
public async Task<string?> GetValueAsync(string tableName, string keyName, string KeyValue,
|
/// Get value from a column in a table
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="keyName">The column that the search is made by</param>
|
||||||
|
/// <param name="KeyValue">The value that is searched in the specified column</param>
|
||||||
|
/// <param name="ResultColumnName">The column that has the result</param>
|
||||||
|
/// <returns>A string that has the requested value (can be null if nothing found)</returns>
|
||||||
|
public async Task<string?> GetValueAsync(
|
||||||
|
string tableName, string keyName, string KeyValue,
|
||||||
string ResultColumnName)
|
string ResultColumnName)
|
||||||
{
|
{
|
||||||
if (!await TableExistsAsync(tableName))
|
if (!await TableExistsAsync(tableName))
|
||||||
throw new System.Exception($"Table {tableName} does not exist");
|
throw new Exception($"Table {tableName} does not exist");
|
||||||
|
|
||||||
return await ReadDataAsync($"SELECT {ResultColumnName} FROM {tableName} WHERE {keyName}='{KeyValue}'");
|
return await ReadDataAsync($"SELECT {ResultColumnName} FROM {tableName} WHERE {keyName}='{KeyValue}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get value from a column in a table
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="keyName">The column that the search is made by</param>
|
||||||
|
/// <param name="KeyValue">The value that is searched in the specified column</param>
|
||||||
|
/// <param name="ResultColumnName">The column that has the result</param>
|
||||||
|
/// <returns>A string that has the requested value (can be null if nothing found)</returns>
|
||||||
public string? GetValue(string tableName, string keyName, string KeyValue, string ResultColumnName)
|
public string? GetValue(string tableName, string keyName, string KeyValue, string ResultColumnName)
|
||||||
{
|
{
|
||||||
if (!TableExists(tableName))
|
if (!TableExists(tableName))
|
||||||
throw new System.Exception($"Table {tableName} does not exist");
|
throw new Exception($"Table {tableName} does not exist");
|
||||||
|
|
||||||
return ReadData($"SELECT {ResultColumnName} FROM {tableName} WHERE {keyName}='{KeyValue}'");
|
return ReadData($"SELECT {ResultColumnName} FROM {tableName} WHERE {keyName}='{KeyValue}'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop the connection to the SQL Database
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public async void Stop()
|
public async void Stop()
|
||||||
{
|
{
|
||||||
await Connection.CloseAsync();
|
await Connection.CloseAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddColumnsToTableAsync(string tableName, string[] columns)
|
/// <summary>
|
||||||
|
/// Change the structure of a table by adding new columns
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="columns">The columns to be added</param>
|
||||||
|
/// <param name="TYPE">The type of the columns (TEXT, INTEGER, FLOAT, etc)</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task AddColumnsToTableAsync(string tableName, string[] columns, string TYPE = "TEXT")
|
||||||
{
|
{
|
||||||
var command = Connection.CreateCommand();
|
var command = Connection.CreateCommand();
|
||||||
command.CommandText = $"SELECT * FROM {tableName}";
|
command.CommandText = $"SELECT * FROM {tableName}";
|
||||||
var reader = await command.ExecuteReaderAsync();
|
var reader = await command.ExecuteReaderAsync();
|
||||||
var tableColumns = new List<string>();
|
var tableColumns = new List<string>();
|
||||||
for (int i = 0; i < reader.FieldCount; i++)
|
for (var i = 0; i < reader.FieldCount; i++)
|
||||||
tableColumns.Add(reader.GetName(i));
|
tableColumns.Add(reader.GetName(i));
|
||||||
|
|
||||||
foreach (var column in columns)
|
foreach (var column in columns)
|
||||||
{
|
|
||||||
if (!tableColumns.Contains(column))
|
if (!tableColumns.Contains(column))
|
||||||
{
|
{
|
||||||
command.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {column} TEXT";
|
command.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {column} {TYPE}";
|
||||||
await command.ExecuteNonQueryAsync();
|
await command.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void AddColumnsToTable(string tableName, string[] columns)
|
/// <summary>
|
||||||
|
/// Change the structure of a table by adding new columns
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="columns">The columns to be added</param>
|
||||||
|
/// <param name="TYPE">The type of the columns (TEXT, INTEGER, FLOAT, etc)</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public void AddColumnsToTable(string tableName, string[] columns, string TYPE = "TEXT")
|
||||||
{
|
{
|
||||||
var command = Connection.CreateCommand();
|
var command = Connection.CreateCommand();
|
||||||
command.CommandText = $"SELECT * FROM {tableName}";
|
command.CommandText = $"SELECT * FROM {tableName}";
|
||||||
var reader = command.ExecuteReader();
|
var reader = command.ExecuteReader();
|
||||||
var tableColumns = new List<string>();
|
var tableColumns = new List<string>();
|
||||||
for (int i = 0; i < reader.FieldCount; i++)
|
for (var i = 0; i < reader.FieldCount; i++)
|
||||||
tableColumns.Add(reader.GetName(i));
|
tableColumns.Add(reader.GetName(i));
|
||||||
|
|
||||||
foreach (var column in columns)
|
foreach (var column in columns)
|
||||||
{
|
|
||||||
if (!tableColumns.Contains(column))
|
if (!tableColumns.Contains(column))
|
||||||
{
|
{
|
||||||
command.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {column} TEXT";
|
command.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {column} {TYPE}";
|
||||||
command.ExecuteNonQuery();
|
command.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if a table exists
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <returns>True if the table exists, false if not</returns>
|
||||||
public async Task<bool> TableExistsAsync(string tableName)
|
public async Task<bool> TableExistsAsync(string tableName)
|
||||||
{
|
{
|
||||||
var cmd = Connection.CreateCommand();
|
var cmd = Connection.CreateCommand();
|
||||||
@@ -189,6 +291,11 @@ namespace PluginManager.Database
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if a table exists
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <returns>True if the table exists, false if not</returns>
|
||||||
public bool TableExists(string tableName)
|
public bool TableExists(string tableName)
|
||||||
{
|
{
|
||||||
var cmd = Connection.CreateCommand();
|
var cmd = Connection.CreateCommand();
|
||||||
@@ -200,6 +307,12 @@ namespace PluginManager.Database
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a table
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="columns">The columns of the table</param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task CreateTableAsync(string tableName, params string[] columns)
|
public async Task CreateTableAsync(string tableName, params string[] columns)
|
||||||
{
|
{
|
||||||
var cmd = Connection.CreateCommand();
|
var cmd = Connection.CreateCommand();
|
||||||
@@ -207,6 +320,12 @@ namespace PluginManager.Database
|
|||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a table
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tableName">The table name</param>
|
||||||
|
/// <param name="columns">The columns of the table</param>
|
||||||
|
/// <returns></returns>
|
||||||
public void CreateTable(string tableName, params string[] columns)
|
public void CreateTable(string tableName, params string[] columns)
|
||||||
{
|
{
|
||||||
var cmd = Connection.CreateCommand();
|
var cmd = Connection.CreateCommand();
|
||||||
@@ -214,33 +333,48 @@ namespace PluginManager.Database
|
|||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute a custom query
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query</param>
|
||||||
|
/// <returns>The number of rows that the query modified</returns>
|
||||||
public async Task<int> ExecuteAsync(string query)
|
public async Task<int> ExecuteAsync(string query)
|
||||||
{
|
{
|
||||||
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
||||||
await Connection.OpenAsync();
|
await Connection.OpenAsync();
|
||||||
var command = new SQLiteCommand(query, Connection);
|
var command = new SQLiteCommand(query, Connection);
|
||||||
int answer = await command.ExecuteNonQueryAsync();
|
var answer = await command.ExecuteNonQueryAsync();
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute a custom query
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query</param>
|
||||||
|
/// <returns>The number of rows that the query modified</returns>
|
||||||
public int Execute(string query)
|
public int Execute(string query)
|
||||||
{
|
{
|
||||||
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
||||||
Connection.Open();
|
Connection.Open();
|
||||||
var command = new SQLiteCommand(query, Connection);
|
var command = new SQLiteCommand(query, Connection);
|
||||||
int r = command.ExecuteNonQuery();
|
var r = command.ExecuteNonQuery();
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read data from the result table and return the first row
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query</param>
|
||||||
|
/// <returns>The result is a string that has all values separated by space character</returns>
|
||||||
public async Task<string?> ReadDataAsync(string query)
|
public async Task<string?> ReadDataAsync(string query)
|
||||||
{
|
{
|
||||||
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
||||||
await Connection.OpenAsync();
|
await Connection.OpenAsync();
|
||||||
var command = new SQLiteCommand(query, Connection);
|
var command = new SQLiteCommand(query, Connection);
|
||||||
var reader = await command.ExecuteReaderAsync();
|
var reader = await command.ExecuteReaderAsync();
|
||||||
|
|
||||||
object[] values = new object[reader.FieldCount];
|
var values = new object[reader.FieldCount];
|
||||||
if (reader.Read())
|
if (reader.Read())
|
||||||
{
|
{
|
||||||
reader.GetValues(values);
|
reader.GetValues(values);
|
||||||
@@ -250,14 +384,19 @@ namespace PluginManager.Database
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read data from the result table and return the first row
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query</param>
|
||||||
|
/// <returns>The result is a string that has all values separated by space character</returns>
|
||||||
public string? ReadData(string query)
|
public string? ReadData(string query)
|
||||||
{
|
{
|
||||||
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
||||||
Connection.Open();
|
Connection.Open();
|
||||||
var command = new SQLiteCommand(query, Connection);
|
var command = new SQLiteCommand(query, Connection);
|
||||||
var reader = command.ExecuteReader();
|
var reader = command.ExecuteReader();
|
||||||
|
|
||||||
object[] values = new object[reader.FieldCount];
|
var values = new object[reader.FieldCount];
|
||||||
if (reader.Read())
|
if (reader.Read())
|
||||||
{
|
{
|
||||||
reader.GetValues(values);
|
reader.GetValues(values);
|
||||||
@@ -267,14 +406,19 @@ namespace PluginManager.Database
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read data from the result table and return the first row
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query</param>
|
||||||
|
/// <returns>The first row as separated items</returns>
|
||||||
public async Task<object[]?> ReadDataArrayAsync(string query)
|
public async Task<object[]?> ReadDataArrayAsync(string query)
|
||||||
{
|
{
|
||||||
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
||||||
await Connection.OpenAsync();
|
await Connection.OpenAsync();
|
||||||
var command = new SQLiteCommand(query, Connection);
|
var command = new SQLiteCommand(query, Connection);
|
||||||
var reader = await command.ExecuteReaderAsync();
|
var reader = await command.ExecuteReaderAsync();
|
||||||
|
|
||||||
object[] values = new object[reader.FieldCount];
|
var values = new object[reader.FieldCount];
|
||||||
if (reader.Read())
|
if (reader.Read())
|
||||||
{
|
{
|
||||||
reader.GetValues(values);
|
reader.GetValues(values);
|
||||||
@@ -284,9 +428,38 @@ namespace PluginManager.Database
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read data from the result table and return the first row
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query</param>
|
||||||
|
/// <returns>The first row as separated items</returns>
|
||||||
|
public object[]? ReadDataArray(string query)
|
||||||
|
{
|
||||||
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
||||||
|
Connection.Open();
|
||||||
|
var command = new SQLiteCommand(query, Connection);
|
||||||
|
var reader = command.ExecuteReader();
|
||||||
|
|
||||||
|
var values = new object[reader.FieldCount];
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
reader.GetValues(values);
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read all rows from the result table and return them as a list of string arrays. The string arrays contain the
|
||||||
|
/// values of each row
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="query">The query</param>
|
||||||
|
/// <returns>A list of string arrays representing the values that the query returns</returns>
|
||||||
public async Task<List<string[]>?> ReadAllRowsAsync(string query)
|
public async Task<List<string[]>?> ReadAllRowsAsync(string query)
|
||||||
{
|
{
|
||||||
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
|
if (!Connection.State.HasFlag(ConnectionState.Open))
|
||||||
await Connection.OpenAsync();
|
await Connection.OpenAsync();
|
||||||
var command = new SQLiteCommand(query, Connection);
|
var command = new SQLiteCommand(query, Connection);
|
||||||
var reader = await command.ExecuteReaderAsync();
|
var reader = await command.ExecuteReaderAsync();
|
||||||
@@ -297,7 +470,7 @@ namespace PluginManager.Database
|
|||||||
List<string[]> rows = new();
|
List<string[]> rows = new();
|
||||||
while (await reader.ReadAsync())
|
while (await reader.ReadAsync())
|
||||||
{
|
{
|
||||||
string[] values = new string[reader.FieldCount];
|
var values = new string[reader.FieldCount];
|
||||||
reader.GetValues(values);
|
reader.GetValues(values);
|
||||||
rows.Add(values);
|
rows.Add(values);
|
||||||
}
|
}
|
||||||
@@ -306,22 +479,4 @@ namespace PluginManager.Database
|
|||||||
|
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object[]? ReadDataArray(string query)
|
|
||||||
{
|
|
||||||
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
|
|
||||||
Connection.Open();
|
|
||||||
var command = new SQLiteCommand(query, Connection);
|
|
||||||
var reader = command.ExecuteReader();
|
|
||||||
|
|
||||||
object[] values = new object[reader.FieldCount];
|
|
||||||
if (reader.Read())
|
|
||||||
{
|
|
||||||
reader.GetValues(values);
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using Discord.Commands;
|
|
||||||
using PluginManager.Others;
|
using PluginManager.Others;
|
||||||
|
|
||||||
namespace PluginManager.Interfaces;
|
namespace PluginManager.Interfaces;
|
||||||
@@ -37,16 +35,16 @@ public interface DBCommand
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main body of the command. This is what is executed when user calls the command in Server
|
/// The main body of the command. This is what is executed when user calls the command in Server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">The disocrd Context</param>
|
/// <param name="args">The disocrd Context</param>
|
||||||
void ExecuteServer(CmdArgs args)
|
void ExecuteServer(DBCommandExecutingArguments args)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main body of the command. This is what is executed when user calls the command in DM
|
/// The main body of the command. This is what is executed when user calls the command in DM
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">The disocrd Context</param>
|
/// <param name="args">The disocrd Context</param>
|
||||||
void ExecuteDM(CmdArgs args)
|
void ExecuteDM(DBCommandExecutingArguments args)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
|
||||||
namespace PluginManager.Interfaces
|
namespace PluginManager.Interfaces;
|
||||||
|
|
||||||
|
public interface DBSlashCommand
|
||||||
{
|
{
|
||||||
public interface DBSlashCommand
|
|
||||||
{
|
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
string Description { get; }
|
string Description { get; }
|
||||||
|
|
||||||
@@ -16,10 +15,7 @@ namespace PluginManager.Interfaces
|
|||||||
|
|
||||||
void ExecuteServer(SocketSlashCommand context)
|
void ExecuteServer(SocketSlashCommand context)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecuteDM(SocketSlashCommand context) { }
|
void ExecuteDM(SocketSlashCommand context) { }
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
17
PluginManager/Interfaces/IInternalAction.cs
Normal file
17
PluginManager/Interfaces/IInternalAction.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using PluginManager.Others;
|
||||||
|
|
||||||
|
namespace PluginManager.Interfaces;
|
||||||
|
|
||||||
|
public interface ICommandAction
|
||||||
|
{
|
||||||
|
public string ActionName { get; }
|
||||||
|
|
||||||
|
public string? Description { get; }
|
||||||
|
|
||||||
|
public string? Usage { get; }
|
||||||
|
|
||||||
|
public InternalActionRunType RunType { get; }
|
||||||
|
|
||||||
|
public Task Execute(string[]? args);
|
||||||
|
}
|
||||||
15
PluginManager/Interfaces/Logger/ILog.cs
Normal file
15
PluginManager/Interfaces/Logger/ILog.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using PluginManager.Others;
|
||||||
|
|
||||||
|
namespace PluginManager.Interfaces.Logger;
|
||||||
|
|
||||||
|
internal interface ILog
|
||||||
|
{
|
||||||
|
string Message { get; set; }
|
||||||
|
string OutputFile { get; set; }
|
||||||
|
|
||||||
|
Type? Source { get; set; }
|
||||||
|
|
||||||
|
LogType Type { get; set; }
|
||||||
|
DateTime ThrowTime { get; set; }
|
||||||
|
}
|
||||||
17
PluginManager/Interfaces/Logger/ILogger.cs
Normal file
17
PluginManager/Interfaces/Logger/ILogger.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using PluginManager.Others;
|
||||||
|
using PluginManager.Others.Logger;
|
||||||
|
|
||||||
|
namespace PluginManager.Interfaces.Logger;
|
||||||
|
|
||||||
|
internal interface ILogger
|
||||||
|
{
|
||||||
|
bool IsEnabled { get; init; }
|
||||||
|
bool OutputToFile { get; init; }
|
||||||
|
|
||||||
|
event EventHandler<Log> OnLog;
|
||||||
|
void Log(
|
||||||
|
string message = "", string outputFile = "", Type? source = default, LogType type = LogType.INFO,
|
||||||
|
DateTime throwTime = default);
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Discord.Commands;
|
|
||||||
using Discord.WebSocket;
|
|
||||||
|
|
||||||
namespace PluginManager.Items;
|
|
||||||
|
|
||||||
public class ConsoleCommand
|
|
||||||
{
|
|
||||||
public string? CommandName { get; init; }
|
|
||||||
public string? Description { get; init; }
|
|
||||||
public string? Usage { get; init; }
|
|
||||||
public Action<string[]>? Action { get; init; }
|
|
||||||
}
|
|
||||||
@@ -1,533 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
using Discord.WebSocket;
|
|
||||||
|
|
||||||
using PluginManager.Loaders;
|
|
||||||
using PluginManager.Online;
|
|
||||||
using PluginManager.Others;
|
|
||||||
|
|
||||||
using OperatingSystem = PluginManager.Others.OperatingSystem;
|
|
||||||
|
|
||||||
namespace PluginManager.Items;
|
|
||||||
|
|
||||||
public class ConsoleCommandsHandler
|
|
||||||
{
|
|
||||||
private static readonly PluginsManager manager =
|
|
||||||
new("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Plugins.txt");
|
|
||||||
|
|
||||||
private static readonly List<ConsoleCommand> commandList = new();
|
|
||||||
|
|
||||||
|
|
||||||
private static bool isDownloading;
|
|
||||||
private static bool pluginsLoaded;
|
|
||||||
private readonly DiscordSocketClient? client;
|
|
||||||
|
|
||||||
public ConsoleCommandsHandler(DiscordSocketClient client)
|
|
||||||
{
|
|
||||||
if (!Logger.isConsole) throw new Exception("Can not use ConsoleCommandsHandler for Non console apps");
|
|
||||||
this.client = client;
|
|
||||||
InitializeBasicCommands();
|
|
||||||
|
|
||||||
|
|
||||||
//Logger.WriteLine("Initialized console command handler !");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeBasicCommands()
|
|
||||||
{
|
|
||||||
commandList.Clear();
|
|
||||||
|
|
||||||
AddCommand("help", "Show help", "help <command>", args =>
|
|
||||||
{
|
|
||||||
if (args.Length <= 1)
|
|
||||||
{
|
|
||||||
Logger.WriteLine("Available commands:");
|
|
||||||
var items = new List<string[]>();
|
|
||||||
items.Add(new[] { "-", "-", "-" });
|
|
||||||
items.Add(new[] { "Command", "Description", "Usage" });
|
|
||||||
items.Add(new[] { " ", " ", "Argument type: <optional> [required]" });
|
|
||||||
items.Add(new[] { "-", "-", "-" });
|
|
||||||
|
|
||||||
foreach (var command in commandList)
|
|
||||||
{
|
|
||||||
if (!command.CommandName.StartsWith("_"))
|
|
||||||
items.Add(new[] { command.CommandName, command.Description, command.Usage });
|
|
||||||
}
|
|
||||||
|
|
||||||
items.Add(new[] { "-", "-", "-" });
|
|
||||||
Utilities.FormatAndAlignTable(items, TableFormat.DEFAULT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var command in commandList)
|
|
||||||
if (command.CommandName == args[1])
|
|
||||||
{
|
|
||||||
Logger.WriteLine("Command description: " + command.Description);
|
|
||||||
Logger.WriteLine("Command execution format:" + command.Usage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.WriteLine("Command not found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
AddCommand("lp", "Load plugins", () =>
|
|
||||||
{
|
|
||||||
if (pluginsLoaded)
|
|
||||||
return;
|
|
||||||
var loader = new PluginLoader(client!);
|
|
||||||
var cc = Console.ForegroundColor;
|
|
||||||
loader.onCMDLoad += (name, typeName, success, exception) =>
|
|
||||||
{
|
|
||||||
if (name == null || name.Length < 2)
|
|
||||||
name = typeName;
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
|
||||||
Logger.WriteLine("[CMD] Successfully loaded command : " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
|
||||||
if (exception is null)
|
|
||||||
Logger.WriteLine("An error occured while loading: " + name);
|
|
||||||
else
|
|
||||||
Logger.WriteLine("[CMD] Failed to load command : " + name + " because " + exception!.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.ForegroundColor = cc;
|
|
||||||
};
|
|
||||||
loader.onEVELoad += (name, typeName, success, exception) =>
|
|
||||||
{
|
|
||||||
if (name == null || name.Length < 2)
|
|
||||||
name = typeName;
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
|
||||||
Logger.WriteLine("[EVENT] Successfully loaded event : " + name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
|
||||||
Logger.WriteLine("[EVENT] Failed to load event : " + name + " because " + exception!.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.ForegroundColor = cc;
|
|
||||||
};
|
|
||||||
|
|
||||||
loader.onSLSHLoad += (name, typeName, success, exception) =>
|
|
||||||
{
|
|
||||||
if (name == null || name.Length < 2)
|
|
||||||
name = typeName;
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
|
||||||
Logger.WriteLine("[SLASH] Successfully loaded command : " + name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
|
||||||
Logger.WriteLine("[SLASH] Failed to load command : " + name + " because " + exception!.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.ForegroundColor = cc;
|
|
||||||
};
|
|
||||||
|
|
||||||
loader.LoadPlugins();
|
|
||||||
Console.ForegroundColor = cc;
|
|
||||||
pluginsLoaded = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
AddCommand("listplugs", "list available plugins", () => { manager.ListAvailablePlugins().Wait(); });
|
|
||||||
|
|
||||||
AddCommand("dwplug", "download plugin", "dwplug [name]", async args =>
|
|
||||||
{
|
|
||||||
isDownloading = true;
|
|
||||||
if (args.Length == 1)
|
|
||||||
{
|
|
||||||
isDownloading = false;
|
|
||||||
Logger.WriteLine("Please specify plugin name");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var name = string.Join(' ', args, 1, args.Length - 1);
|
|
||||||
// info[0] = plugin type
|
|
||||||
// info[1] = plugin link
|
|
||||||
// info[2] = if others are required, or string.Empty if none
|
|
||||||
var info = await manager.GetPluginLinkByName(name);
|
|
||||||
if (info[1] == null) // link is null
|
|
||||||
{
|
|
||||||
if (name == "")
|
|
||||||
{
|
|
||||||
isDownloading = false;
|
|
||||||
Utilities.WriteColorText("Name is invalid");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
isDownloading = false;
|
|
||||||
Utilities.WriteColorText($"Failed to find plugin &b{name} &c!" +
|
|
||||||
" Use &glistplugs &ccommand to display all available plugins !");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string path;
|
|
||||||
if (info[0] == "Plugin")
|
|
||||||
path = "./Data/Plugins/" + name + ".dll";
|
|
||||||
else
|
|
||||||
path = $"./{info[1].Split('/')[info[1].Split('/').Length - 1]}";
|
|
||||||
|
|
||||||
if (OperatingSystem.WINDOWS == Functions.GetOperatingSystem())
|
|
||||||
{
|
|
||||||
await ServerCom.DownloadFileAsync(info[1], path);
|
|
||||||
}
|
|
||||||
else if (OperatingSystem.LINUX == Functions.GetOperatingSystem())
|
|
||||||
{
|
|
||||||
var bar = new Utilities.ProgressBar(ProgressBarType.NO_END);
|
|
||||||
bar.Start();
|
|
||||||
await ServerCom.DownloadFileNoProgressAsync(info[1], path);
|
|
||||||
bar.Stop("Plugin Downloaded !");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Logger.WriteLine("\n");
|
|
||||||
|
|
||||||
// check requirements if any
|
|
||||||
|
|
||||||
if (info.Length == 3 && info[2] != string.Empty && info[2] != null)
|
|
||||||
{
|
|
||||||
Logger.WriteLine($"Downloading requirements for plugin : {name}");
|
|
||||||
|
|
||||||
var lines = await ServerCom.ReadTextFromURL(info[2]);
|
|
||||||
|
|
||||||
foreach (var line in lines)
|
|
||||||
{
|
|
||||||
if (!(line.Length > 0 && line.Contains(",")))
|
|
||||||
continue;
|
|
||||||
var split = line.Split(',');
|
|
||||||
Logger.WriteLine($"\nDownloading item: {split[1]}");
|
|
||||||
if (File.Exists("./" + split[1])) File.Delete("./" + split[1]);
|
|
||||||
if (OperatingSystem.WINDOWS == Functions.GetOperatingSystem())
|
|
||||||
{
|
|
||||||
await ServerCom.DownloadFileAsync(split[0], "./" + split[1]);
|
|
||||||
}
|
|
||||||
else if (OperatingSystem.LINUX == Functions.GetOperatingSystem())
|
|
||||||
{
|
|
||||||
var bar = new Utilities.ProgressBar(ProgressBarType.NO_END);
|
|
||||||
bar.Start();
|
|
||||||
await ServerCom.DownloadFileNoProgressAsync(split[0], "./" + split[1]);
|
|
||||||
bar.Stop("Item downloaded !");
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.WriteLine();
|
|
||||||
if (split[0].EndsWith(".pak"))
|
|
||||||
{
|
|
||||||
File.Move("./" + split[1], "./Data/PAKS/" + split[1], true);
|
|
||||||
}
|
|
||||||
else if (split[0].EndsWith(".zip") || split[0].EndsWith(".pkg"))
|
|
||||||
{
|
|
||||||
Logger.WriteLine($"Extracting {split[1]} ...");
|
|
||||||
var bar = new Utilities.ProgressBar(
|
|
||||||
ProgressBarType.NO_END);
|
|
||||||
bar.Start();
|
|
||||||
await ArchiveManager.ExtractArchive("./" + split[1], "./", null,
|
|
||||||
UnzipProgressType.PercentageFromTotalSize);
|
|
||||||
bar.Stop("Extracted");
|
|
||||||
Logger.WriteLine("\n");
|
|
||||||
File.Delete("./" + split[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
var ver = await ServerCom.GetVersionOfPackageFromWeb(name);
|
|
||||||
if (ver is null) throw new Exception("Incorrect version");
|
|
||||||
await Config.Plugins.SetVersionAsync(name, ver);
|
|
||||||
|
|
||||||
isDownloading = false;
|
|
||||||
|
|
||||||
await ExecuteCommad("localload " + name);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
AddCommand("value", "read value from VariableStack", "value [key]", args =>
|
|
||||||
{
|
|
||||||
if (args.Length != 2)
|
|
||||||
return;
|
|
||||||
if (!Config.Variables.Exists(args[1]))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var data = Config.Variables.GetValue(args[1]);
|
|
||||||
Logger.WriteLine($"{args[1]} => {data}");
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
AddCommand("add", "add variable to the system variables", "add [key] [value] [isReadOnly=true/false]", args =>
|
|
||||||
{
|
|
||||||
if (args.Length < 4)
|
|
||||||
return;
|
|
||||||
var key = args[1];
|
|
||||||
var value = args[2];
|
|
||||||
var isReadOnly = args[3].Equals("true", StringComparison.CurrentCultureIgnoreCase);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Config.Variables.Add(key, value, isReadOnly);
|
|
||||||
Logger.WriteLine($"Updated config file with the following command: {args[1]} => {value}");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.WriteLine(ex.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
AddCommand("remv", "remove variable from system variables", "remv [key]", args =>
|
|
||||||
{
|
|
||||||
if (args.Length < 2)
|
|
||||||
return;
|
|
||||||
Config.Variables.RemoveKey(args[1]);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
AddCommand("sd", "Shuts down the discord bot", async () =>
|
|
||||||
{
|
|
||||||
if (client is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Settings.sqlDatabase.Stop();
|
|
||||||
await client.StopAsync();
|
|
||||||
await client.DisposeAsync();
|
|
||||||
await Task.Delay(1000);
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
AddCommand("import", "Load an external command", "import [pluginName]", async args =>
|
|
||||||
{
|
|
||||||
if (args.Length <= 1) return;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var pName = string.Join(' ', args, 1, args.Length - 1);
|
|
||||||
using (var client = new HttpClient())
|
|
||||||
{
|
|
||||||
var url = (await manager.GetPluginLinkByName(pName))[1];
|
|
||||||
if (url is null) throw new Exception($"Invalid plugin name {pName}.");
|
|
||||||
var s = await client.GetStreamAsync(url);
|
|
||||||
var str = new MemoryStream();
|
|
||||||
await s.CopyToAsync(str);
|
|
||||||
var asmb = Assembly.Load(str.ToArray());
|
|
||||||
|
|
||||||
await PluginLoader.LoadPluginFromAssembly(asmb, this.client);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.WriteLine(ex.Message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
AddCommand("localload", "Load a local command", "local [pluginName]", async args =>
|
|
||||||
{
|
|
||||||
if (args.Length <= 1) return;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var pName = string.Join(' ', args, 1, args.Length - 1);
|
|
||||||
var asmb = Assembly.LoadFile(Path.GetFullPath("./Data/Plugins/" + pName + ".dll"));
|
|
||||||
|
|
||||||
await PluginLoader.LoadPluginFromAssembly(asmb, this.client);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.WriteLine(ex.Message);
|
|
||||||
Logger.WriteErrFile(ex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
AddCommand("remplug", "Remove a plugin", "remplug [plugName]", async args =>
|
|
||||||
{
|
|
||||||
if (args.Length <= 1) return;
|
|
||||||
|
|
||||||
isDownloading = true;
|
|
||||||
var plugName = string.Join(' ', args, 1, args.Length - 1);
|
|
||||||
if (pluginsLoaded)
|
|
||||||
{
|
|
||||||
if (Functions.GetOperatingSystem() == OperatingSystem.WINDOWS)
|
|
||||||
{
|
|
||||||
Process.Start("DiscordBot.exe", $"/remplug {plugName}");
|
|
||||||
await Task.Delay(100);
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Process.Start("./DiscordBot", $"/remplug {plugName}");
|
|
||||||
await Task.Delay(100);
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
isDownloading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var location = $"./Data/Plugins/{plugName}.dll";
|
|
||||||
|
|
||||||
if (!File.Exists(location))
|
|
||||||
{
|
|
||||||
Logger.WriteLine("The plugin does not exist");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
File.Delete(location);
|
|
||||||
|
|
||||||
Logger.WriteLine("Removed the plugin DLL. Checking for other files ...");
|
|
||||||
|
|
||||||
var info = await manager.GetPluginLinkByName(plugName);
|
|
||||||
if (info[2] != string.Empty)
|
|
||||||
{
|
|
||||||
var lines = await ServerCom.ReadTextFromURL(info[2]);
|
|
||||||
foreach (var line in lines)
|
|
||||||
{
|
|
||||||
if (!(line.Length > 0 && line.Contains(",")))
|
|
||||||
continue;
|
|
||||||
var split = line.Split(',');
|
|
||||||
if (File.Exists("./" + split[1]))
|
|
||||||
File.Delete("./" + split[1]);
|
|
||||||
|
|
||||||
|
|
||||||
Logger.WriteLine("Removed: " + split[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Directory.Exists($"./Data/Plugins/{plugName}"))
|
|
||||||
Directory.Delete($"./Data/Plugins/{plugName}", true);
|
|
||||||
|
|
||||||
if (Directory.Exists(plugName))
|
|
||||||
Directory.Delete(plugName, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
isDownloading = false;
|
|
||||||
Logger.WriteLine(plugName + " has been successfully deleted !");
|
|
||||||
});
|
|
||||||
|
|
||||||
AddCommand("reload", "Reload the bot with all plugins", () =>
|
|
||||||
{
|
|
||||||
|
|
||||||
if (Functions.GetOperatingSystem() == OperatingSystem.WINDOWS)
|
|
||||||
{
|
|
||||||
Process.Start("DiscordBot.exe", "lp");
|
|
||||||
HandleCommand("sd");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//HandleCommand("sd");
|
|
||||||
Console.WriteLine("This command can not be used outside of Windows yet. Please restart the bot using the manual way");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//AddCommand("");
|
|
||||||
|
|
||||||
//Sort the commands by name
|
|
||||||
commandList.Sort((x, y) => x.CommandName.CompareTo(y.CommandName));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AddCommand(string command, string description, string usage, Action<string[]> action)
|
|
||||||
{
|
|
||||||
commandList.Add(new ConsoleCommand
|
|
||||||
{ CommandName = command, Description = description, Action = action, Usage = usage });
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
|
||||||
Utilities.WriteColorText($"Command &r{command} &cadded to the list of commands");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AddCommand(string command, string description, Action action)
|
|
||||||
{
|
|
||||||
AddCommand(command, description, command, args => action());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void RemoveCommand(string command)
|
|
||||||
{
|
|
||||||
commandList.RemoveAll(x => x.CommandName == command);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool CommandExists(string command)
|
|
||||||
{
|
|
||||||
return GetCommand(command) is not null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ConsoleCommand? GetCommand(string command)
|
|
||||||
{
|
|
||||||
return commandList.FirstOrDefault(t => t.CommandName == command);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* public static async Task ExecuteSpecialCommand(string command)
|
|
||||||
{
|
|
||||||
if (!command.StartsWith("_")) return;
|
|
||||||
|
|
||||||
string[] args = command.Split(' ');
|
|
||||||
foreach (var item in commandList)
|
|
||||||
if (item.CommandName == args[0])
|
|
||||||
{
|
|
||||||
Logger.WriteLine();
|
|
||||||
item.Action(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public static async Task ExecuteCommad(string command)
|
|
||||||
{
|
|
||||||
if (!Logger.isConsole)
|
|
||||||
throw new Exception("Can not use console based commands on non console based application !");
|
|
||||||
var args = command.Split(' ');
|
|
||||||
foreach (var item in commandList.ToList())
|
|
||||||
if (item.CommandName == args[0])
|
|
||||||
{
|
|
||||||
item.Action.Invoke(args);
|
|
||||||
while (isDownloading) await Task.Delay(1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool HandleCommand(string command, bool removeCommandExecution = true)
|
|
||||||
{
|
|
||||||
if (!Logger.isConsole)
|
|
||||||
throw new Exception("Can not use console based commands on non console based application !");
|
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
|
||||||
var args = command.Split(' ');
|
|
||||||
foreach (var item in commandList.ToList())
|
|
||||||
if (item.CommandName == args[0])
|
|
||||||
{
|
|
||||||
if (args[0].StartsWith("_"))
|
|
||||||
throw new Exception("This command is reserved for internal worker and can not be executed manually !");
|
|
||||||
|
|
||||||
if (Logger.isConsole)
|
|
||||||
if (removeCommandExecution)
|
|
||||||
{
|
|
||||||
Console.SetCursorPosition(0, Console.CursorTop - 1);
|
|
||||||
for (var i = 0; i < command.Length + 30; i++)
|
|
||||||
Logger.Write(" ");
|
|
||||||
Console.SetCursorPosition(0, Console.CursorTop);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.WriteLine();
|
|
||||||
item.Action(args);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
//Logger.WriteLine($"Executing: {args[0]} with the following parameters: {args.MergeStrings(1)}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
72
PluginManager/Loaders/ActionsLoader.cs
Normal file
72
PluginManager/Loaders/ActionsLoader.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
using PluginManager.Others;
|
||||||
|
|
||||||
|
namespace PluginManager.Loaders;
|
||||||
|
|
||||||
|
public class ActionsLoader
|
||||||
|
{
|
||||||
|
public delegate void ActionLoaded(string name, string typeName, bool success, Exception? e = null);
|
||||||
|
|
||||||
|
private readonly string actionExtension = "dll";
|
||||||
|
|
||||||
|
private readonly string actionFolder = @"./Data/Plugins/";
|
||||||
|
|
||||||
|
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_STARTUP)
|
||||||
|
await action.Execute(null);
|
||||||
|
|
||||||
|
ActionLoadedEvent?.Invoke(action.ActionName, type.Name, true);
|
||||||
|
actions.Add(action);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ActionLoadedEvent?.Invoke(type.Name, type.Name, false, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
using PluginManager.Others;
|
||||||
|
|
||||||
namespace PluginManager.Loaders;
|
namespace PluginManager.Loaders;
|
||||||
|
|
||||||
@@ -15,7 +17,7 @@ internal class LoaderArgs : EventArgs
|
|||||||
internal object? Plugin { get; init; }
|
internal object? Plugin { get; init; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class Loader<T>
|
internal class Loader
|
||||||
{
|
{
|
||||||
internal Loader(string path, string extension)
|
internal Loader(string path, string extension)
|
||||||
{
|
{
|
||||||
@@ -31,25 +33,38 @@ internal class Loader<T>
|
|||||||
|
|
||||||
internal event PluginLoadedEventHandler? PluginLoaded;
|
internal event PluginLoadedEventHandler? PluginLoaded;
|
||||||
|
|
||||||
internal List<T>? Load()
|
|
||||||
|
internal (List<DBEvent>?, List<DBCommand>?, List<DBSlashCommand>?) Load()
|
||||||
{
|
{
|
||||||
var list = new List<T>();
|
List<DBEvent> events = new();
|
||||||
|
List<DBSlashCommand> slashCommands = new();
|
||||||
|
List<DBCommand> commands = new();
|
||||||
|
|
||||||
if (!Directory.Exists(path))
|
if (!Directory.Exists(path))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
return null;
|
return (null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
var files = Directory.GetFiles(path, $"*.{extension}", SearchOption.AllDirectories);
|
var files = Directory.GetFiles(path, $"*.{extension}", SearchOption.AllDirectories);
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Assembly.LoadFrom(file);
|
Assembly.LoadFrom(file);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Config.Logger.Log("PluginName: " + new FileInfo(file).Name.Split('.')[0] + " not loaded", source: typeof(Loader), type: LogType.ERROR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (FileLoaded != null)
|
if (FileLoaded != null)
|
||||||
{
|
{
|
||||||
var args = new LoaderArgs
|
var args = new LoaderArgs
|
||||||
{
|
{
|
||||||
Exception = null,
|
Exception = null,
|
||||||
TypeName = nameof(T),
|
TypeName = null,
|
||||||
IsLoaded = false,
|
IsLoaded = false,
|
||||||
PluginName = new FileInfo(file).Name.Split('.')[0],
|
PluginName = new FileInfo(file).Name.Split('.')[0],
|
||||||
Plugin = null
|
Plugin = null
|
||||||
@@ -58,6 +73,15 @@ internal class Loader<T>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (LoadItems<DBEvent>(), LoadItems<DBCommand>(), LoadItems<DBSlashCommand>());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal List<T> LoadItems<T>()
|
||||||
|
{
|
||||||
|
List<T> list = new();
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var interfaceType = typeof(T);
|
var interfaceType = typeof(T);
|
||||||
@@ -81,7 +105,10 @@ internal class Loader<T>
|
|||||||
Exception = null,
|
Exception = null,
|
||||||
IsLoaded = true,
|
IsLoaded = true,
|
||||||
PluginName = type.FullName,
|
PluginName = type.FullName,
|
||||||
TypeName = nameof(T),
|
TypeName = typeof(T) == typeof(DBCommand) ? "DBCommand" :
|
||||||
|
typeof(T) == typeof(DBEvent) ? "DBEvent" :
|
||||||
|
typeof(T) == typeof(DBSlashCommand) ? "DBSlashCommand" :
|
||||||
|
null,
|
||||||
Plugin = plugin
|
Plugin = plugin
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -97,14 +124,17 @@ internal class Loader<T>
|
|||||||
TypeName = nameof(T)
|
TypeName = nameof(T)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.WriteErrFile(ex.ToString());
|
Config.Logger.Log(ex.Message, source: typeof(Loader), type: LogType.ERROR);
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,136 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
using PluginManager.Interfaces;
|
|
||||||
|
|
||||||
namespace PluginManager.Loaders
|
|
||||||
{
|
|
||||||
internal class LoaderV2
|
|
||||||
{
|
|
||||||
internal LoaderV2(string path, string extension)
|
|
||||||
{
|
|
||||||
this.path = path;
|
|
||||||
this.extension = extension;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private string path { get; }
|
|
||||||
private string extension { get; }
|
|
||||||
|
|
||||||
internal event FileLoadedEventHandler? FileLoaded;
|
|
||||||
|
|
||||||
internal event PluginLoadedEventHandler? PluginLoaded;
|
|
||||||
|
|
||||||
|
|
||||||
internal delegate void FileLoadedEventHandler(LoaderArgs args);
|
|
||||||
|
|
||||||
internal delegate void PluginLoadedEventHandler(LoaderArgs args);
|
|
||||||
|
|
||||||
|
|
||||||
internal (List<DBEvent>?, List<DBCommand>?, List<DBSlashCommand>?) Load()
|
|
||||||
{
|
|
||||||
|
|
||||||
List<DBEvent> events = new();
|
|
||||||
List<DBSlashCommand> slashCommands = new();
|
|
||||||
List<DBCommand> commands = new();
|
|
||||||
|
|
||||||
if (!Directory.Exists(path))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(path);
|
|
||||||
return (null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
var files = Directory.GetFiles(path, $"*.{extension}", SearchOption.AllDirectories);
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assembly.LoadFrom(file);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.WriteLine(ex.Message);
|
|
||||||
Logger.WriteLine("PluginName: " + new FileInfo(file).Name.Split('.')[0] + " not loaded");
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (FileLoaded != null)
|
|
||||||
{
|
|
||||||
var args = new LoaderArgs
|
|
||||||
{
|
|
||||||
Exception = null,
|
|
||||||
TypeName = null,
|
|
||||||
IsLoaded = false,
|
|
||||||
PluginName = new FileInfo(file).Name.Split('.')[0],
|
|
||||||
Plugin = null
|
|
||||||
};
|
|
||||||
FileLoaded.Invoke(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (LoadItems<DBEvent>(), LoadItems<DBCommand>(), LoadItems<DBSlashCommand>());
|
|
||||||
}
|
|
||||||
|
|
||||||
internal List<T> LoadItems<T>()
|
|
||||||
{
|
|
||||||
List<T> list = new();
|
|
||||||
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var interfaceType = typeof(T);
|
|
||||||
var types = AppDomain.CurrentDomain.GetAssemblies()
|
|
||||||
.SelectMany(a => a.GetTypes())
|
|
||||||
.Where(p => interfaceType.IsAssignableFrom(p) && p.IsClass)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
|
|
||||||
list.Clear();
|
|
||||||
foreach (var type in types)
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var plugin = (T)Activator.CreateInstance(type)!;
|
|
||||||
list.Add(plugin);
|
|
||||||
|
|
||||||
|
|
||||||
if (PluginLoaded != null)
|
|
||||||
PluginLoaded.Invoke(new LoaderArgs
|
|
||||||
{
|
|
||||||
Exception = null,
|
|
||||||
IsLoaded = true,
|
|
||||||
PluginName = type.FullName,
|
|
||||||
TypeName = typeof(T) == typeof(DBCommand) ? "DBCommand" : typeof(T) == typeof(DBEvent) ? "DBEvent" : "DBSlashCommand",
|
|
||||||
Plugin = plugin
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (PluginLoaded != null)
|
|
||||||
PluginLoaded.Invoke(new LoaderArgs
|
|
||||||
{
|
|
||||||
Exception = ex,
|
|
||||||
IsLoaded = false,
|
|
||||||
PluginName = type.FullName,
|
|
||||||
TypeName = nameof(T)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.WriteErrFile(ex.ToString());
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
|
||||||
using PluginManager.Interfaces;
|
using PluginManager.Interfaces;
|
||||||
using PluginManager.Online;
|
using PluginManager.Others;
|
||||||
using PluginManager.Online.Updates;
|
|
||||||
|
|
||||||
namespace PluginManager.Loaders;
|
namespace PluginManager.Loaders;
|
||||||
|
|
||||||
@@ -62,43 +58,40 @@ public class PluginLoader
|
|||||||
public static List<DBEvent>? Events { get; set; }
|
public static List<DBEvent>? Events { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of <see cref="DBSlashCommand"/> commands
|
/// A list of <see cref="DBSlashCommand" /> commands
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static List<DBSlashCommand>? SlashCommands { get; set; }
|
public static List<DBSlashCommand>? SlashCommands { get; set; }
|
||||||
|
|
||||||
|
public static int PluginsLoaded
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var count = 0;
|
||||||
|
if (Commands is not null)
|
||||||
|
count += Commands.Count;
|
||||||
|
if (Events is not null)
|
||||||
|
count += Events.Count;
|
||||||
|
if (SlashCommands is not null)
|
||||||
|
count += SlashCommands.Count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main mathod that is called to load all events
|
/// The main mathod that is called to load all events
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async void LoadPlugins()
|
public async void LoadPlugins()
|
||||||
{
|
{
|
||||||
//Check for updates in commands
|
|
||||||
foreach (var file in Directory.GetFiles("./Data/Plugins/", $"*.{pluginExtension}",
|
|
||||||
SearchOption.AllDirectories))
|
|
||||||
await Task.Run(async () =>
|
|
||||||
{
|
|
||||||
var name = new FileInfo(file).Name.Split('.')[0];
|
|
||||||
var version = await ServerCom.GetVersionOfPackageFromWeb(name);
|
|
||||||
if (version is null)
|
|
||||||
return;
|
|
||||||
if (Config.Plugins.GetVersion(name) is not null)
|
|
||||||
Config.Plugins.SetVersion(name, version);
|
|
||||||
|
|
||||||
if (await PluginUpdater.CheckForUpdates(name))
|
|
||||||
await PluginUpdater.Download(name);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
//Load all plugins
|
//Load all plugins
|
||||||
|
|
||||||
Commands = new List<DBCommand>();
|
Commands = new List<DBCommand>();
|
||||||
Events = new List<DBEvent>();
|
Events = new List<DBEvent>();
|
||||||
SlashCommands = new List<DBSlashCommand>();
|
SlashCommands = new List<DBSlashCommand>();
|
||||||
|
|
||||||
Logger.WriteLogFile("Starting plugin loader ... Client: " + _client.CurrentUser.Username);
|
Config.Logger.Log("Starting plugin loader ... Client: " + _client.CurrentUser.Username, source: typeof(PluginLoader), type: LogType.INFO);
|
||||||
Logger.WriteLine("Loading plugins");
|
|
||||||
|
|
||||||
var loader = new LoaderV2("./Data/Plugins", "dll");
|
var loader = new Loader("./Data/Plugins", "dll");
|
||||||
loader.FileLoaded += (args) => Logger.WriteLogFile($"{args.PluginName} file Loaded");
|
loader.FileLoaded += args => Config.Logger.Log($"{args.PluginName} file Loaded", source: typeof(PluginLoader), type: LogType.INFO);
|
||||||
loader.PluginLoaded += Loader_PluginLoaded;
|
loader.PluginLoaded += Loader_PluginLoaded;
|
||||||
var res = loader.Load();
|
var res = loader.Load();
|
||||||
Events = res.Item1;
|
Events = res.Item1;
|
||||||
@@ -108,7 +101,6 @@ public class PluginLoader
|
|||||||
|
|
||||||
private async void Loader_PluginLoaded(LoaderArgs args)
|
private async void Loader_PluginLoaded(LoaderArgs args)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch (args.TypeName)
|
switch (args.TypeName)
|
||||||
{
|
{
|
||||||
case "DBCommand":
|
case "DBCommand":
|
||||||
@@ -124,60 +116,67 @@ public class PluginLoader
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.WriteLine(ex.ToString());
|
Config.Logger.Log(ex.Message, source: typeof(PluginLoader), type: LogType.ERROR);
|
||||||
Logger.WriteLine("Plugin: " + args.PluginName);
|
|
||||||
Logger.WriteLine("Type: " + args.TypeName);
|
|
||||||
Logger.WriteLine("IsLoaded: " + args.IsLoaded);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "DBSlashCommand":
|
case "DBSlashCommand":
|
||||||
if (args.IsLoaded)
|
if (args.IsLoaded)
|
||||||
{
|
{
|
||||||
var slash = (DBSlashCommand)args.Plugin;
|
var slash = (DBSlashCommand)args.Plugin;
|
||||||
SlashCommandBuilder builder = new SlashCommandBuilder();
|
var builder = new SlashCommandBuilder();
|
||||||
builder.WithName(slash.Name);
|
builder.WithName(slash.Name);
|
||||||
builder.WithDescription(slash.Description);
|
builder.WithDescription(slash.Description);
|
||||||
builder.WithDMPermission(slash.canUseDM);
|
builder.WithDMPermission(slash.canUseDM);
|
||||||
builder.Options = slash.Options;
|
builder.Options = slash.Options;
|
||||||
|
|
||||||
onSLSHLoad?.Invoke(((DBSlashCommand)args.Plugin!).Name, args.TypeName, args.IsLoaded, args.Exception);
|
onSLSHLoad?.Invoke(((DBSlashCommand)args.Plugin!).Name, args.TypeName, args.IsLoaded,
|
||||||
|
args.Exception);
|
||||||
await _client.CreateGlobalApplicationCommandAsync(builder.Build());
|
await _client.CreateGlobalApplicationCommandAsync(builder.Build());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task LoadPluginFromAssembly(Assembly asmb, DiscordSocketClient client)
|
public static async Task LoadPluginFromAssembly(Assembly asmb, DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
var types = asmb.GetTypes();
|
var types = asmb.GetTypes();
|
||||||
foreach (var type in types)
|
foreach (var type in types)
|
||||||
|
try
|
||||||
|
{
|
||||||
if (type.IsClass && typeof(DBEvent).IsAssignableFrom(type))
|
if (type.IsClass && typeof(DBEvent).IsAssignableFrom(type))
|
||||||
{
|
{
|
||||||
var instance = (DBEvent)Activator.CreateInstance(type);
|
var instance = (DBEvent)Activator.CreateInstance(type);
|
||||||
instance.Start(client);
|
instance.Start(client);
|
||||||
PluginLoader.Events.Add(instance);
|
Events.Add(instance);
|
||||||
Logger.WriteLine($"[EVENT] Loaded external {type.FullName}!");
|
Config.Logger.Log($"[EVENT] Loaded external {type.FullName}!", source: typeof(PluginLoader));
|
||||||
}
|
}
|
||||||
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
|
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
|
||||||
{
|
{
|
||||||
var instance = (DBCommand)Activator.CreateInstance(type);
|
var instance = (DBCommand)Activator.CreateInstance(type);
|
||||||
PluginLoader.Commands.Add(instance);
|
Commands.Add(instance);
|
||||||
Logger.WriteLine($"[CMD] Instance: {type.FullName} loaded !");
|
Config.Logger.Log($"[CMD] Instance: {type.FullName} loaded !", source: typeof(PluginLoader));
|
||||||
}
|
}
|
||||||
else if (type.IsClass && typeof(DBSlashCommand).IsAssignableFrom(type))
|
else if (type.IsClass && typeof(DBSlashCommand).IsAssignableFrom(type))
|
||||||
{
|
{
|
||||||
var instance = (DBSlashCommand)Activator.CreateInstance(type);
|
var instance = (DBSlashCommand)Activator.CreateInstance(type);
|
||||||
SlashCommandBuilder builder = new SlashCommandBuilder();
|
var builder = new SlashCommandBuilder();
|
||||||
builder.WithName(instance.Name);
|
builder.WithName(instance.Name);
|
||||||
builder.WithDescription(instance.Description);
|
builder.WithDescription(instance.Description);
|
||||||
builder.WithDMPermission(instance.canUseDM);
|
builder.WithDMPermission(instance.canUseDM);
|
||||||
builder.Options = instance.Options;
|
builder.Options = instance.Options;
|
||||||
|
|
||||||
await client.CreateGlobalApplicationCommandAsync(builder.Build());
|
await client.CreateGlobalApplicationCommandAsync(builder.Build());
|
||||||
PluginLoader.SlashCommands.Add(instance);
|
SlashCommands.Add(instance);
|
||||||
Logger.WriteLine($"[SLASH] Instance: {type.FullName} loaded !");
|
Config.Logger.Log($"[SLASH] Instance: {type.FullName} loaded !", source: typeof(PluginLoader));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
//Console.WriteLine(ex.Message);
|
||||||
|
Config.Logger.Log(ex.Message, source: typeof(PluginLoader), type: LogType.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
using Discord;
|
|
||||||
|
|
||||||
namespace PluginManager
|
|
||||||
{
|
|
||||||
public static class Logger
|
|
||||||
{
|
|
||||||
|
|
||||||
public static bool isConsole { get; private set; }
|
|
||||||
private static bool isInitialized;
|
|
||||||
|
|
||||||
private static string? logFolder;
|
|
||||||
private static string? errFolder;
|
|
||||||
|
|
||||||
public static void Initialize(bool console)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (isInitialized) throw new Exception("Logger is already initialized");
|
|
||||||
|
|
||||||
if (!Config.Variables.Exists("LogFolder"))
|
|
||||||
Config.Variables.Add("LogFolder", "./Data/Output/Logs/");
|
|
||||||
|
|
||||||
if (!Config.Variables.Exists("ErrorFolder"))
|
|
||||||
Config.Variables.Add("ErrorFolder", "./Data/Output/Errors/");
|
|
||||||
|
|
||||||
isInitialized = true;
|
|
||||||
logFolder = Config.Variables.GetValue("LogFolder");
|
|
||||||
errFolder = Config.Variables.GetValue("ErrorFolder");
|
|
||||||
isConsole = console;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public delegate void LogEventHandler(string Message);
|
|
||||||
public static event LogEventHandler LogEvent;
|
|
||||||
|
|
||||||
public static void Log(string Message)
|
|
||||||
{
|
|
||||||
if (!isInitialized) throw new Exception("Logger is not initialized");
|
|
||||||
LogEvent?.Invoke(Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Log(string Message, params object[] Args)
|
|
||||||
{
|
|
||||||
if (!isInitialized) throw new Exception("Logger is not initialized");
|
|
||||||
LogEvent?.Invoke(string.Format(Message, Args));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Log(IMessage message, bool newLine)
|
|
||||||
{
|
|
||||||
if (!isInitialized) throw new Exception("Logger is not initialized");
|
|
||||||
LogEvent?.Invoke(message.Content);
|
|
||||||
if (newLine)
|
|
||||||
LogEvent?.Invoke("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WriteLine(string? message)
|
|
||||||
{
|
|
||||||
if (!isInitialized) throw new Exception("Logger is not initialized");
|
|
||||||
if (message is not null)
|
|
||||||
LogEvent?.Invoke(message + '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LogError(System.Exception ex)
|
|
||||||
{
|
|
||||||
if (!isInitialized) throw new Exception("Logger is not initialized");
|
|
||||||
string message = "[ERROR]" + ex.Message;
|
|
||||||
LogEvent?.Invoke(message + '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void LogError(string? message)
|
|
||||||
{
|
|
||||||
if (!isInitialized) throw new Exception("Logger is not initialized");
|
|
||||||
if (message is not null)
|
|
||||||
LogEvent?.Invoke("[ERROR]" + message + '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void WriteLine()
|
|
||||||
{
|
|
||||||
if (!isInitialized) throw new Exception("Logger is not initialized");
|
|
||||||
LogEvent?.Invoke("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Write(string message)
|
|
||||||
{
|
|
||||||
if (!isInitialized) throw new Exception("Logger is not initialized");
|
|
||||||
LogEvent?.Invoke(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void Write<T>(T c)
|
|
||||||
{
|
|
||||||
if (!isInitialized) throw new Exception("Logger is not initialized");
|
|
||||||
LogEvent?.Invoke($"{c}");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Write logs to file
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="LogMessage">The message to be wrote</param>
|
|
||||||
public static void WriteLogFile(string LogMessage)
|
|
||||||
{
|
|
||||||
if (!isInitialized) throw new Exception("Logger is not initialized");
|
|
||||||
var logsPath = logFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Log.txt";
|
|
||||||
Directory.CreateDirectory(logFolder);
|
|
||||||
File.AppendAllTextAsync(logsPath, LogMessage + " \n").Wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Write error to file
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ErrMessage">The message to be wrote</param>
|
|
||||||
public static void WriteErrFile(string ErrMessage)
|
|
||||||
{
|
|
||||||
if (!isInitialized) throw new Exception("Logger is not initialized");
|
|
||||||
var errPath = errFolder +
|
|
||||||
$"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Error.txt";
|
|
||||||
Directory.CreateDirectory(errFolder);
|
|
||||||
File.AppendAllText(errPath, ErrMessage + " \n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WriteErrFile(this Exception ex)
|
|
||||||
{
|
|
||||||
if (!isInitialized) throw new Exception("Logger is not initialized");
|
|
||||||
WriteErrFile(ex.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,6 @@ using System.IO;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using PluginManager.Others;
|
using PluginManager.Others;
|
||||||
|
|
||||||
namespace PluginManager.Online.Helpers;
|
namespace PluginManager.Online.Helpers;
|
||||||
@@ -19,7 +18,8 @@ internal static class OnlineFunctions
|
|||||||
/// <param name="progress">The <see cref="IProgress{T}" /> that is used to track the download progress</param>
|
/// <param name="progress">The <see cref="IProgress{T}" /> that is used to track the download progress</param>
|
||||||
/// <param name="cancellation">The cancellation token</param>
|
/// <param name="cancellation">The cancellation token</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal static async Task DownloadFileAsync(this HttpClient client, string url, Stream destination,
|
internal static async Task DownloadFileAsync(
|
||||||
|
this HttpClient client, string url, Stream destination,
|
||||||
IProgress<float>? progress = null,
|
IProgress<float>? progress = null,
|
||||||
IProgress<long>? downloadedBytes = null, int bufferSize = 81920,
|
IProgress<long>? downloadedBytes = null, int bufferSize = 81920,
|
||||||
CancellationToken cancellation = default)
|
CancellationToken cancellation = default)
|
||||||
@@ -35,20 +35,25 @@ internal static class OnlineFunctions
|
|||||||
if (progress == null || !contentLength.HasValue)
|
if (progress == null || !contentLength.HasValue)
|
||||||
{
|
{
|
||||||
await download.CopyToAsync(destination, cancellation);
|
await download.CopyToAsync(destination, cancellation);
|
||||||
|
if(!contentLength.HasValue)
|
||||||
|
progress?.Report(100f);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert absolute progress (bytes downloaded) into relative progress (0% - 100%)
|
// Convert absolute progress (bytes downloaded) into relative progress (0% - 100%)
|
||||||
var relativeProgress = new Progress<long>(totalBytes =>
|
// total ... 100%
|
||||||
|
// downloaded ... x%
|
||||||
|
// x = downloaded * 100 / total => x = downloaded / total * 100
|
||||||
|
var relativeProgress = new Progress<long>(totalBytesDownloaded =>
|
||||||
{
|
{
|
||||||
progress?.Report((float)totalBytes / contentLength.Value * 100);
|
progress?.Report(totalBytesDownloaded / (float)contentLength.Value * 100);
|
||||||
downloadedBytes?.Report(totalBytes);
|
downloadedBytes?.Report(totalBytesDownloaded);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Use extension method to report progress while downloading
|
// Use extension method to report progress while downloading
|
||||||
await download.CopyToOtherStreamAsync(destination, bufferSize, relativeProgress, cancellation);
|
await download.CopyToOtherStreamAsync(destination, bufferSize, relativeProgress, cancellation);
|
||||||
progress.Report(100);
|
progress.Report(100f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,11 +12,25 @@ public class VersionString
|
|||||||
{
|
{
|
||||||
var data = version.Split('.');
|
var data = version.Split('.');
|
||||||
try
|
try
|
||||||
|
{
|
||||||
|
if (data.Length == 3)
|
||||||
{
|
{
|
||||||
PackageVersionID = int.Parse(data[0]);
|
PackageVersionID = int.Parse(data[0]);
|
||||||
PackageMainVersion = int.Parse(data[1]);
|
PackageMainVersion = int.Parse(data[1]);
|
||||||
PackageCheckVersion = int.Parse(data[2]);
|
PackageCheckVersion = int.Parse(data[2]);
|
||||||
}
|
}
|
||||||
|
else if (data.Length == 4)
|
||||||
|
{
|
||||||
|
// ignore the first item data[0]
|
||||||
|
PackageVersionID = int.Parse(data[1]);
|
||||||
|
PackageMainVersion = int.Parse(data[2]);
|
||||||
|
PackageCheckVersion = int.Parse(data[3]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Invalid version string");
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine(version);
|
Console.WriteLine(version);
|
||||||
@@ -24,6 +38,25 @@ public class VersionString
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool Equals(VersionString other)
|
||||||
|
{
|
||||||
|
return PackageCheckVersion == other.PackageCheckVersion && PackageMainVersion == other.PackageMainVersion &&
|
||||||
|
PackageVersionID == other.PackageVersionID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj)) return false;
|
||||||
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
|
if (obj.GetType() != GetType()) return false;
|
||||||
|
return Equals((VersionString)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(PackageCheckVersion, PackageMainVersion, PackageVersionID);
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return "{PackageID: " + PackageVersionID + ", PackageVersion: " + PackageMainVersion +
|
return "{PackageID: " + PackageVersionID + ", PackageVersion: " + PackageMainVersion +
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using PluginManager.Online.Helpers;
|
using PluginManager.Online.Helpers;
|
||||||
using PluginManager.Others;
|
using PluginManager.Others;
|
||||||
|
|
||||||
using OperatingSystem = PluginManager.Others.OperatingSystem;
|
using OperatingSystem = PluginManager.Others.OperatingSystem;
|
||||||
|
|
||||||
namespace PluginManager.Online;
|
namespace PluginManager.Online;
|
||||||
@@ -14,10 +12,21 @@ public class PluginsManager
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Plugin Manager constructor
|
/// The Plugin Manager constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="link">The link to the file where all plugins are stored</param>
|
/// <param name="plink">The link to the file where all plugins are stored</param>
|
||||||
public PluginsManager(string link)
|
/// <param name="vlink">The link to the file where all plugin versions are stored</param>
|
||||||
|
public PluginsManager(string plink, string vlink)
|
||||||
{
|
{
|
||||||
PluginsLink = link;
|
PluginsLink = plink;
|
||||||
|
VersionsLink = vlink;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The default Plugin Manager constructor. It uses the default links.
|
||||||
|
/// </summary>
|
||||||
|
public PluginsManager()
|
||||||
|
{
|
||||||
|
PluginsLink = "https://raw.githubusercontent.com/andreitdr/SethPlugins/releases/PluginsList";
|
||||||
|
VersionsLink = "https://raw.githubusercontent.com/andreitdr/SethPlugins/releases/Versions";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -25,12 +34,15 @@ public class PluginsManager
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string PluginsLink { get; }
|
public string PluginsLink { get; }
|
||||||
|
|
||||||
|
public string VersionsLink { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The method to load all plugins
|
/// The method to load all plugins
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task ListAvailablePlugins()
|
public async Task<List<string[]>> GetAvailablePlugins()
|
||||||
{
|
{
|
||||||
|
// Config.Logger.Log("Got data from " + VersionsLink, this, LogLevel.INFO);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var list = await ServerCom.ReadTextFromURL(PluginsLink);
|
var list = await ServerCom.ReadTextFromURL(PluginsLink);
|
||||||
@@ -40,16 +52,12 @@ public class PluginsManager
|
|||||||
var op = Functions.GetOperatingSystem();
|
var op = Functions.GetOperatingSystem();
|
||||||
|
|
||||||
var len = lines.Length;
|
var len = lines.Length;
|
||||||
string[] titles = { "Name", "Description", "Type", "Version" };
|
|
||||||
data.Add(new[] { "-", "-", "-", "-" });
|
|
||||||
data.Add(titles);
|
|
||||||
data.Add(new[] { "-", "-", "-", "-" });
|
|
||||||
for (var i = 0; i < len; i++)
|
for (var i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
if (lines[i].Length <= 2)
|
if (lines[i].Length <= 2)
|
||||||
continue;
|
continue;
|
||||||
var content = lines[i].Split(',');
|
var content = lines[i].Split(',');
|
||||||
var display = new string[titles.Length];
|
var display = new string[4]; // 4 columns
|
||||||
if (op == OperatingSystem.WINDOWS)
|
if (op == OperatingSystem.WINDOWS)
|
||||||
{
|
{
|
||||||
if (content[4].Contains("Windows"))
|
if (content[4].Contains("Windows"))
|
||||||
@@ -58,7 +66,7 @@ public class PluginsManager
|
|||||||
display[1] = content[1];
|
display[1] = content[1];
|
||||||
display[2] = content[2];
|
display[2] = content[2];
|
||||||
display[3] =
|
display[3] =
|
||||||
(await ServerCom.GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0"))
|
(await GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0"))
|
||||||
.ToShortString();
|
.ToShortString();
|
||||||
data.Add(display);
|
data.Add(display);
|
||||||
}
|
}
|
||||||
@@ -71,22 +79,39 @@ public class PluginsManager
|
|||||||
display[1] = content[1];
|
display[1] = content[1];
|
||||||
display[2] = content[2];
|
display[2] = content[2];
|
||||||
display[3] =
|
display[3] =
|
||||||
(await ServerCom.GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0"))
|
(await GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0"))
|
||||||
.ToShortString();
|
.ToShortString();
|
||||||
data.Add(display);
|
data.Add(display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return data;
|
||||||
data.Add(new[] { "-", "-", "-", "-" });
|
|
||||||
|
|
||||||
Utilities.FormatAndAlignTable(data, TableFormat.CENTER_EACH_COLUMN_BASED);
|
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
Logger.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message);
|
Config.Logger.Log(message: "Failed to execute command: listplugs\nReason: " + exception.Message, source: typeof(PluginsManager), type: LogType.ERROR );
|
||||||
Logger.WriteErrFile(exception.ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<VersionString?> GetVersionOfPackageFromWeb(string pakName)
|
||||||
|
{
|
||||||
|
var data = await ServerCom.ReadTextFromURL(VersionsLink);
|
||||||
|
foreach (var item in data)
|
||||||
|
{
|
||||||
|
if (item.StartsWith("#"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var split = item.Split(',');
|
||||||
|
if (split[0] == pakName)
|
||||||
|
{
|
||||||
|
// Config.Logger.Log("Searched for " + pakName + " and found " + split[1] + " as version.", LogLevel.INFO);
|
||||||
|
return new VersionString(split[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -104,7 +129,7 @@ public class PluginsManager
|
|||||||
for (var i = 0; i < len; i++)
|
for (var i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
var contents = lines[i].Split(',');
|
var contents = lines[i].Split(',');
|
||||||
if (contents[0] == name)
|
if (contents[0].ToLowerInvariant() == name.ToLowerInvariant())
|
||||||
{
|
{
|
||||||
if (contents.Length == 6)
|
if (contents.Length == 6)
|
||||||
return new[] { contents[2], contents[3], contents[5] };
|
return new[] { contents[2], contents[3], contents[5] };
|
||||||
@@ -116,10 +141,9 @@ public class PluginsManager
|
|||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
Logger.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message);
|
Config.Logger.Log("Failed to execute command: plugin list\nReason: " + exception.Message, source: typeof(PluginsManager), type: LogType.ERROR);
|
||||||
Logger.WriteErrFile(exception.ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new string[] { null!, null!, null! };
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
using PluginManager.Online.Helpers;
|
using PluginManager.Online.Helpers;
|
||||||
using PluginManager.Others;
|
|
||||||
|
|
||||||
namespace PluginManager.Online;
|
namespace PluginManager.Online;
|
||||||
|
|
||||||
@@ -32,8 +29,9 @@ public static class ServerCom
|
|||||||
/// <param name="location">The location where to store the downloaded data</param>
|
/// <param name="location">The location where to store the downloaded data</param>
|
||||||
/// <param name="progress">The <see cref="IProgress{T}" /> to track the download</param>
|
/// <param name="progress">The <see cref="IProgress{T}" /> to track the download</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static async Task DownloadFileAsync(string URL, string location, IProgress<float> progress,
|
public static async Task DownloadFileAsync(
|
||||||
IProgress<long>? downloadedBytes = null)
|
string URL, string location, IProgress<float> progress,
|
||||||
|
IProgress<long>? downloadedBytes)
|
||||||
{
|
{
|
||||||
using (var client = new HttpClient())
|
using (var client = new HttpClient())
|
||||||
{
|
{
|
||||||
@@ -46,69 +44,9 @@ public static class ServerCom
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public static async Task DownloadFileAsync(string URl, string location, IProgress<float> progress)
|
||||||
/// Download file from url
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="URL">The url to the file</param>
|
|
||||||
/// <param name="location">The location where to store the downloaded data</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task DownloadFileAsync(string URL, string location)
|
|
||||||
{
|
{
|
||||||
var isDownloading = true;
|
await DownloadFileAsync(URl, location, progress, null);
|
||||||
float c_progress = 0;
|
|
||||||
|
|
||||||
var pbar = new Utilities.ProgressBar(ProgressBarType.NORMAL) { Max = 100f, NoColor = true };
|
|
||||||
|
|
||||||
IProgress<float> progress = new Progress<float>(percent => { c_progress = percent; });
|
|
||||||
|
|
||||||
|
|
||||||
var updateProgressBarTask = new Task(() =>
|
|
||||||
{
|
|
||||||
while (isDownloading)
|
|
||||||
{
|
|
||||||
pbar.Update(c_progress);
|
|
||||||
if (c_progress == 100f)
|
|
||||||
break;
|
|
||||||
Thread.Sleep(500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
new Thread(updateProgressBarTask.Start).Start();
|
|
||||||
await DownloadFileAsync(URL, location, progress);
|
|
||||||
|
|
||||||
|
|
||||||
c_progress = pbar.Max;
|
|
||||||
pbar.Update(100f);
|
|
||||||
isDownloading = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task DownloadFileNoProgressAsync(string URL, string location)
|
|
||||||
{
|
|
||||||
IProgress<float> progress = new Progress<float>();
|
|
||||||
await DownloadFileAsync(URL, location, progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static VersionString? GetVersionOfPackage(string pakName)
|
|
||||||
{
|
|
||||||
if (Config.Plugins.GetVersion(pakName) is null)
|
|
||||||
return null;
|
|
||||||
return new VersionString(Config.Plugins.GetVersion(pakName));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<VersionString?> GetVersionOfPackageFromWeb(string pakName)
|
|
||||||
{
|
|
||||||
var url = "https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Versions";
|
|
||||||
var data = await ReadTextFromURL(url);
|
|
||||||
foreach (var item in data)
|
|
||||||
{
|
|
||||||
if (item.StartsWith("#"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
string[] split = item.Split(',');
|
|
||||||
if (split[0] == pakName)
|
|
||||||
return new VersionString(split[1]);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
using PluginManager.Items;
|
|
||||||
using PluginManager.Others;
|
|
||||||
|
|
||||||
namespace PluginManager.Online.Updates;
|
|
||||||
|
|
||||||
public class PluginUpdater
|
|
||||||
{
|
|
||||||
public static async Task<bool> CheckForUpdates(string pakName)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var webV = await ServerCom.GetVersionOfPackageFromWeb(pakName);
|
|
||||||
var local = ServerCom.GetVersionOfPackage(pakName);
|
|
||||||
|
|
||||||
if (local is null) return true;
|
|
||||||
if (webV is null) return false;
|
|
||||||
|
|
||||||
if (webV == local) return false;
|
|
||||||
if (webV > local) return true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<List<string>> GetInfo(string pakName)
|
|
||||||
{
|
|
||||||
|
|
||||||
Utilities.WriteColorText("An update was found for &g" + pakName + "&c. Version: &r" +
|
|
||||||
(await ServerCom.GetVersionOfPackageFromWeb(pakName))?.ToShortString() +
|
|
||||||
"&c. Current Version: &y" +
|
|
||||||
ServerCom.GetVersionOfPackage(pakName)?.ToShortString());
|
|
||||||
|
|
||||||
List<string> fileInfo = await ServerCom.ReadTextFromURL("");
|
|
||||||
return fileInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task Download(string pakName)
|
|
||||||
{
|
|
||||||
var pakUpdateInfo = await GetInfo(pakName);
|
|
||||||
Logger.Log(string.Join("\n", pakUpdateInfo));
|
|
||||||
await ConsoleCommandsHandler.ExecuteCommad("dwplug " + pakName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
66
PluginManager/Others/Actions/InternalActionsManager.cs
Normal file
66
PluginManager/Others/Actions/InternalActionsManager.cs
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
using PluginManager.Loaders;
|
||||||
|
|
||||||
|
namespace PluginManager.Others.Actions;
|
||||||
|
|
||||||
|
public class InternalActionManager
|
||||||
|
{
|
||||||
|
public Dictionary<string, ICommandAction> Actions = new();
|
||||||
|
public ActionsLoader loader;
|
||||||
|
|
||||||
|
public InternalActionManager(string path, string extension)
|
||||||
|
{
|
||||||
|
loader = new ActionsLoader(path, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Initialize()
|
||||||
|
{
|
||||||
|
//loader.ActionLoadedEvent += OnActionLoaded;
|
||||||
|
var m_actions = await loader.Load();
|
||||||
|
if (m_actions == null) return;
|
||||||
|
foreach (var action in m_actions)
|
||||||
|
{
|
||||||
|
Actions.TryAdd(action.ActionName, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Refresh()
|
||||||
|
{
|
||||||
|
Actions.Clear();
|
||||||
|
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<string> 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";
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Actions[actionName].Execute(args);
|
||||||
|
return "Action executed";
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Config.Logger.Log(e.Message , type: LogType.ERROR, source: typeof(InternalActionManager));
|
||||||
|
return e.Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,31 +4,67 @@ using System.IO.Compression;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PluginManager.Others
|
namespace PluginManager.Others;
|
||||||
|
|
||||||
|
public static class ArchiveManager
|
||||||
{
|
{
|
||||||
public static class ArchiveManager
|
private static string? archiveFolder;
|
||||||
{
|
|
||||||
public static bool isInitialized { get; private set; }
|
public static bool isInitialized { get; private set; }
|
||||||
private static string archiveFolder;
|
|
||||||
|
|
||||||
public static void Initialize()
|
public static void Initialize()
|
||||||
{
|
{
|
||||||
if (isInitialized) throw new Exception("ArchiveManager is already initialized");
|
if (isInitialized) throw new Exception("ArchiveManager is already initialized");
|
||||||
|
|
||||||
if (!Config.Variables.Exists("ArchiveFolder"))
|
if (!Config.AppSettings.ContainsKey("ArchiveFolder"))
|
||||||
Config.Variables.Add("ArchiveFolder", "./Data/PAKS/");
|
Config.AppSettings["ArchiveFolder"] = "./Data/PAKS/";
|
||||||
|
|
||||||
|
archiveFolder = Config.AppSettings["ArchiveFolder"];
|
||||||
|
|
||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
archiveFolder = Config.Variables.GetValue("ArchiveFolder");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a file from a zip archive. The output is a byte array
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileName">The file name in the archive</param>
|
||||||
|
/// <param name="archName">The archive location on the disk</param>
|
||||||
|
/// <returns>An array of bytes that represents the Stream value from the file that was read inside the archive</returns>
|
||||||
|
public async static Task<byte[]?> ReadStreamFromPakAsync(string fileName, string archName)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("ArchiveManager is not initialized");
|
||||||
|
|
||||||
|
archName = archiveFolder + archName;
|
||||||
|
|
||||||
|
if (!File.Exists(archName))
|
||||||
|
throw new Exception("Failed to load file !");
|
||||||
|
|
||||||
|
byte[]? data = null;
|
||||||
|
|
||||||
|
using (var zip = ZipFile.OpenRead(archName))
|
||||||
|
{
|
||||||
|
var entry = zip.Entries.FirstOrDefault(entry => entry.FullName == fileName || entry.Name == fileName);
|
||||||
|
if (entry is null) throw new Exception("File not found in archive");
|
||||||
|
|
||||||
|
var MemoryStream = new MemoryStream();
|
||||||
|
|
||||||
|
var stream = entry.Open();
|
||||||
|
await stream.CopyToAsync(MemoryStream);
|
||||||
|
data = MemoryStream.ToArray();
|
||||||
|
|
||||||
|
stream.Close();
|
||||||
|
MemoryStream.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read data from a file that is inside an archive (ZIP format)
|
/// Read data from a file that is inside an archive (ZIP format)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="FileName">The file name that is inside the archive or its full path</param>
|
/// <param name="FileName">The file name that is inside the archive or its full path</param>
|
||||||
/// <param name="archFile">The archive location from the PAKs folder</param>
|
/// <param name="archFile">The archive location from the PAKs folder</param>
|
||||||
/// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns>
|
/// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns>
|
||||||
public static async Task<string> ReadFromPakAsync(string FileName, string archFile)
|
public static async Task<string?> ReadFromPakAsync(string FileName, string archFile)
|
||||||
{
|
{
|
||||||
if (!isInitialized) throw new Exception("ArchiveManager is not initialized");
|
if (!isInitialized) throw new Exception("ArchiveManager is not initialized");
|
||||||
archFile = archiveFolder + archFile;
|
archFile = archiveFolder + archFile;
|
||||||
@@ -37,7 +73,7 @@ namespace PluginManager.Others
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string textValue = null;
|
string? textValue = null;
|
||||||
using (var fs = new FileStream(archFile, FileMode.Open))
|
using (var fs = new FileStream(archFile, FileMode.Open))
|
||||||
using (var zip = new ZipArchive(fs, ZipArchiveMode.Read))
|
using (var zip = new ZipArchive(fs, ZipArchiveMode.Read))
|
||||||
{
|
{
|
||||||
@@ -55,8 +91,9 @@ namespace PluginManager.Others
|
|||||||
|
|
||||||
return textValue;
|
return textValue;
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
Config.Logger.Log(message: ex.Message, source: typeof(ArchiveManager), type: LogType.ERROR); // Write the error to a file
|
||||||
await Task.Delay(100);
|
await Task.Delay(100);
|
||||||
return await ReadFromPakAsync(FileName, archFile);
|
return await ReadFromPakAsync(FileName, archFile);
|
||||||
}
|
}
|
||||||
@@ -70,14 +107,15 @@ namespace PluginManager.Others
|
|||||||
/// <param name="progress">The progress that is updated as a file is processed</param>
|
/// <param name="progress">The progress that is updated as a file is processed</param>
|
||||||
/// <param name="type">The type of progress</param>
|
/// <param name="type">The type of progress</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static async Task ExtractArchive(string zip, string folder, IProgress<float> progress,
|
public static async Task ExtractArchive(
|
||||||
|
string zip, string folder, IProgress<float> progress,
|
||||||
UnzipProgressType type)
|
UnzipProgressType type)
|
||||||
{
|
{
|
||||||
if (!isInitialized) throw new Exception("ArchiveManager is not initialized");
|
if (!isInitialized) throw new Exception("ArchiveManager is not initialized");
|
||||||
Directory.CreateDirectory(folder);
|
Directory.CreateDirectory(folder);
|
||||||
using (var archive = ZipFile.OpenRead(zip))
|
using (var archive = ZipFile.OpenRead(zip))
|
||||||
{
|
{
|
||||||
if (type == UnzipProgressType.PercentageFromNumberOfFiles)
|
if (type == UnzipProgressType.PERCENTAGE_FROM_NUMBER_OF_FILES)
|
||||||
{
|
{
|
||||||
var totalZIPFiles = archive.Entries.Count();
|
var totalZIPFiles = archive.Entries.Count();
|
||||||
var currentZIPFile = 0;
|
var currentZIPFile = 0;
|
||||||
@@ -93,7 +131,7 @@ namespace PluginManager.Others
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
|
Config.Logger.Log(ex.Message, source: typeof(ArchiveManager), type: LogType.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentZIPFile++;
|
currentZIPFile++;
|
||||||
@@ -102,7 +140,7 @@ namespace PluginManager.Others
|
|||||||
progress.Report((float)currentZIPFile / totalZIPFiles * 100);
|
progress.Report((float)currentZIPFile / totalZIPFiles * 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == UnzipProgressType.PercentageFromTotalSize)
|
else if (type == UnzipProgressType.PERCENTAGE_FROM_TOTAL_SIZE)
|
||||||
{
|
{
|
||||||
ulong zipSize = 0;
|
ulong zipSize = 0;
|
||||||
|
|
||||||
@@ -125,7 +163,7 @@ namespace PluginManager.Others
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
|
Config.Logger.Log(ex.Message, source: typeof(ArchiveManager), type: LogType.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
@@ -135,5 +173,4 @@ namespace PluginManager.Others
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
using Discord.Commands;
|
|
||||||
using Discord.WebSocket;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace PluginManager.Others
|
|
||||||
{
|
|
||||||
public class CmdArgs
|
|
||||||
{
|
|
||||||
public SocketCommandContext context { get; init; }
|
|
||||||
public string cleanContent { get; init; }
|
|
||||||
public string commandUsed { get;init; }
|
|
||||||
public string[] arguments { get;init; }
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,368 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace PluginManager.Others;
|
|
||||||
|
|
||||||
public static class Utilities
|
|
||||||
{
|
|
||||||
private static Dictionary<char, ConsoleColor> Colors = new()
|
|
||||||
{
|
|
||||||
{ 'g', ConsoleColor.Green },
|
|
||||||
{ 'b', ConsoleColor.Blue },
|
|
||||||
{ 'r', ConsoleColor.Red },
|
|
||||||
{ 'm', ConsoleColor.Magenta },
|
|
||||||
{ 'y', ConsoleColor.Yellow }
|
|
||||||
};
|
|
||||||
|
|
||||||
private static char ColorPrefix = '&';
|
|
||||||
|
|
||||||
|
|
||||||
private static bool CanAproximateTo(this float f, float y)
|
|
||||||
{
|
|
||||||
return MathF.Abs(f - y) < 0.000001;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A way to create a table based on input data
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">The List of arrays of strings that represent the rows.</param>
|
|
||||||
public static void FormatAndAlignTable(List<string[]> data, TableFormat format)
|
|
||||||
{
|
|
||||||
if (format == TableFormat.CENTER_EACH_COLUMN_BASED)
|
|
||||||
{
|
|
||||||
var tableLine = '-';
|
|
||||||
var tableCross = '+';
|
|
||||||
var tableWall = '|';
|
|
||||||
|
|
||||||
var len = new int[data[0].Length];
|
|
||||||
foreach (var line in data)
|
|
||||||
for (var i = 0; i < line.Length; i++)
|
|
||||||
if (line[i].Length > len[i])
|
|
||||||
len[i] = line[i].Length;
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var row in data)
|
|
||||||
{
|
|
||||||
if (row[0][0] == tableLine)
|
|
||||||
Logger.Write(tableCross);
|
|
||||||
else
|
|
||||||
Logger.Write(tableWall);
|
|
||||||
for (var l = 0; l < row.Length; l++)
|
|
||||||
{
|
|
||||||
if (row[l][0] == tableLine)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < len[l] + 4; ++i)
|
|
||||||
Logger.Write(tableLine);
|
|
||||||
}
|
|
||||||
else if (row[l].Length == len[l])
|
|
||||||
{
|
|
||||||
Logger.Write(" ");
|
|
||||||
Logger.Write(row[l]);
|
|
||||||
Logger.Write(" ");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var lenHalf = row[l].Length / 2;
|
|
||||||
for (var i = 0; i < (len[l] + 4) / 2 - lenHalf; ++i)
|
|
||||||
Logger.Write(" ");
|
|
||||||
Logger.Write(row[l]);
|
|
||||||
for (var i = (len[l] + 4) / 2 + lenHalf + 1; i < len[l] + 4; ++i)
|
|
||||||
Logger.Write(" ");
|
|
||||||
if (row[l].Length % 2 == 0)
|
|
||||||
Logger.Write(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Write(row[l][0] == tableLine ? tableCross : tableWall);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.WriteLine(); //end line
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format == TableFormat.CENTER_OVERALL_LENGTH)
|
|
||||||
{
|
|
||||||
var maxLen = 0;
|
|
||||||
foreach (var row in data)
|
|
||||||
foreach (var s in row)
|
|
||||||
if (s.Length > maxLen)
|
|
||||||
maxLen = s.Length;
|
|
||||||
|
|
||||||
var div = (maxLen + 4) / 2;
|
|
||||||
|
|
||||||
foreach (var row in data)
|
|
||||||
{
|
|
||||||
Logger.Write("\t");
|
|
||||||
if (row[0] == "-")
|
|
||||||
Logger.Write("+");
|
|
||||||
else
|
|
||||||
Logger.Write("|");
|
|
||||||
|
|
||||||
foreach (var s in row)
|
|
||||||
{
|
|
||||||
if (s == "-")
|
|
||||||
{
|
|
||||||
for (var i = 0; i < maxLen + 4; ++i)
|
|
||||||
Logger.Write("-");
|
|
||||||
}
|
|
||||||
else if (s.Length == maxLen)
|
|
||||||
{
|
|
||||||
Logger.Write(" ");
|
|
||||||
Logger.Write(s);
|
|
||||||
Logger.Write(" ");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var lenHalf = s.Length / 2;
|
|
||||||
for (var i = 0; i < div - lenHalf; ++i)
|
|
||||||
Logger.Write(" ");
|
|
||||||
Logger.Write(s);
|
|
||||||
for (var i = div + lenHalf + 1; i < maxLen + 4; ++i)
|
|
||||||
Logger.Write(" ");
|
|
||||||
if (s.Length % 2 == 0)
|
|
||||||
Logger.Write(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s == "-")
|
|
||||||
Logger.Write("+");
|
|
||||||
else
|
|
||||||
Logger.Write("|");
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.WriteLine(); //end line
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format == TableFormat.DEFAULT)
|
|
||||||
{
|
|
||||||
var widths = new int[data[0].Length];
|
|
||||||
var space_between_columns = 3;
|
|
||||||
for (var i = 0; i < data.Count; i++)
|
|
||||||
for (var j = 0; j < data[i].Length; j++)
|
|
||||||
if (data[i][j].Length > widths[j])
|
|
||||||
widths[j] = data[i][j].Length;
|
|
||||||
|
|
||||||
for (var i = 0; i < data.Count; i++)
|
|
||||||
{
|
|
||||||
for (var j = 0; j < data[i].Length; j++)
|
|
||||||
{
|
|
||||||
if (data[i][j] == "-")
|
|
||||||
data[i][j] = " ";
|
|
||||||
Logger.Write(data[i][j]);
|
|
||||||
for (var k = 0; k < widths[j] - data[i][j].Length + 1 + space_between_columns; k++)
|
|
||||||
Logger.Write(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Exception("Unknown type of table");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WriteColorText(string text, bool appendNewLineAtEnd = true)
|
|
||||||
{
|
|
||||||
if (!Logger.isConsole)
|
|
||||||
{
|
|
||||||
foreach (var item in Colors)
|
|
||||||
text = text.Replace($"{ColorPrefix}{item.Key}", "").Replace("&c", "");
|
|
||||||
Logger.Write(text);
|
|
||||||
if (appendNewLineAtEnd)
|
|
||||||
Logger.WriteLine();
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
var initialForeGround = Console.ForegroundColor;
|
|
||||||
var input = text.ToCharArray();
|
|
||||||
for (var i = 0; i < input.Length; i++)
|
|
||||||
if (input[i] == ColorPrefix)
|
|
||||||
{
|
|
||||||
if (i + 1 < input.Length)
|
|
||||||
{
|
|
||||||
if (Colors.ContainsKey(input[i + 1]))
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = Colors[input[i + 1]];
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
else if (input[i + 1] == 'c')
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = initialForeGround;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.Write(input[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.ForegroundColor = initialForeGround;
|
|
||||||
if (appendNewLineAtEnd)
|
|
||||||
Logger.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Progress bar object
|
|
||||||
/// </summary>
|
|
||||||
public class ProgressBar
|
|
||||||
{
|
|
||||||
private readonly int BarLength = 32;
|
|
||||||
|
|
||||||
private bool isRunning;
|
|
||||||
private int position = 1;
|
|
||||||
private bool positive = true;
|
|
||||||
|
|
||||||
public ProgressBar(ProgressBarType type)
|
|
||||||
{
|
|
||||||
if (!Logger.isConsole)
|
|
||||||
throw new Exception("This class (or function) can be used with console only. For UI please use another approach.");
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float Max { get; init; }
|
|
||||||
public ConsoleColor Color { get; init; }
|
|
||||||
public bool NoColor { get; init; }
|
|
||||||
public ProgressBarType type { get; set; }
|
|
||||||
|
|
||||||
public int TotalLength { get; private set; }
|
|
||||||
|
|
||||||
|
|
||||||
public async void Start()
|
|
||||||
{
|
|
||||||
if (type != ProgressBarType.NO_END)
|
|
||||||
throw new Exception("Only NO_END progress bar can use this method");
|
|
||||||
if (isRunning)
|
|
||||||
throw new Exception("This progress bar is already running");
|
|
||||||
|
|
||||||
isRunning = true;
|
|
||||||
while (isRunning)
|
|
||||||
{
|
|
||||||
UpdateNoEnd();
|
|
||||||
await Task.Delay(100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void Start(string message)
|
|
||||||
{
|
|
||||||
if (type != ProgressBarType.NO_END)
|
|
||||||
throw new Exception("Only NO_END progress bar can use this method");
|
|
||||||
if (isRunning)
|
|
||||||
throw new Exception("This progress bar is already running");
|
|
||||||
|
|
||||||
isRunning = true;
|
|
||||||
|
|
||||||
TotalLength = message.Length + BarLength + 5;
|
|
||||||
while (isRunning)
|
|
||||||
{
|
|
||||||
UpdateNoEnd(message);
|
|
||||||
await Task.Delay(100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
if (type != ProgressBarType.NO_END)
|
|
||||||
throw new Exception("Only NO_END progress bar can use this method");
|
|
||||||
if (!isRunning)
|
|
||||||
throw new Exception("Can not stop a progressbar that did not start");
|
|
||||||
isRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop(string message)
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
|
|
||||||
if (message is not null)
|
|
||||||
{
|
|
||||||
Console.CursorLeft = 0;
|
|
||||||
for (var i = 0; i < BarLength + message.Length + 1; i++)
|
|
||||||
Logger.Write(" ");
|
|
||||||
Console.CursorLeft = 0;
|
|
||||||
Logger.WriteLine(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update(float progress)
|
|
||||||
{
|
|
||||||
if (type == ProgressBarType.NO_END)
|
|
||||||
throw new Exception("This function is for progress bars with end");
|
|
||||||
|
|
||||||
UpdateNormal(progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateNoEnd(string message)
|
|
||||||
{
|
|
||||||
Console.CursorLeft = 0;
|
|
||||||
Logger.Write("[");
|
|
||||||
for (var i = 1; i <= position; i++)
|
|
||||||
Logger.Write(" ");
|
|
||||||
Logger.Write("<==()==>");
|
|
||||||
position += positive ? 1 : -1;
|
|
||||||
for (var i = position; i <= BarLength - 1 - (positive ? 0 : 2); i++)
|
|
||||||
Logger.Write(" ");
|
|
||||||
Logger.Write("] " + message);
|
|
||||||
|
|
||||||
|
|
||||||
if (position == BarLength - 1 || position == 1)
|
|
||||||
positive = !positive;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateNoEnd()
|
|
||||||
{
|
|
||||||
Console.CursorLeft = 0;
|
|
||||||
Logger.Write("[");
|
|
||||||
for (var i = 1; i <= position; i++)
|
|
||||||
Logger.Write(" ");
|
|
||||||
Logger.Write("<==()==>");
|
|
||||||
position += positive ? 1 : -1;
|
|
||||||
for (var i = position; i <= BarLength - 1 - (positive ? 0 : 2); i++)
|
|
||||||
Logger.Write(" ");
|
|
||||||
Logger.Write("]");
|
|
||||||
|
|
||||||
|
|
||||||
if (position == BarLength - 1 || position == 1)
|
|
||||||
positive = !positive;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateNormal(float progress)
|
|
||||||
{
|
|
||||||
Console.CursorLeft = 0;
|
|
||||||
Logger.Write("[");
|
|
||||||
Console.CursorLeft = BarLength;
|
|
||||||
Logger.Write("]");
|
|
||||||
Console.CursorLeft = 1;
|
|
||||||
var onechunk = 30.0f / Max;
|
|
||||||
|
|
||||||
var position = 1;
|
|
||||||
|
|
||||||
for (var i = 0; i < onechunk * progress; i++)
|
|
||||||
{
|
|
||||||
Console.BackgroundColor = NoColor ? ConsoleColor.Black : Color;
|
|
||||||
Console.CursorLeft = position++;
|
|
||||||
Logger.Write("#");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = position; i < BarLength; i++)
|
|
||||||
{
|
|
||||||
Console.BackgroundColor = NoColor ? ConsoleColor.Black : ConsoleColor.DarkGray;
|
|
||||||
Console.CursorLeft = position++;
|
|
||||||
Logger.Write(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.CursorLeft = BarLength + 4;
|
|
||||||
Console.BackgroundColor = ConsoleColor.Black;
|
|
||||||
if (progress.CanAproximateTo(Max))
|
|
||||||
Logger.Write(progress + " % ✓");
|
|
||||||
else
|
|
||||||
Logger.Write(MathF.Round(progress, 2) + " % ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
47
PluginManager/Others/DBCommandExecutingArguments.cs
Normal file
47
PluginManager/Others/DBCommandExecutingArguments.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using PluginManager.Bot;
|
||||||
|
|
||||||
|
namespace PluginManager.Others;
|
||||||
|
|
||||||
|
public class DBCommandExecutingArguments
|
||||||
|
{
|
||||||
|
public DBCommandExecutingArguments(
|
||||||
|
SocketCommandContext context, string cleanContent, string commandUsed, string[]? arguments)
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
this.cleanContent = cleanContent;
|
||||||
|
this.commandUsed = commandUsed;
|
||||||
|
this.arguments = arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBCommandExecutingArguments(SocketUserMessage? message, DiscordSocketClient client)
|
||||||
|
{
|
||||||
|
this.context = new SocketCommandContext(client, message);
|
||||||
|
int pos = 0;
|
||||||
|
if (message.HasMentionPrefix(client.CurrentUser, ref pos))
|
||||||
|
{
|
||||||
|
var mentionPrefix = "<@" + client.CurrentUser.Id + ">";
|
||||||
|
this.cleanContent = message.Content.Substring(mentionPrefix.Length + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.cleanContent = message.Content.Substring(Config.DiscordBot.botPrefix.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
var split = this.cleanContent.Split(' ');
|
||||||
|
|
||||||
|
string[]? argsClean = null;
|
||||||
|
if (split.Length > 1)
|
||||||
|
argsClean = string.Join(' ', split, 1, split.Length - 1).Split(' ');
|
||||||
|
|
||||||
|
this.commandUsed = split[0];
|
||||||
|
this.arguments = argsClean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SocketCommandContext context { get; init; }
|
||||||
|
public string cleanContent { get; init; }
|
||||||
|
public string commandUsed { get; init; }
|
||||||
|
public string[]? arguments { get; init; }
|
||||||
|
}
|
||||||
@@ -11,25 +11,11 @@ public enum OperatingSystem
|
|||||||
UNKNOWN
|
UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A list with all errors
|
|
||||||
/// </summary>
|
|
||||||
public enum Error
|
|
||||||
{
|
|
||||||
UNKNOWN_ERROR,
|
|
||||||
GUILD_NOT_FOUND,
|
|
||||||
STREAM_NOT_FOUND,
|
|
||||||
INVALID_USER,
|
|
||||||
INVALID_CHANNEL,
|
|
||||||
INVALID_PERMISSIONS
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The output log type
|
/// The output log type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum OutputLogLevel
|
public enum LogType
|
||||||
{
|
{
|
||||||
NONE,
|
|
||||||
INFO,
|
INFO,
|
||||||
WARNING,
|
WARNING,
|
||||||
ERROR,
|
ERROR,
|
||||||
@@ -38,25 +24,24 @@ public enum OutputLogLevel
|
|||||||
|
|
||||||
public enum UnzipProgressType
|
public enum UnzipProgressType
|
||||||
{
|
{
|
||||||
PercentageFromNumberOfFiles,
|
PERCENTAGE_FROM_NUMBER_OF_FILES,
|
||||||
PercentageFromTotalSize
|
PERCENTAGE_FROM_TOTAL_SIZE
|
||||||
}
|
|
||||||
|
|
||||||
public enum TableFormat
|
|
||||||
{
|
|
||||||
CENTER_EACH_COLUMN_BASED,
|
|
||||||
CENTER_OVERALL_LENGTH,
|
|
||||||
DEFAULT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SaveType
|
public enum SaveType
|
||||||
{
|
{
|
||||||
NORMAL,
|
TXT,
|
||||||
BACKUP
|
JSON
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ProgressBarType
|
public enum InternalActionRunType
|
||||||
{
|
{
|
||||||
NORMAL,
|
ON_STARTUP,
|
||||||
NO_END
|
ON_CALL
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum ExceptionExitCode : int
|
||||||
|
{
|
||||||
|
CONFIG_FAILED_TO_LOAD = 1,
|
||||||
|
CONFIG_KEY_NOT_FOUND = 2,
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
using Discord.WebSocket;
|
|
||||||
|
|
||||||
using PluginManager.Items;
|
|
||||||
|
|
||||||
|
|
||||||
namespace PluginManager.Others;
|
namespace PluginManager.Others;
|
||||||
|
|
||||||
@@ -21,9 +16,19 @@ public static class Functions
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The location for the Resources folder
|
/// The location for the Resources folder
|
||||||
|
/// String: ./Data/Resources/
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly string dataFolder = @"./Data/Resources/";
|
public static readonly string dataFolder = @"./Data/Resources/";
|
||||||
|
|
||||||
|
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>
|
/// <summary>
|
||||||
/// Get the Operating system you are runnin on
|
/// Get the Operating system you are runnin on
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -48,7 +53,8 @@ public static class Functions
|
|||||||
/// <exception cref="ArgumentOutOfRangeException">Triggered if <paramref name="bufferSize" /> is less then or equal to 0</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="InvalidOperationException">Triggered if <paramref name="stream" /> is not readable</exception>
|
||||||
/// <exception cref="ArgumentException">Triggered in <paramref name="destination" /> is not writable</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,
|
public static async Task CopyToOtherStreamAsync(
|
||||||
|
this Stream stream, Stream destination, int bufferSize,
|
||||||
IProgress<long>? progress = null,
|
IProgress<long>? progress = null,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
@@ -62,7 +68,8 @@ public static class Functions
|
|||||||
var buffer = new byte[bufferSize];
|
var buffer = new byte[bufferSize];
|
||||||
long totalBytesRead = 0;
|
long totalBytesRead = 0;
|
||||||
int bytesRead;
|
int bytesRead;
|
||||||
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
|
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken)
|
||||||
|
.ConfigureAwait(false)) != 0)
|
||||||
{
|
{
|
||||||
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
|
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
|
||||||
totalBytesRead += bytesRead;
|
totalBytesRead += bytesRead;
|
||||||
@@ -70,39 +77,22 @@ public static class Functions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Save to JSON file
|
public static T SelectRandomValueOf<T>()
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The class type</typeparam>
|
|
||||||
/// <param name="file">The file path</param>
|
|
||||||
/// <param name="Data">The values</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task SaveToJsonFile<T>(string file, T Data)
|
|
||||||
{
|
{
|
||||||
var str = new MemoryStream();
|
var enums = Enum.GetValues(typeof(T));
|
||||||
await JsonSerializer.SerializeAsync(str, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true });
|
var random = new Random();
|
||||||
await File.WriteAllBytesAsync(file, str.ToArray());
|
return (T)enums.GetValue(random.Next(enums.Length));
|
||||||
await str.FlushAsync();
|
|
||||||
str.Close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public static T RandomValue<T>(this T[] values)
|
||||||
/// Convert json text or file to some kind of data
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The data type</typeparam>
|
|
||||||
/// <param name="input">The file or json text</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task<T> ConvertFromJson<T>(string input)
|
|
||||||
{
|
{
|
||||||
Stream text;
|
Random random = new();
|
||||||
if (File.Exists(input))
|
return values[random.Next(values.Length)];
|
||||||
text = new MemoryStream(await File.ReadAllBytesAsync(input));
|
}
|
||||||
else
|
|
||||||
text = new MemoryStream(Encoding.ASCII.GetBytes(input));
|
public static string ToResourcesPath(this string path)
|
||||||
text.Position = 0;
|
{
|
||||||
var obj = await JsonSerializer.DeserializeAsync<T>(text);
|
return Path.Combine(dataFolder, path);
|
||||||
await text.FlushAsync();
|
|
||||||
text.Close();
|
|
||||||
return (obj ?? default)!;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
47
PluginManager/Others/JsonManager.cs
Normal file
47
PluginManager/Others/JsonManager.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PluginManager;
|
||||||
|
|
||||||
|
public class JsonManager
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Save to JSON file
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The class type</typeparam>
|
||||||
|
/// <param name="file">The file path</param>
|
||||||
|
/// <param name="Data">The values</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task SaveToJsonFile<T>(string file, T Data)
|
||||||
|
{
|
||||||
|
var str = new MemoryStream();
|
||||||
|
await JsonSerializer.SerializeAsync(str, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true });
|
||||||
|
await File.WriteAllBytesAsync(file, str.ToArray());
|
||||||
|
await str.FlushAsync();
|
||||||
|
str.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert json text or file to some kind of data
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The data type</typeparam>
|
||||||
|
/// <param name="input">The file or json text</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task<T> ConvertFromJson<T>(string input)
|
||||||
|
{
|
||||||
|
Stream text;
|
||||||
|
if (File.Exists(input))
|
||||||
|
text = new MemoryStream(await File.ReadAllBytesAsync(input));
|
||||||
|
else
|
||||||
|
text = new MemoryStream(Encoding.ASCII.GetBytes(input));
|
||||||
|
text.Position = 0;
|
||||||
|
|
||||||
|
var obj = await JsonSerializer.DeserializeAsync<T>(text);
|
||||||
|
await text.FlushAsync();
|
||||||
|
text.Close();
|
||||||
|
return (obj ?? default)!;
|
||||||
|
}
|
||||||
|
}
|
||||||
78
PluginManager/Others/Logger/Log.cs
Normal file
78
PluginManager/Others/Logger/Log.cs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using PluginManager.Interfaces.Logger;
|
||||||
|
|
||||||
|
namespace PluginManager.Others.Logger;
|
||||||
|
|
||||||
|
public class Log : ILog
|
||||||
|
{
|
||||||
|
public string Message { get; set; }
|
||||||
|
public string OutputFile { get; set; }
|
||||||
|
public Type? Source { get; set; }
|
||||||
|
public LogType Type { get; set; }
|
||||||
|
public DateTime ThrowTime { get; set; }
|
||||||
|
|
||||||
|
public Log(string message, string outputFile, Type? source, LogType type, DateTime throwTime)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
OutputFile = outputFile;
|
||||||
|
Source = source;
|
||||||
|
Type = type;
|
||||||
|
ThrowTime = throwTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log(string message, string outputFile, Type? source, LogType type)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
OutputFile = outputFile;
|
||||||
|
Source = source;
|
||||||
|
Type = type;
|
||||||
|
ThrowTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log(string message, string outputFile, Type? source)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
OutputFile = outputFile;
|
||||||
|
Source = source;
|
||||||
|
Type = LogType.INFO;
|
||||||
|
ThrowTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log(string message, string outputFile)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
OutputFile = outputFile;
|
||||||
|
Source = typeof(Log);
|
||||||
|
Type = LogType.INFO;
|
||||||
|
ThrowTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log(string message)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
OutputFile = "";
|
||||||
|
Source = typeof(Log);
|
||||||
|
Type = LogType.INFO;
|
||||||
|
ThrowTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Log(string message) => new (message);
|
||||||
|
|
||||||
|
public static implicit operator string(Log log) => $"[{log.ThrowTime}] {log.Message}";
|
||||||
|
|
||||||
|
public string AsLongString()
|
||||||
|
{
|
||||||
|
return $"[{ThrowTime}] [{Source}] [{Type}] {Message}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string AsShortString()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FormatedLongString()
|
||||||
|
{
|
||||||
|
return $"[{ThrowTime}]\t[{Source}]\t\t\t[{Type}]\t{Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
69
PluginManager/Others/Logger/Logger.cs
Normal file
69
PluginManager/Others/Logger/Logger.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using PluginManager.Interfaces.Logger;
|
||||||
|
|
||||||
|
namespace PluginManager.Others.Logger;
|
||||||
|
|
||||||
|
public sealed class Logger : ILogger
|
||||||
|
{
|
||||||
|
public bool IsEnabled { get; init; }
|
||||||
|
public bool OutputToFile { get; init; }
|
||||||
|
|
||||||
|
public LogType LowestLogLevel { get; set; }
|
||||||
|
private bool UseShortVersion { get; }
|
||||||
|
|
||||||
|
public Logger(bool useShortVersion, bool outputToFile, LogType lowestLogLevel = LogType.INFO)
|
||||||
|
{
|
||||||
|
UseShortVersion = useShortVersion;
|
||||||
|
OutputToFile = outputToFile;
|
||||||
|
IsEnabled = true;
|
||||||
|
LowestLogLevel = lowestLogLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<Log>? OnLog;
|
||||||
|
|
||||||
|
private async Task Log(Log logMessage)
|
||||||
|
{
|
||||||
|
if (!IsEnabled) return;
|
||||||
|
|
||||||
|
OnLog?.Invoke(this, logMessage);
|
||||||
|
|
||||||
|
if (logMessage.Type < LowestLogLevel) return;
|
||||||
|
|
||||||
|
if (OutputToFile)
|
||||||
|
await File.AppendAllTextAsync(
|
||||||
|
logMessage.OutputFile,
|
||||||
|
(UseShortVersion ? logMessage : logMessage.AsLongString()) + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void Log(string message = "", string outputFile = "", Type? source = default, LogType type = LogType.INFO, DateTime throwTime = default)
|
||||||
|
{
|
||||||
|
if (!IsEnabled) return;
|
||||||
|
|
||||||
|
if (type < LowestLogLevel) return;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(message)) return;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(outputFile)) outputFile = Config.AppSettings["LogFolder"] + "/" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";
|
||||||
|
|
||||||
|
if(throwTime == default) throwTime = DateTime.Now;
|
||||||
|
|
||||||
|
if (source == default) source = typeof(Log);
|
||||||
|
|
||||||
|
await Log(new Log(message, outputFile, source, type, throwTime));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void Log(Exception exception, LogType logType = LogType.ERROR, Type? source = null)
|
||||||
|
{
|
||||||
|
if (!IsEnabled) return;
|
||||||
|
|
||||||
|
if (logType < LowestLogLevel) return;
|
||||||
|
|
||||||
|
await Log(new Log(exception.Message,
|
||||||
|
Config.AppSettings["LogFolder"] + "/" + DateTime.Now.ToString("yyyy-MM-dd") + ".log",
|
||||||
|
source, logType, DateTime.Now));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
|
||||||
|
|||||||
129
PluginManager/Others/SettingsDictionary.cs
Normal file
129
PluginManager/Others/SettingsDictionary.cs
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PluginManager.Others;
|
||||||
|
|
||||||
|
public class SettingsDictionary<TKey, TValue> : IDictionary<TKey, TValue>
|
||||||
|
{
|
||||||
|
public string? _file { get; }
|
||||||
|
private IDictionary<TKey, TValue>? _dictionary;
|
||||||
|
|
||||||
|
public SettingsDictionary(string? file)
|
||||||
|
{
|
||||||
|
_file = file;
|
||||||
|
if (!LoadFromFile())
|
||||||
|
{
|
||||||
|
_dictionary = new Dictionary<TKey, TValue>();
|
||||||
|
SaveToFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SaveToFile()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(_file))
|
||||||
|
await JsonManager.SaveToJsonFile(_file, _dictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool LoadFromFile()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(_file))
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(_file))
|
||||||
|
{
|
||||||
|
string FileContent = File.ReadAllText(_file);
|
||||||
|
if (string.IsNullOrEmpty(FileContent))
|
||||||
|
File.WriteAllText(_file, "{}");
|
||||||
|
|
||||||
|
if(!FileContent.Contains("{") || !FileContent.Contains("}"))
|
||||||
|
File.WriteAllText(_file, "{}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
File.WriteAllText(_file, "{}");
|
||||||
|
_dictionary = JsonManager.ConvertFromJson<IDictionary<TKey, TValue>>(_file).Result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||||
|
{
|
||||||
|
return _dictionary!.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return ((IEnumerable) _dictionary!).GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(KeyValuePair<TKey, TValue> item)
|
||||||
|
{
|
||||||
|
this._dictionary!.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
this._dictionary!.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(KeyValuePair<TKey, TValue> item)
|
||||||
|
{
|
||||||
|
return this._dictionary!.Contains(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
this._dictionary!.CopyTo(array, arrayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(KeyValuePair<TKey, TValue> item)
|
||||||
|
{
|
||||||
|
return this._dictionary!.Remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count => _dictionary!.Count;
|
||||||
|
public bool IsReadOnly => _dictionary!.IsReadOnly;
|
||||||
|
public void Add(TKey key, TValue value)
|
||||||
|
{
|
||||||
|
this._dictionary!.Add(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ContainsKey(TKey key)
|
||||||
|
{
|
||||||
|
return this._dictionary!.ContainsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(TKey key)
|
||||||
|
{
|
||||||
|
return this._dictionary!.Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetValue(TKey key, out TValue value)
|
||||||
|
{
|
||||||
|
return this._dictionary!.TryGetValue(key, out value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TValue this[TKey key]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (this._dictionary!.ContainsKey(key))
|
||||||
|
if(this._dictionary[key] is string s && !string.IsNullOrEmpty(s) && !string.IsNullOrWhiteSpace(s))
|
||||||
|
return this._dictionary[key];
|
||||||
|
|
||||||
|
return default!;
|
||||||
|
}
|
||||||
|
set => this._dictionary![key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICollection<TKey> Keys => _dictionary!.Keys;
|
||||||
|
public ICollection<TValue> Values => _dictionary!.Values;
|
||||||
|
}
|
||||||
@@ -1,24 +1,18 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<DebugSymbols>false</DebugSymbols>
|
<DebugSymbols>false</DebugSymbols>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="BlankWindow1.xaml" />
|
<None Remove="BlankWindow1.xaml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Discord.Net" Version="3.8.1" />
|
<PackageReference Include="Discord.Net" Version="3.11.0" />
|
||||||
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.117" />
|
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.118" />
|
||||||
<PackageReference Include="Terminal.Gui" Version="1.8.2" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
using PluginManager.Database;
|
|
||||||
|
|
||||||
namespace PluginManager
|
|
||||||
{
|
|
||||||
public class Settings
|
|
||||||
{
|
|
||||||
|
|
||||||
public static class Variables
|
|
||||||
{
|
|
||||||
public static string WebsiteURL = "https://wizzy69.github.io/SethDiscordBot";
|
|
||||||
public static string UpdaterURL = "https://github.com/Wizzy69/installer/releases/download/release-1-discordbot/Updater.zip";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SqlDatabase sqlDatabase;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
41
README.md
41
README.md
@@ -8,9 +8,7 @@ This project is based on:
|
|||||||
|
|
||||||
|
|
||||||
## Plugins
|
## Plugins
|
||||||
#### Requirements:
|
- Some plugins can be found in [this repo](https://github.com/andreitdr/SethPlugins).
|
||||||
- [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&channel=Release&version=VS2022&source=VSLandingPage&cid=2030&passive=false)
|
|
||||||
- .NET 6 (downloaded with Visual Studio)
|
|
||||||
|
|
||||||
Plugin Types:
|
Plugin Types:
|
||||||
1. Commands
|
1. Commands
|
||||||
@@ -19,12 +17,16 @@ Plugin Types:
|
|||||||
|
|
||||||
### How to create a plugin
|
### How to create a plugin
|
||||||
|
|
||||||
First of all, Create a new project (class library) in Visual Studio.
|
#### Requirements:
|
||||||
Then import the PluginManager.dll as project to your project.
|
- [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&channel=Release&version=VS2022&source=VSLandingPage&cid=2030&passive=false)
|
||||||
|
- .NET 6 (downloaded with Visual Studio)
|
||||||
|
|
||||||
|
First of all, create a new project (class library) in Visual Studio.
|
||||||
|
Then import the PluginManager as reference to your project.
|
||||||
|
|
||||||
## 1. Commands
|
## 1. Commands
|
||||||
|
|
||||||
Commands are loaded when all plugins are loaded into memory. When an user executes the command, only then the Execute function is called.
|
Commands are loaded when all plugins are loaded into memory. The Execute method is called whenever any user (that respects the `requireAdmin` propery) calls the command using the bot prefix and the `Command`.
|
||||||
Commands are plugins that allow users to interact with them.
|
Commands are plugins that allow users to interact with them.
|
||||||
Here is an example:
|
Here is an example:
|
||||||
```cs
|
```cs
|
||||||
@@ -35,20 +37,21 @@ using PluginManager.Interfaces;
|
|||||||
|
|
||||||
namespace LevelingSystem;
|
namespace LevelingSystem;
|
||||||
|
|
||||||
internal class LevelCommand : DBCommand
|
public class LevelCommand : DBCommand
|
||||||
{
|
{
|
||||||
public string Command => "level";
|
public string Command => "level";
|
||||||
|
|
||||||
public List<string> Aliases => new() { "lvl" };
|
public List<string> Aliases => new() { "lvl" };
|
||||||
|
|
||||||
public string Description => "Display tour current level";
|
public string Description => "Display your current level";
|
||||||
|
|
||||||
public string Usage => "level";
|
public string Usage => "level";
|
||||||
|
|
||||||
public bool requireAdmin => false;
|
public bool requireAdmin => false;
|
||||||
|
|
||||||
public async void ExecuteServer(SocketCommandContext context)
|
public async void ExecuteServer(DBCommandExecutingArguments context)
|
||||||
{
|
{
|
||||||
|
//Variables.database is a sql connection that is defined in an auxiliary file in the same napespace as this class
|
||||||
object[] user = await Variables.database.ReadDataArrayAsync($"SELECT * FROM Levels WHERE UserID='{context.Message.Author.Id}'");
|
object[] user = await Variables.database.ReadDataArrayAsync($"SELECT * FROM Levels WHERE UserID='{context.Message.Author.Id}'");
|
||||||
if (user is null)
|
if (user is null)
|
||||||
{
|
{
|
||||||
@@ -69,6 +72,11 @@ internal class LevelCommand : DBCommand
|
|||||||
builder.WithAuthor(context.Message.Author.Mention);
|
builder.WithAuthor(context.Message.Author.Mention);
|
||||||
await context.Channel.SendMessageAsync(embed: builder.Build());
|
await context.Channel.SendMessageAsync(embed: builder.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Optional method (tell the bot what should it do if the command is executed from a DM channel)
|
||||||
|
//public async void ExecuteDM(DBCommandExecutingArguments context) {
|
||||||
|
//
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -85,8 +93,8 @@ internal class LevelCommand : DBCommand
|
|||||||
- context - the command context
|
- context - the command context
|
||||||
|
|
||||||
From here on, start coding. When your plugin is done, build it as any DLL project then add it to the following path
|
From here on, start coding. When your plugin is done, build it as any DLL project then add it to the following path
|
||||||
`{bot_executable}/Data/Plugins/<optional subfolder>/[your dll name].dll`
|
`{bot_executable}/Data/Plugins/<optional subfolder>/[plugin name].dll`
|
||||||
Then, reload bot and execute command `lp` in bot's console. The plugin should be loaded into memory or an error is thrown if not. If an error is thrown, then
|
Then, reload bot and execute command `plugin load` in the console. The plugin should be loaded into memory or an error is thrown if not. If an error is thrown, then
|
||||||
there is something wrong in your command's code.
|
there is something wrong in your command's code.
|
||||||
|
|
||||||
## 2. Events
|
## 2. Events
|
||||||
@@ -107,8 +115,6 @@ public class OnUserJoin : DBEvent
|
|||||||
|
|
||||||
public async void Start(Discord.WebSocket.DiscordSocketClient client)
|
public async void Start(Discord.WebSocket.DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Hello World from {name}");
|
|
||||||
|
|
||||||
client.UserJoined += async (user) => {
|
client.UserJoined += async (user) => {
|
||||||
await (await user.CreateDMChannelAsync()).SendMessageAsync("Welcome to server !");
|
await (await user.CreateDMChannelAsync()).SendMessageAsync("Welcome to server !");
|
||||||
};
|
};
|
||||||
@@ -148,7 +154,7 @@ namespace SlashCommands
|
|||||||
public List<SlashCommandOptionBuilder> Options => new List<SlashCommandOptionBuilder>()
|
public List<SlashCommandOptionBuilder> Options => new List<SlashCommandOptionBuilder>()
|
||||||
{
|
{
|
||||||
new SlashCommandOptionBuilder() {Name = "min-value", Description = "Minimum value", IsRequired=true, Type = ApplicationCommandOptionType.Integer, MinValue = 0, MaxValue = int.MaxValue-1},
|
new SlashCommandOptionBuilder() {Name = "min-value", Description = "Minimum value", IsRequired=true, Type = ApplicationCommandOptionType.Integer, MinValue = 0, MaxValue = int.MaxValue-1},
|
||||||
new SlashCommandOptionBuilder() {Name="max-value", Description = "Maximum value", IsRequired=true, Type=ApplicationCommandOptionType.Integer,MinValue = 0, MaxValue = int.MaxValue-1}
|
new SlashCommandOptionBuilder() {Name = "max-value", Description = "Maximum value", IsRequired=true, Type=ApplicationCommandOptionType.Integer,MinValue = 0, MaxValue = int.MaxValue-1}
|
||||||
};
|
};
|
||||||
|
|
||||||
public async void ExecuteServer(SocketSlashCommand command)
|
public async void ExecuteServer(SocketSlashCommand command)
|
||||||
@@ -180,3 +186,10 @@ namespace SlashCommands
|
|||||||
- context - the command context
|
- context - the command context
|
||||||
- ExecuteDM() - this function will be called if the command is invoked in a DM channel (optional)
|
- ExecuteDM() - this function will be called if the command is invoked in a DM channel (optional)
|
||||||
- context - the command context
|
- context - the command context
|
||||||
|
|
||||||
|
|
||||||
|
## Note:
|
||||||
|
You can create multiple commands, events and slash commands into one single plugin (class library). The PluginManager will detect the classes and load them individualy. If there are more commands (normal commands, events or slash commands) into a single project (class library) they can use the same resources (a class for example) that is contained within the plugin.
|
||||||
|
|
||||||
|
|
||||||
|
> Updated: 25.09.2023
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.1.32421.90
|
VisualStudioVersion = 17.1.32421.90
|
||||||
@@ -7,15 +7,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiscordBot", "DiscordBot\Di
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PluginManager", "PluginManager\PluginManager.csproj", "{EDD4D9B3-98DD-4367-A09F-D1C5ACB61132}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PluginManager", "PluginManager\PluginManager.csproj", "{EDD4D9B3-98DD-4367-A09F-D1C5ACB61132}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MusicLibrary", "..\DiscordBotItems\Plugins\MusicLibrary\MusicLibrary.csproj", "{878DFE01-4596-4EBC-9651-0679598CE794}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SethPlugins", "SethPlugins", "{78B6D390-F61A-453F-B38D-E4C054321615}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlashCommands", "..\DiscordBotItems\Plugins\SlashCommands\SlashCommands.csproj", "{C2D73BE8-997B-4A4A-8EA5-989BE33EE1DD}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MusicPlayer", "..\SethPlugins\MusicPlayer\MusicPlayer.csproj", "{1690CBBC-BDC0-4DD8-B701-F8817189D9D5}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LevelingSystem", "..\DiscordBotItems\Plugins\LevelingSystem\LevelingSystem.csproj", "{0138F343-BBB9-4D5F-B499-D9C2978BE9AA}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LevelingSystem", "..\SethPlugins\LevelingSystem\LevelingSystem.csproj", "{BFE3491C-AC01-4252-B242-6451270FC548}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roles", "..\DiscordBotItems\Roles\Roles.csproj", "{0900B4CB-B531-4A8D-98D8-E709A7C2E098}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PythonCompatibilityLayer", "..\SethPlugins\PythonCompatibilityLayer\PythonCompatibilityLayer.csproj", "{81ED4953-13E5-4950-96A8-8CEF5FD59559}"
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DBEconomy", "..\DiscordBotItems\Plugins\DBEconomy\DBEconomy.csproj", "{0321365B-4ADC-4B1D-BD98-F573D36E83B2}"
|
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -31,30 +29,27 @@ Global
|
|||||||
{EDD4D9B3-98DD-4367-A09F-D1C5ACB61132}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{EDD4D9B3-98DD-4367-A09F-D1C5ACB61132}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{EDD4D9B3-98DD-4367-A09F-D1C5ACB61132}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{EDD4D9B3-98DD-4367-A09F-D1C5ACB61132}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{EDD4D9B3-98DD-4367-A09F-D1C5ACB61132}.Release|Any CPU.Build.0 = Release|Any CPU
|
{EDD4D9B3-98DD-4367-A09F-D1C5ACB61132}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{878DFE01-4596-4EBC-9651-0679598CE794}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{1690CBBC-BDC0-4DD8-B701-F8817189D9D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{878DFE01-4596-4EBC-9651-0679598CE794}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{1690CBBC-BDC0-4DD8-B701-F8817189D9D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{878DFE01-4596-4EBC-9651-0679598CE794}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{1690CBBC-BDC0-4DD8-B701-F8817189D9D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{878DFE01-4596-4EBC-9651-0679598CE794}.Release|Any CPU.Build.0 = Release|Any CPU
|
{1690CBBC-BDC0-4DD8-B701-F8817189D9D5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{C2D73BE8-997B-4A4A-8EA5-989BE33EE1DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{BFE3491C-AC01-4252-B242-6451270FC548}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{C2D73BE8-997B-4A4A-8EA5-989BE33EE1DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{BFE3491C-AC01-4252-B242-6451270FC548}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{C2D73BE8-997B-4A4A-8EA5-989BE33EE1DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{BFE3491C-AC01-4252-B242-6451270FC548}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{C2D73BE8-997B-4A4A-8EA5-989BE33EE1DD}.Release|Any CPU.Build.0 = Release|Any CPU
|
{BFE3491C-AC01-4252-B242-6451270FC548}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{0138F343-BBB9-4D5F-B499-D9C2978BE9AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{81ED4953-13E5-4950-96A8-8CEF5FD59559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{0138F343-BBB9-4D5F-B499-D9C2978BE9AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{81ED4953-13E5-4950-96A8-8CEF5FD59559}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{0138F343-BBB9-4D5F-B499-D9C2978BE9AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{81ED4953-13E5-4950-96A8-8CEF5FD59559}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{0138F343-BBB9-4D5F-B499-D9C2978BE9AA}.Release|Any CPU.Build.0 = Release|Any CPU
|
{81ED4953-13E5-4950-96A8-8CEF5FD59559}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{0900B4CB-B531-4A8D-98D8-E709A7C2E098}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{0900B4CB-B531-4A8D-98D8-E709A7C2E098}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{0900B4CB-B531-4A8D-98D8-E709A7C2E098}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{0900B4CB-B531-4A8D-98D8-E709A7C2E098}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{0321365B-4ADC-4B1D-BD98-F573D36E83B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{0321365B-4ADC-4B1D-BD98-F573D36E83B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{0321365B-4ADC-4B1D-BD98-F573D36E83B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{0321365B-4ADC-4B1D-BD98-F573D36E83B2}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{1690CBBC-BDC0-4DD8-B701-F8817189D9D5} = {78B6D390-F61A-453F-B38D-E4C054321615}
|
||||||
|
{BFE3491C-AC01-4252-B242-6451270FC548} = {78B6D390-F61A-453F-B38D-E4C054321615}
|
||||||
|
{81ED4953-13E5-4950-96A8-8CEF5FD59559} = {78B6D390-F61A-453F-B38D-E4C054321615}
|
||||||
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF}
|
SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
|||||||
Reference in New Issue
Block a user