18 Commits

Author SHA1 Message Date
e5f3aff39a patch (database & slash commands) 2022-11-02 15:35:18 +02:00
11ec02ef68 Changed Config System 2022-10-25 21:37:52 +03:00
cad19935d5 Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2022-10-23 20:11:47 +03:00
47f88f167f patch 2022-10-23 20:11:27 +03:00
9d6c335799 2022-10-23 11:08:46 +03:00
cbaf552e7a 2022-10-22 16:02:05 +03:00
a4975a4578 Merge branch 'preview' of https://github.com/Wizzy69/DiscordBotWithAPI into preview 2022-10-22 14:45:35 +03:00
725d02d152 2022-10-22 14:44:55 +03:00
ae7118e89a Update to Discord.Net 3.8.1 (API v10) 2022-10-22 13:55:48 +03:00
cad3bb5b75 2022-10-14 12:44:44 +03:00
269d7d56ff 2022-10-14 12:44:21 +03:00
403c023191 2022-10-14 11:13:09 +03:00
3f7a8e04d4 2022-10-14 11:06:56 +03:00
0abbd24b86 Code cleanup 2022-10-12 20:29:00 +03:00
21f1975fbc 2022-10-09 20:59:16 +03:00
d6f072904e patch 2022-10-09 20:26:39 +03:00
6fc491a0d6 2022-10-07 13:36:15 +03:00
7bc9db03f0 patch 2022-10-03 21:46:34 +03:00
35 changed files with 2197 additions and 1806 deletions

2
.gitignore vendored
View File

@@ -368,3 +368,5 @@ FodyWeavers.xsd
#folders #folders
/Plugins/ /Plugins/
/DiscordBot.rar /DiscordBot.rar
/DiscordBot/Data/
/DiscordBot/Updater/

View File

@@ -1,4 +0,0 @@
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>

View File

@@ -1,9 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using PluginManager; using PluginManager;
using PluginManager.Interfaces; using PluginManager.Interfaces;
@@ -66,12 +64,10 @@ internal class Help : DBCommand
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 + " ";
}
embedBuilder.AddField("Admin Commands", adminCommands); embedBuilder.AddField("Admin Commands", adminCommands);
embedBuilder.AddField("Normal Commands", normalCommands); embedBuilder.AddField("Normal Commands", normalCommands);
@@ -81,10 +77,11 @@ 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 || (p.Aliases is not null && p.Aliases.Contains(command))); var cmd = PluginLoader.Commands!.Find(p => p.Command == command ||
(p.Aliases is not null && p.Aliases.Contains(command)));
if (cmd == null) return null; if (cmd == null) return null;
embedBuilder.AddField("Usage", Config.GetValue<string>("prefix") + cmd.Usage); embedBuilder.AddField("Usage", Config.Variables.GetValue("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;

View File

@@ -1,10 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using PluginManager.Others; using PluginManager.Others;
using PluginManager.Others.Permissions;
using DiscordLibCommands = Discord.Commands; using DiscordLibCommands = Discord.Commands;
using DiscordLib = Discord; using DiscordLib = Discord;
using OperatingSystem = PluginManager.Others.OperatingSystem; using OperatingSystem = PluginManager.Others.OperatingSystem;

View File

@@ -1,89 +0,0 @@
using System;
using System.Collections.Generic;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using PluginManager;
using PluginManager.Interfaces;
namespace DiscordBot.Discord.Commands;
internal class Settings : DBCommand
{
/// <summary>
/// Command name
/// </summary>
public string Command => "set";
public List<string> Aliases => null;
/// <summary>
/// Command Description
/// </summary>
public string Description => "This command allows you change all settings. Use \"set help\" to show details";
/// <summary>
/// Command usage
/// </summary>
public string Usage => "set [keyword] [new Value]";
/// <summary>
/// Check if the command require administrator to be executed
/// </summary>
public bool requireAdmin => true;
/// <summary>
/// The main body of the command
/// </summary>
/// <param name="context">The command context</param>
public async void Execute(SocketCommandContext context)
{
var channel = context.Message.Channel;
try
{
var content = context.Message.Content;
var data = content.Split(' ');
var keyword = data[1];
if (keyword.ToLower() == "help")
{
await channel.SendMessageAsync("set token [new value] -- set the value of the new token (require restart)");
await channel.SendMessageAsync("set prefix [new value] -- set the value of the new preifx (require restart)");
return;
}
switch (keyword.ToLower())
{
case "token":
if (data.Length != 3)
{
await channel.SendMessageAsync("Invalid token !");
return;
}
Config.SetValue("token", data[2]);
break;
case "prefix":
if (data.Length != 3)
{
await channel.SendMessageAsync("Invalid token !");
return;
}
Config.SetValue("token", data[2]);
break;
default:
return;
}
await channel.SendMessageAsync("Restart required ...");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
await channel.SendMessageAsync("Unknown usage to this command !\nUsage: " + Usage);
}
}
}

View File

@@ -1,13 +1,10 @@
using System; using System;
using System.Threading;
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;
using static PluginManager.Others.Functions; using static PluginManager.Others.Functions;
namespace DiscordBot.Discord.Core; namespace DiscordBot.Discord.Core;
@@ -63,7 +60,14 @@ internal class Boot
/// <returns>Task</returns> /// <returns>Task</returns>
public async Task Awake() public async Task Awake()
{ {
DiscordSocketConfig config = new DiscordSocketConfig { AlwaysDownloadUsers = true }; var config = new DiscordSocketConfig
{
AlwaysDownloadUsers = true,
//Disable system clock checkup (for responses at slash commands)
UseInteractionSnowflakeDate = false
};
client = new DiscordSocketClient(config); client = new DiscordSocketClient(config);
service = new CommandService(); service = new CommandService();
@@ -71,11 +75,14 @@ internal class Boot
CommonTasks(); CommonTasks();
await client.LoginAsync(TokenType.Bot, botToken); await client.LoginAsync(TokenType.Bot, botToken);
await client.StartAsync(); await client.StartAsync();
commandServiceHandler = new CommandHandler(client, service, botPrefix); commandServiceHandler = new CommandHandler(client, service, botPrefix);
await commandServiceHandler.InstallCommandsAsync(); await commandServiceHandler.InstallCommandsAsync();
await Task.Delay(2000); await Task.Delay(2000);
while (!isReady) ; while (!isReady) ;
} }
@@ -89,19 +96,22 @@ internal class Boot
client.Ready += Ready; client.Ready += Ready;
} }
private Task Client_LoggedOut() private async Task Client_LoggedOut()
{ {
WriteLogFile("Successfully Logged Out"); WriteLogFile("Successfully Logged Out");
Log(new LogMessage(LogSeverity.Info, "Boot", "Successfully logged out from discord !")); await Log(new LogMessage(LogSeverity.Info, "Boot", "Successfully logged out from discord !"));
return Task.CompletedTask;
/* var cmds = await client.GetGlobalApplicationCommandsAsync();
foreach (var cmd in cmds)
await cmd.DeleteAsync();*/
} }
private Task Ready() private async Task Ready()
{ {
Console.Title = "ONLINE"; Console.Title = "ONLINE";
isReady = true;
return Task.CompletedTask;
isReady = true;
} }
private Task LoggedIn() private Task LoggedIn()
@@ -141,5 +151,4 @@ internal class Boot
return Task.CompletedTask; return Task.CompletedTask;
} }
} }

View File

@@ -1,4 +1,5 @@
using System.Linq; using System;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -37,9 +38,34 @@ internal class CommandHandler
public async Task InstallCommandsAsync() public async Task InstallCommandsAsync()
{ {
client.MessageReceived += MessageHandler; client.MessageReceived += MessageHandler;
client.SlashCommandExecuted += Client_SlashCommandExecuted;
await commandService.AddModulesAsync(Assembly.GetEntryAssembly(), null); await commandService.AddModulesAsync(Assembly.GetEntryAssembly(), null);
} }
private async Task Client_SlashCommandExecuted(SocketSlashCommand arg)
{
try
{
var plugin = PluginLoader.SlashCommands!
.Where(p => p.Name == arg.Data.Name)
.FirstOrDefault();
if (plugin is null) throw new Exception("Failed to run command. !");
if (arg.Channel is SocketDMChannel)
plugin.ExecuteDM(arg);
else plugin.ExecuteServer(arg);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
ex.WriteErrFile();
}
}
/// <summary> /// <summary>
/// The message handler for the bot /// The message handler for the bot
/// </summary> /// </summary>
@@ -75,9 +101,15 @@ internal class CommandHandler
await commandService.ExecuteAsync(context, argPos, null); await commandService.ExecuteAsync(context, argPos, null);
var plugin = PluginLoader.Commands!.Where(p => p.Command == message.Content.Split(' ')[0].Substring(botPrefix.Length) || (p.Aliases is not null && p.Aliases.Contains(message.Content.Split(' ')[0].Substring(botPrefix.Length)))).FirstOrDefault(); var plugin = PluginLoader.Commands!
.Where(
p => p.Command == message.Content.Split(' ')[0].Substring(botPrefix.Length) ||
(p.Aliases is not null &&
p.Aliases.Contains(
message.Content.Split(' ')[0].Substring(botPrefix.Length))))
.FirstOrDefault();
if (plugin is null) throw new System.Exception("Failed to run command. !"); if (plugin is null) throw new Exception("Failed to run command. !");
if (plugin.requireAdmin && !context.Message.Author.isAdmin()) if (plugin.requireAdmin && !context.Message.Author.isAdmin())
return; return;
@@ -85,9 +117,8 @@ internal class CommandHandler
if (context.Channel is SocketDMChannel) if (context.Channel is SocketDMChannel)
plugin.ExecuteDM(context); plugin.ExecuteDM(context);
else plugin.ExecuteServer(context); else plugin.ExecuteServer(context);
} }
catch (System.Exception ex) catch (Exception ex)
{ {
ex.WriteErrFile(); ex.WriteErrFile();
} }

View File

@@ -0,0 +1,52 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>disable</Nullable>
<ApplicationIcon />
<StartupObject />
<SignAssembly>False</SignAssembly>
<IsPublishable>True</IsPublishable>
<AssemblyVersion>1.0.1.0</AssemblyVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>none</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>none</DebugType>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Data\**" />
<Compile Remove="obj\**" />
<Compile Remove="Output\**" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Remove="Data\**" />
<EmbeddedResource Remove="obj\**" />
<EmbeddedResource Remove="Output\**" />
</ItemGroup>
<ItemGroup>
<None Remove="Data\**" />
<None Remove="obj\**" />
<None Remove="Output\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.7.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PluginManager\PluginManager.csproj" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="xcopy /B /Y &quot;$(TargetDir)*.dll&quot; &quot;$(TargetDir)Libraries&quot;" />
</Target>
</Project>

View File

@@ -8,7 +8,7 @@
<StartupObject /> <StartupObject />
<SignAssembly>False</SignAssembly> <SignAssembly>False</SignAssembly>
<IsPublishable>True</IsPublishable> <IsPublishable>True</IsPublishable>
<AssemblyVersion>1.0.0.14</AssemblyVersion> <AssemblyVersion>1.0.1.0</AssemblyVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

29
DiscordBot/Entry.cs Normal file
View File

@@ -0,0 +1,29 @@
using System;
using System.IO;
using System.Reflection;
namespace DiscordBot
{
public class Entry
{
[STAThread]
public static void Main(string[] args)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(LoadFromSameFolder);
static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args)
{
string folderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "./Libraries");
string assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll");
if (!File.Exists(assemblyPath)) return null;
Assembly assembly = Assembly.LoadFrom(assemblyPath);
return assembly;
}
Program.Startup(args);
}
}
}

View File

@@ -1,8 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -10,13 +8,16 @@ using System.Threading.Tasks;
using DiscordBot.Discord.Core; using DiscordBot.Discord.Core;
using PluginManager; using PluginManager;
using PluginManager.Database;
using PluginManager.Items; using PluginManager.Items;
using PluginManager.Online; using PluginManager.Online;
using PluginManager.Online.Helpers;
using PluginManager.Others; using PluginManager.Others;
using Terminal.Gui; using Terminal.Gui;
using OperatingSystem = PluginManager.Others.OperatingSystem;
namespace DiscordBot; namespace DiscordBot;
public class Program public class Program
@@ -29,20 +30,20 @@ public class Program
/// The main entry point for the application. /// The main entry point for the application.
/// </summary> /// </summary>
[STAThread] [STAThread]
[Obsolete] public static void Startup(string[] args)
public static void Main(string[] args)
{ {
Console.WriteLine("Loading resources ...");
PreLoadComponents().Wait(); PreLoadComponents().Wait();
if (!Config.Variables.Exists("ServerID") || !Config.Variables.Exists("token") ||
if (!Config.ContainsKey("ServerID") || (!Config.ContainsKey("token") || Config.GetValue<string>("token") == null || (Config.GetValue<string>("token")?.Length != 70 && Config.GetValue<string>("token")?.Length != 59)) || (!Config.ContainsKey("prefix") || Config.GetValue<string>("prefix") == null || Config.GetValue<string>("prefix")?.Length != 1) || (args.Length > 0 && args[0] == "/newconfig")) Config.Variables.GetValue("token") == null ||
(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"))
{ {
Application.Init(); Application.Init();
var top = Application.Top; var top = Application.Top;
Application.IsMouseDisabled = true;
var win = new Window("Discord Bot Config - " + Assembly.GetExecutingAssembly().GetName().Version) var win = new Window("Discord Bot Config - " + Assembly.GetExecutingAssembly().GetName().Version)
{ {
X = 0, X = 0,
@@ -53,7 +54,10 @@ public class Program
top.Add(win); top.Add(win);
var labelInfo = new Label("Configuration file not found or invalid. Please fill the following fields to create a new configuration file.") var labelInfo = new Label(
"Configuration file not found or invalid. " +
"Please fill the following fields to create a new configuration file."
)
{ {
X = Pos.Center(), X = Pos.Center(),
Y = 2 Y = 2
@@ -88,10 +92,9 @@ public class Program
var labelServerid = new Label("Please insert your server id here (optional): ") var labelServerid = new Label("Please insert your server id here (optional): ")
{ {
X = 5, X = 5,
Y = 11, Y = 11
}; };
var textFiledServerID = new TextField("null") var textFiledServerID = new TextField("")
{ {
X = Pos.Left(labelServerid) + labelServerid.Text.Length + 2, X = Pos.Left(labelServerid) + labelServerid.Text.Length + 2,
Y = labelServerid.Y, Y = labelServerid.Y,
@@ -110,15 +113,17 @@ public class Program
Y = 16 Y = 16
}; };
Console.CancelKeyPress += (sender, e) => var button3 = new Button("ⓘ")
{ {
top.Running = false; X = Pos.Left(textFiledServerID) + 20,
Y = textFiledServerID.Y
}; };
Console.CancelKeyPress += (sender, e) => { top.Running = false; };
button.Clicked += () => button.Clicked += () =>
{ {
string passMessage = ""; var passMessage = "";
if (textFiledToken.Text.Length != 70 && textFiledToken.Text.Length != 59) if (textFiledToken.Text.Length != 70 && textFiledToken.Text.Length != 59)
passMessage += "Invalid token, "; passMessage += "Invalid token, ";
if (textFiledPrefix.Text.ContainsAny("0123456789/\\ ") || textFiledPrefix.Text.Length != 1) if (textFiledPrefix.Text.ContainsAny("0123456789/\\ ") || textFiledPrefix.Text.Length != 1)
@@ -128,42 +133,53 @@ public class Program
if (passMessage != "") if (passMessage != "")
{ {
MessageBox.ErrorQuery("Discord Bot Settings", "Failed to pass check. Invalid information given:\n" + passMessage, "Retry"); MessageBox.ErrorQuery("Discord Bot Settings",
"Failed to pass check. Invalid information given:\n" + passMessage, "Retry");
return; return;
} }
Config.AddValueToVariables<string>("ServerID", ((string)textFiledServerID.Text), true); Config.Variables.Add("ServerID", (string)textFiledServerID.Text, true);
Config.AddValueToVariables<string>("token", ((string)textFiledToken.Text), true); Config.Variables.Add("token", (string)textFiledToken.Text, true);
Config.AddValueToVariables<string>("prefix", ((string)textFiledPrefix.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"); MessageBox.Query("Discord Bot Settings", "Successfully saved config !\nJust start the bot :D",
"Start :D");
top.Running = false; top.Running = false;
}; };
button2.Clicked += async () => button2.Clicked += async () =>
{ {
string[] license = await File.ReadAllLinesAsync("LICENSE.txt"); var license =
string 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"; await ServerCom.ReadTextFromURL(
int r = MessageBox.Query("Discord Bot Settings", ProductLicense, "Close", "Read about libraries used"); "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) if (r == 1)
{ {
int i = 0; var i = 0;
while (i < license.Length) while (i < license.Count)
{ {
string print_message = license[i++] + "\n"; var print_message = license[i++] + "\n";
for (; i < license.Length && !license[i].StartsWith("-----------"); i++) for (; i < license.Count && !license[i].StartsWith("-----------"); i++)
print_message += license[i] + "\n"; 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; 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(labelInfo, labelPrefix, labelServerid, labelToken);
win.Add(textFiledToken, textFiledPrefix, textFiledServerID); win.Add(textFiledToken, textFiledPrefix, textFiledServerID, button3);
win.Add(button, button2); win.Add(button, button2);
Application.Run(); Application.Run();
Application.Shutdown(); Application.Shutdown();
@@ -175,22 +191,18 @@ public class Program
/// <summary> /// <summary>
/// The main loop for the discord bot /// The main loop for the discord bot
/// </summary> /// </summary>
/// <param name="discordbooter">The discord booter used to start the application</param> private static void NoGUI()
private static void NoGUI(Boot discordbooter)
{ {
#if DEBUG #if DEBUG
Console.WriteLine(); Settings.Variables.outputStream.WriteLine();
ConsoleCommandsHandler.ExecuteCommad("lp").Wait(); ConsoleCommandsHandler.ExecuteCommad("lp").Wait();
#else #else
if (loadPluginsOnStartup) consoleCommandsHandler.HandleCommand("lp"); if (loadPluginsOnStartup) consoleCommandsHandler.HandleCommand("lp");
if (listPluginsAtStartup) consoleCommandsHandler.HandleCommand("listplugs"); if (listPluginsAtStartup) consoleCommandsHandler.HandleCommand("listplugs");
#endif #endif
Config.SaveConfig(SaveType.NORMAL).Wait();
while (true) while (true)
{ {
var cmd = Console.ReadLine(); var cmd = Console.ReadLine();
if (!consoleCommandsHandler.HandleCommand(cmd! if (!consoleCommandsHandler.HandleCommand(cmd!
#if DEBUG #if DEBUG
@@ -198,7 +210,7 @@ public class Program
#endif #endif
) && cmd.Length > 0) ) && cmd.Length > 0)
Console.WriteLine("Failed to run command " + cmd); Settings.Variables.outputStream.WriteLine("Failed to run command " + cmd);
} }
} }
@@ -206,238 +218,143 @@ 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<Boot> StartNoGui()
{ {
Console.Clear(); Console.Clear();
Console.ForegroundColor = ConsoleColor.DarkYellow; Console.ForegroundColor = ConsoleColor.DarkYellow;
List<string> startupMessageList = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/StartupMessage"); var startupMessageList =
await ServerCom.ReadTextFromURL(
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/StartupMessage");
foreach (var message in startupMessageList) foreach (var message in startupMessageList)
Console.WriteLine(message); Settings.Variables.outputStream.WriteLine(message);
Console.WriteLine($"Running on version: {Config.GetValue<string>("Version") ?? System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()}"); Settings.Variables.outputStream.WriteLine(
Console.WriteLine($"Git URL: {Config.GetValue<string>("GitURL") ?? " Could not find Git URL"}"); $"Running on version: {Assembly.GetExecutingAssembly().GetName().Version}");
Settings.Variables.outputStream.WriteLine($"Git URL: {Settings.Variables.WebsiteURL}");
Console_Utilities.WriteColorText("&rRemember to close the bot using the ShutDown command (&ysd&r) or some settings won't be saved\n"); 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.ContainsKey("LaunchMessage")) if (Config.Variables.Exists("LaunchMessage"))
{ Utilities.WriteColorText(Config.Variables.GetValue("LaunchMessage"));
Console_Utilities.WriteColorText(Config.GetValue<string>("LaunchMessage"));
Config.RemoveKey("LaunchMessage");
}
Console_Utilities.WriteColorText("Please note that the bot saves a backup save file every time you are using the shudown command (&ysd&c)");
Console.WriteLine($"============================ LOG ============================"); Utilities.WriteColorText(
"Please note that the bot saves a backup save file every time you are using the shudown command (&ysd&c)");
Settings.Variables.outputStream.WriteLine("============================ LOG ============================");
try try
{ {
var token = Config.GetValue<string>("token"); string token = "";
#if DEBUG #if DEBUG
Console.WriteLine("Starting in DEBUG MODE");
if (!Directory.Exists("./Data/BetaTest")) if (await Settings.sqlDatabase.TableExistsAsync("BetaTest"))
Console.WriteLine("Failed to start in debug mode because the folder ./Data/BetaTest does not exist");
else
{ {
token = File.ReadAllText("./Data/BetaTest/token.txt"); Settings.Variables.outputStream.WriteLine("Starting in DEBUG MODE");
token = await Settings.sqlDatabase.GetValueAsync("BetaTest", "VariableName", "Token", "Value");
//Debug mode code...
} }
#else
token = Config.Variables.GetValue("token");
#endif #endif
var prefix = Config.Variables.GetValue("prefix");
var prefix = Config.GetValue<string>("prefix");
var discordbooter = new Boot(token, prefix); var discordbooter = new Boot(token, prefix);
await discordbooter.Awake(); await discordbooter.Awake();
return discordbooter; return discordbooter;
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine(ex); Settings.Variables.outputStream.WriteLine(ex);
return null; return null;
} }
} }
/// <summary>
/// Clear folder
/// </summary>
/// <param name="d">Directory path</param>
private static Task ClearFolder(string d)
{
var files = Directory.GetFiles(d);
var fileNumb = files.Length;
for (var i = 0; i < fileNumb; i++)
{
File.Delete(files[i]);
Console.WriteLine("Deleting : " + files[i]);
}
return Task.CompletedTask;
}
/// <summary> /// <summary>
/// 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(string[] args)
{ {
var len = args.Length; var len = args.Length;
if (len == 3 && args[0] == "/download") var b = await StartNoGui();
{
var url = args[1];
var location = args[2];
await ServerCom.DownloadFileAsync(url, location);
return;
}
if (len > 0 && (args.Contains("--cmd") || args.Contains("--args") || args.Contains("--nomessage")))
{
if (args.Contains("lp") || args.Contains("loadplugins"))
loadPluginsOnStartup = true;
if (args.Contains("listplugs"))
listPluginsAtStartup = true;
len = 0;
}
if (len == 2 && args[0] == "/procKill")
{
Process.GetProcessById(int.Parse(args[1])).Kill();
len = 0;
}
var b = await StartNoGUI();
consoleCommandsHandler = new ConsoleCommandsHandler(b.client); consoleCommandsHandler = new ConsoleCommandsHandler(b.client);
if (len > 0 && args[0] == "/remplug") if (len > 0 && args[0] == "/remplug")
{ {
var plugName = string.Join(' ', args, 1, args.Length - 1);
string plugName = Functions.MergeStrings(args, 1); Settings.Variables.outputStream.WriteLine("Starting to remove " + plugName);
Console.WriteLine("Starting to remove " + plugName);
await ConsoleCommandsHandler.ExecuteCommad("remplug " + plugName); await ConsoleCommandsHandler.ExecuteCommad("remplug " + plugName);
loadPluginsOnStartup = true; loadPluginsOnStartup = true;
len = 0;
} }
if (len > 0 && args[0] == "/updateplug") if (len > 0 && args[0] == "/lp")
{ loadPluginsOnStartup = true;
string plugName = args.MergeStrings(1);
Console.WriteLine("Updating " + plugName);
await ConsoleCommandsHandler.ExecuteCommad("dwplug" + plugName);
return;
}
if (len == 0 || (args[0] != "--exec" && args[0] != "--execute")) var mainThread = new Thread(() =>
{
Thread mainThread = new Thread(() =>
{ {
try try
{ {
NoGUI(b); 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.ContainsKey("LaunchMessage")) if (Config.Variables.Exists("LaunchMessage"))
Config.AddValueToVariables("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 !", false); Config.Variables.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 !",
false);
Functions.WriteErrFile(ex.ToString()); Functions.WriteErrFile(ex.ToString());
} }
} }
}); });
mainThread.Start(); mainThread.Start();
return;
}
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine("Execute command interface noGUI\n\n");
Console.WriteLine(
"\tCommand name\t\t\t\tDescription\n" +
"-- help | -help\t\t ------ \tDisplay the help message\n" +
"--reset-full\t\t ------ \tReset all files (clear files)\n" +
"--reset-logs\t\t ------ \tClear up the output folder\n" +
"--start\t\t ------ \tStart the bot\n" +
"exit\t\t\t ------ \tClose the application"
);
while (true)
{
Console.ForegroundColor = ConsoleColor.White;
Console.Write("> ");
var message = Console.ReadLine().Split(' ');
switch (message[0])
{
case "--help":
case "-help":
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine("\tCommand name\t\t\t\tDescription\n" + "-- help | -help\t\t ------ \tDisplay the help message\n" + "--reset-full\t\t ------ \tReset all files (clear files)\n" + "--reset-settings\t ------ \tReset only bot settings\n" + "--reset-logs\t\t ------ \tClear up the output folder\n" + "--start\t\t ------ \tStart the bot\n" + "exit\t\t\t ------ \tClose the application");
break;
case "--reset-full":
await ClearFolder("./Data/Resources/");
await ClearFolder("./Output/Logs/");
await ClearFolder("./Output/Errors");
await ClearFolder("./Data/Languages/");
await ClearFolder("./Data/Plugins/Commands");
await ClearFolder("./Data/Plugins/Events");
Console.WriteLine("Successfully cleared all folders");
break;
case "--reset-logs":
await ClearFolder("./Output/Logs");
await ClearFolder("./Output/Errors");
Console.WriteLine("Successfully clear logs folder");
break;
case "--exit":
case "exit":
Environment.Exit(0);
break;
default:
Console.WriteLine("Failed to execute command " + message[0]);
break;
}
}
} }
private static async Task PreLoadComponents() private static async Task PreLoadComponents()
{ {
Console_Utilities.ProgressBar main = new Console_Utilities.ProgressBar(ProgressBarType.NO_END); Settings.Variables.outputStream = Console.Out;
Settings.Variables.outputStream.WriteLine("Loading resources ...");
var main = new Utilities.ProgressBar(ProgressBarType.NO_END);
main.Start(); main.Start();
Directory.CreateDirectory("./Data/Resources"); Directory.CreateDirectory("./Data/Resources");
Directory.CreateDirectory("./Data/Plugins/Commands"); Directory.CreateDirectory("./Data/Plugins");
Directory.CreateDirectory("./Data/Plugins/Events");
Directory.CreateDirectory("./Data/PAKS"); Directory.CreateDirectory("./Data/PAKS");
await Config.LoadConfig();
if (Config.ContainsKey("DeleteLogsAtStartup")) Settings.sqlDatabase = new SqlDatabase(Functions.dataFolder + "SetDB.dat");
if (Config.GetValue<bool>("DeleteLogsAtStartup"))
await Settings.sqlDatabase.Open();
await Config.Initialize();
if (await Config.Variables.ExistsAsync("DeleteLogsAtStartup"))
if (await Config.Variables.GetValueAsync("DeleteLogsAtStartup") == "true")
foreach (var file in Directory.GetFiles("./Output/Logs/")) foreach (var file in Directory.GetFiles("./Output/Logs/"))
File.Delete(file); File.Delete(file);
List<string> OnlineDefaultKeys = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/SetupKeys"); var OnlineDefaultKeys =
await ServerCom.ReadTextFromURL(
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/SetupKeys");
Config.PluginConfig.Load();
if (!Config.ContainsKey("Version")) if (!await Config.Variables.ExistsAsync("Version"))
Config.AddValueToVariables("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString(), false); await Config.Variables.AddAsync("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString(), false);
else else
Config.SetValue("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString()); await Config.Variables.SetValueAsync("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
foreach (var key in OnlineDefaultKeys) foreach (var key in OnlineDefaultKeys)
{ {
if (key.Length <= 3 || !key.Contains(' ')) continue; if (key.Length <= 3 || !key.Contains(' ')) continue;
string[] s = key.Split(' '); var s = key.Split(' ');
try try
{ {
if (Config.ContainsKey(s[0])) Config.SetValue(s[0], s[1]); if (await Config.Variables.ExistsAsync(s[0])) await Config.Variables.SetValueAsync(s[0], s[1]);
else Config.GetAndAddValueToVariable(s[0], s[1], s[2].Equals("true", StringComparison.CurrentCultureIgnoreCase)); else
await Config.Variables.AddAsync(s[0], s[1], s[2].ToLower() == "true");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -446,66 +363,79 @@ public class Program
} }
var onlineSettingsList =
await ServerCom.ReadTextFromURL(
List<string> onlineSettingsList = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/OnlineData"); "https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/OnlineData");
main.Stop("Loaded online settings. Loading updates ..."); main.Stop("Loaded online settings. Loading updates ...");
foreach (var key in onlineSettingsList) foreach (var key in onlineSettingsList)
{ {
if (key.Length <= 3 || !key.Contains(' ')) continue; if (key.Length <= 3 || !key.Contains(' ')) continue;
string[] s = key.Split(' '); var s = key.Split(' ');
switch (s[0]) switch (s[0])
{ {
case "CurrentVersion": case "CurrentVersion":
string newVersion = s[1]; var newVersion = s[1];
if (!newVersion.Equals(Config.GetValue<string>("Version"))) if (!newVersion.Equals(await Config.Variables.GetValueAsync("Version")))
{ {
if (Functions.GetOperatingSystem() == PluginManager.Others.OperatingSystem.WINDOWS) 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;
}
string url = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0.zip"; if (Functions.GetOperatingSystem() == OperatingSystem.WINDOWS)
//string url2 = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}-preview/net6.0.zip"; {
var url =
Process.Start(".\\Updater\\Updater.exe", $"{newVersion} {url} {Process.GetCurrentProcess().ProcessName}"); $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0.zip";
Process.Start(".\\Updater\\Updater.exe",
$"{newVersion} {url} {Process.GetCurrentProcess().ProcessName}");
} }
else else
{ {
string url = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0_linux.zip"; var url =
Console.WriteLine("Downloading update ..."); $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0_linux.zip";
Settings.Variables.outputStream.WriteLine("Downloading update ...");
await ServerCom.DownloadFileNoProgressAsync(url, "./update.zip"); await ServerCom.DownloadFileNoProgressAsync(url, "./update.zip");
await File.WriteAllTextAsync("Install.sh", "#!/bin/bash\nunzip -qq update.zip -d ./\nrm update.zip\nchmod +x SethDiscordBot\n./DiscordBot"); await File.WriteAllTextAsync("Install.sh",
"#!/bin/bash\nunzip -qq update.zip -d ./\nrm update.zip\nchmod +x SethDiscordBot\n./DiscordBot");
Process.Start("Install.sh").WaitForExit(); Process.Start("Install.sh").WaitForExit();
Environment.Exit(0); Environment.Exit(0);
} }
} }
break; break;
case "UpdaterVersion": case "UpdaterVersion":
string updaternewversion = s[1]; var updaternewversion = s[1];
if (Config.UpdaterVersion != updaternewversion && Functions.GetOperatingSystem() == PluginManager.Others.OperatingSystem.WINDOWS) 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 ||
!Directory.Exists("./Updater") ||
!File.Exists("./Updater/Updater.exe"))
{ {
Console.Clear(); Console.Clear();
Console.WriteLine("Installing updater ...\nDo NOT close the bot during update !"); Settings.Variables.outputStream.WriteLine("Installing updater ...\nDo NOT close the bot during update !");
Console_Utilities.ProgressBar bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END); var bar = new Utilities.ProgressBar(ProgressBarType.NO_END);
bar.Start(); bar.Start();
await ServerCom.DownloadFileNoProgressAsync("https://github.com/Wizzy69/installer/releases/download/release-1-discordbot/Updater.zip", "./Updater.zip"); await ServerCom.DownloadFileNoProgressAsync(
await Functions.ExtractArchive("./Updater.zip", "./", null, UnzipProgressType.PercentageFromTotalSize); "https://github.com/Wizzy69/installer/releases/download/release-1-discordbot/Updater.zip",
Config.UpdaterVersion = updaternewversion; "./Updater.zip");
await Functions.ExtractArchive("./Updater.zip", "./", null,
UnzipProgressType.PercentageFromTotalSize);
await Config.Variables.SetValueAsync("UpdaterVersion", updaternewversion);
File.Delete("Updater.zip"); File.Delete("Updater.zip");
await Config.SaveConfig(SaveType.NORMAL);
bar.Stop("Updater has been updated !"); bar.Stop("Updater has been updated !");
Console.Clear(); Console.Clear();
} }
break; break;
} }
} }
Console_Utilities.Initialize();
await Config.SaveConfig(SaveType.NORMAL);
Console.Clear(); Console.Clear();
} }
} }

View File

@@ -1,239 +1,199 @@
using System; using System;
using PluginManager.Others;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
namespace PluginManager using PluginManager.Online.Helpers;
namespace PluginManager;
public static class Config
{ {
internal class AppConfig private static bool IsLoaded = false;
public static async Task Initialize()
{ {
public string? UpdaterVersion { get; set; } if (IsLoaded)
public Dictionary<string, object>? ApplicationVariables { get; init; }
public List<string>? ProtectedKeyWords { get; init; }
public Dictionary<string, string>? PluginVersions { get; init; }
}
public static class Config
{
public static class PluginConfig
{
public static readonly List<Tuple<string, PluginType>> InstalledPlugins = new();
public static void Load()
{
new Thread(LoadCommands).Start();
new Thread(LoadEvents).Start();
}
private static void LoadCommands()
{
string cmd_path = "./Data/Plugins/Commands/";
string[] files = Directory.GetFiles(cmd_path, $"*.{Loaders.PluginLoader.pluginCMDExtension}", SearchOption.AllDirectories);
foreach (var file in files)
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
{
string PluginName = new FileInfo(file).Name;
string name = PluginName.Substring(0, PluginName.Length - 1 - PluginManager.Loaders.PluginLoader.pluginCMDExtension.Length);
InstalledPlugins.Add(new(name, PluginType.Command));
}
}
private static void LoadEvents()
{
string eve_path = "./Data/Plugins/Events/";
string[] files = Directory.GetFiles(eve_path, $"*.{Loaders.PluginLoader.pluginEVEExtension}", SearchOption.AllDirectories);
foreach (var file in files)
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
if (!file.Contains("PluginManager", StringComparison.InvariantCultureIgnoreCase))
{
string PluginName = new FileInfo(file).Name;
string name = PluginName.Substring(0, PluginName.Length - 1 - PluginManager.Loaders.PluginLoader.pluginEVEExtension.Length);
InstalledPlugins.Add(new(name, PluginType.Event));
}
}
public static bool Contains(string pluginName)
{
foreach (var tuple in InstalledPlugins)
if (tuple.Item1 == pluginName)
return true;
return false;
}
public static PluginType GetPluginType(string pluginName)
{
foreach (var tuple in InstalledPlugins)
if (tuple.Item1 == pluginName)
return tuple.Item2;
return PluginType.Unknown;
}
}
private static AppConfig? appConfig { get; set; }
public static string UpdaterVersion { get => appConfig.UpdaterVersion; set => appConfig.UpdaterVersion = value; }
public static string GetPluginVersion(string pluginName) => appConfig!.PluginVersions![pluginName];
public static void SetPluginVersion(string pluginName, string newVersion)
{
if (appConfig!.PluginVersions!.ContainsKey(pluginName))
appConfig.PluginVersions[pluginName] = newVersion;
else appConfig.PluginVersions.Add(pluginName, newVersion);
// SaveConfig();
}
public static void RemovePluginVersion(string pluginName) => appConfig!.PluginVersions!.Remove(pluginName);
public static bool PluginVersionsContainsKey(string pluginName) => appConfig!.PluginVersions!.ContainsKey(pluginName);
public static void AddValueToVariables<T>(string key, T value, bool isProtected)
{
if (value == null)
throw new Exception("The value cannot be null");
if (appConfig!.ApplicationVariables!.ContainsKey(key))
throw new Exception($"The key ({key}) already exists in the variables. Value {GetValue<T>(key)}");
appConfig.ApplicationVariables.Add(key, value);
if (isProtected && key != "Version")
appConfig.ProtectedKeyWords!.Add(key);
SaveConfig(SaveType.NORMAL);
}
public static Type GetVariableType(string value)
{
if (int.TryParse(value, out var intValue))
return typeof(int);
if (bool.TryParse(value, out var boolValue))
return typeof(bool);
if (float.TryParse(value, out var floatValue))
return typeof(float);
if (double.TryParse(value, out var doubleValue))
return typeof(double);
if (uint.TryParse(value, out var uintValue))
return typeof(uint);
if (long.TryParse(value, out var longValue))
return typeof(long);
if (byte.TryParse(value, out var byteValue))
return typeof(byte);
return typeof(string);
}
public static void GetAndAddValueToVariable(string key, string value, bool isReadOnly)
{
if (Config.ContainsKey(key))
return; return;
if (int.TryParse(value, out var intValue))
Config.AddValueToVariables(key, intValue, isReadOnly); if (!await Settings.sqlDatabase.TableExistsAsync("Plugins"))
else if (bool.TryParse(value, out var boolValue)) await Settings.sqlDatabase.CreateTableAsync("Plugins", "PluginName", "Version");
Config.AddValueToVariables(key, boolValue, isReadOnly); if (!await Settings.sqlDatabase.TableExistsAsync("Variables"))
else if (float.TryParse(value, out var floatValue)) await Settings.sqlDatabase.CreateTableAsync("Variables", "VarName", "Value", "ReadOnly");
Config.AddValueToVariables(key, floatValue, isReadOnly);
else if (double.TryParse(value, out var doubleValue)) IsLoaded = true;
Config.AddValueToVariables(key, doubleValue, isReadOnly);
else if (uint.TryParse(value, out var uintValue))
Config.AddValueToVariables(key, uintValue, isReadOnly);
else if (long.TryParse(value, out var longValue))
Config.AddValueToVariables(key, longValue, isReadOnly);
else if (byte.TryParse(value, out var byteValue))
Config.AddValueToVariables(key, byteValue, isReadOnly);
else
Config.AddValueToVariables(key, value, isReadOnly);
} }
public static T? GetValue<T>(string key) public static class Variables
{ {
if (!appConfig!.ApplicationVariables!.ContainsKey(key)) return default; public static async Task<string> GetValueAsync(string VarName)
try
{ {
JsonElement element = (JsonElement)appConfig.ApplicationVariables[key]; if (!IsLoaded)
return element.Deserialize<T>(); throw new Exception("Config is not loaded");
} return await Settings.sqlDatabase.GetValueAsync("Variables", "VarName", VarName, "Value");
catch
{
return (T)appConfig.ApplicationVariables[key];
}
} }
public static void SetValue<T>(string key, T value) public static string GetValue(string VarName)
{ {
if (value == null) if (!IsLoaded)
throw new Exception("Value is null"); throw new Exception("Config is not loaded");
if (!appConfig!.ApplicationVariables!.ContainsKey(key)) return Settings.sqlDatabase.GetValue("Variables", "VarName", VarName, "Value");
throw new Exception("Key does not exist in the config file");
if (appConfig.ProtectedKeyWords!.Contains(key))
throw new Exception("Key is protected");
appConfig.ApplicationVariables[key] = JsonSerializer.SerializeToElement(value);
SaveConfig(SaveType.NORMAL);
} }
public static void RemoveKey(string key)
public static async Task SetValueAsync(string VarName, string Value)
{ {
if (key == "Version" || key == "token" || key == "prefix") if (!IsLoaded)
throw new Exception("Key is protected"); throw new Exception("Config is not loaded");
appConfig!.ApplicationVariables!.Remove(key);
appConfig.ProtectedKeyWords!.Remove(key); if (await IsReadOnlyAsync(VarName))
SaveConfig(SaveType.NORMAL); 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 bool IsReadOnly(string key) public static void SetValue(string VarName, string Value)
{ {
return appConfig.ProtectedKeyWords.Contains(key); 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 SaveConfig(SaveType type)
public static async Task<bool> IsReadOnlyAsync(string VarName)
{ {
if (type == SaveType.NORMAL) 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)
{ {
string path = Functions.dataFolder + "config.json"; if (!IsLoaded)
await Functions.SaveToJsonFile<AppConfig>(path, appConfig!); 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; return;
} }
if (type == SaveType.BACKUP) await Settings.sqlDatabase.InsertAsync("Variables", VarName, Value, ReadOnly ? "true" : "false");
}
public static void Add(string VarName, string Value, bool ReadOnly = false)
{ {
string path = Functions.dataFolder + "config.json.bak"; if (!IsLoaded)
await Functions.SaveToJsonFile<AppConfig>(path, appConfig!); throw new Exception("Config is not loaded");
if (Exists(VarName))
{
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; return;
} }
Settings.sqlDatabase.SetValue("Plugins", "PluginName", pluginName, "Version", version.ToShortString());
} }
public static async Task LoadConfig()
{
string path = Functions.dataFolder + "config.json";
if (File.Exists(path))
{
try
{
appConfig = await Functions.ConvertFromJson<AppConfig>(path);
}
catch (Exception ex)
{
File.Delete(path);
Console.WriteLine("An error occured while loading the settings. Importing from backup file...");
path = Functions.dataFolder + "config.json.bak";
appConfig = await Functions.ConvertFromJson<AppConfig>(path);
Functions.WriteErrFile(ex.Message);
}
Functions.WriteLogFile($"Loaded {appConfig.ApplicationVariables!.Keys.Count} application variables.\nLoaded {appConfig.ProtectedKeyWords!.Count} readonly variables.");
return;
}
appConfig = new() { ApplicationVariables = new Dictionary<string, object>(), ProtectedKeyWords = new List<string>(), PluginVersions = new Dictionary<string, string>(), UpdaterVersion = "-1" };
}
public static bool ContainsValue<T>(T value) => appConfig!.ApplicationVariables!.ContainsValue(value!);
public static bool ContainsKey(string key) => appConfig!.ApplicationVariables!.ContainsKey(key);
public static IDictionary<string, object> GetAllVariables() => appConfig.ApplicationVariables;
} }
} }

View File

@@ -0,0 +1,310 @@
using System.Collections.Generic;
using System.Data.SQLite;
using System.IO;
using System.Threading.Tasks;
namespace PluginManager.Database
{
public class SqlDatabase
{
private string ConnectionString;
private SQLiteConnection Connection;
public SqlDatabase(string fileName)
{
if (!File.Exists(fileName))
SQLiteConnection.CreateFile(fileName);
ConnectionString = $"URI=file:{fileName}";
Connection = new SQLiteConnection(ConnectionString);
}
public async Task Open()
{
await Connection.OpenAsync();
//Console.WriteLine("Opened database successfully");
}
public async Task InsertAsync(string tableName, params string[] values)
{
string query = $"INSERT INTO {tableName} VALUES (";
for (int i = 0; i < values.Length; i++)
{
query += $"'{values[i]}'";
if (i != values.Length - 1)
query += ", ";
}
query += ")";
SQLiteCommand command = new SQLiteCommand(query, Connection);
await command.ExecuteNonQueryAsync();
}
public void Insert(string tableName, params string[] values)
{
string query = $"INSERT INTO {tableName} VALUES (";
for (int i = 0; i < values.Length; i++)
{
query += $"'{values[i]}'";
if (i != values.Length - 1)
query += ", ";
}
query += ")";
SQLiteCommand command = new SQLiteCommand(query, Connection);
command.ExecuteNonQuery();
}
public async Task RemoveKeyAsync(string tableName, string KeyName, string KeyValue)
{
string query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
SQLiteCommand command = new SQLiteCommand(query, Connection);
await command.ExecuteNonQueryAsync();
}
public void RemoveKey(string tableName, string KeyName, string KeyValue)
{
string query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
SQLiteCommand command = new SQLiteCommand(query, Connection);
command.ExecuteNonQuery();
}
public async Task<bool> KeyExistsAsync(string tableName, string keyName, string KeyValue)
{
string query = $"SELECT * FROM {tableName} where {keyName} = '{KeyValue}'";
if (await ReadDataAsync(query) is not null)
return true;
return false;
}
public bool KeyExists(string tableName, string keyName, string KeyValue)
{
string query = $"SELECT * FROM {tableName} where {keyName} = '{KeyValue}'";
if (ReadData(query) is not null)
return true;
return false;
}
public async Task SetValueAsync(string tableName, string keyName, string KeyValue, string ResultColumnName, string ResultColumnValue)
{
if (!await TableExistsAsync(tableName))
throw new System.Exception($"Table {tableName} does not exist");
await ExecuteAsync($"UPDATE {tableName} SET {ResultColumnName}='{ResultColumnValue}' WHERE {keyName}='{KeyValue}'");
}
public void SetValue(string tableName, string keyName, string KeyValue, string ResultColumnName, string ResultColumnValue)
{
if (!TableExists(tableName))
throw new System.Exception($"Table {tableName} does not exist");
Execute($"UPDATE {tableName} SET {ResultColumnName}='{ResultColumnValue}' WHERE {keyName}='{KeyValue}'");
}
public async Task<string> GetValueAsync(string tableName, string keyName, string KeyValue, string ResultColumnName)
{
if (!await TableExistsAsync(tableName))
throw new System.Exception($"Table {tableName} does not exist");
return await ReadDataAsync($"SELECT {ResultColumnName} FROM {tableName} WHERE {keyName}='{KeyValue}'");
}
public string GetValue(string tableName, string keyName, string KeyValue, string ResultColumnName)
{
if (!TableExists(tableName))
throw new System.Exception($"Table {tableName} does not exist");
return ReadData($"SELECT {ResultColumnName} FROM {tableName} WHERE {keyName}='{KeyValue}'");
}
public async void Stop()
{
await Connection.CloseAsync();
}
public async Task AddColumnsToTableAsync(string tableName, string[] columns)
{
var command = Connection.CreateCommand();
command.CommandText = $"SELECT * FROM {tableName}";
var reader = await command.ExecuteReaderAsync();
var tableColumns = new List<string>();
for (int i = 0; i < reader.FieldCount; i++)
tableColumns.Add(reader.GetName(i));
foreach (var column in columns)
{
if (!tableColumns.Contains(column))
{
command.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {column} TEXT";
await command.ExecuteNonQueryAsync();
}
}
}
public void AddColumnsToTable(string tableName, string[] columns)
{
var command = Connection.CreateCommand();
command.CommandText = $"SELECT * FROM {tableName}";
var reader = command.ExecuteReader();
var tableColumns = new List<string>();
for (int i = 0; i < reader.FieldCount; i++)
tableColumns.Add(reader.GetName(i));
foreach (var column in columns)
{
if (!tableColumns.Contains(column))
{
command.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {column} TEXT";
command.ExecuteNonQuery();
}
}
}
public async Task<bool> TableExistsAsync(string tableName)
{
var cmd = Connection.CreateCommand();
cmd.CommandText = $"SELECT name FROM sqlite_master WHERE type='table' AND name='{tableName}'";
var result = await cmd.ExecuteScalarAsync();
if (result == null)
return false;
return true;
}
public bool TableExists(string tableName)
{
var cmd = Connection.CreateCommand();
cmd.CommandText = $"SELECT name FROM sqlite_master WHERE type='table' AND name='{tableName}'";
var result = cmd.ExecuteScalar();
if (result == null)
return false;
return true;
}
public async Task CreateTableAsync(string tableName, params string[] columns)
{
var cmd = Connection.CreateCommand();
cmd.CommandText = $"CREATE TABLE IF NOT EXISTS {tableName} ({string.Join(", ", columns)})";
await cmd.ExecuteNonQueryAsync();
}
public void CreateTable(string tableName, params string[] columns)
{
var cmd = Connection.CreateCommand();
cmd.CommandText = $"CREATE TABLE IF NOT EXISTS {tableName} ({string.Join(", ", columns)})";
cmd.ExecuteNonQuery();
}
public async Task<int> ExecuteAsync(string query)
{
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
await Connection.OpenAsync();
var command = new SQLiteCommand(query, Connection);
int answer = await command.ExecuteNonQueryAsync();
return answer;
}
public int Execute(string query)
{
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
Connection.Open();
var command = new SQLiteCommand(query, Connection);
int r = command.ExecuteNonQuery();
return r;
}
public async Task<string> ReadDataAsync(string query)
{
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
await Connection.OpenAsync();
var command = new SQLiteCommand(query, Connection);
var reader = await command.ExecuteReaderAsync();
object[] values = new object[reader.FieldCount];
if (reader.Read())
{
reader.GetValues(values);
return string.Join<object>(" ", values);
}
return null;
}
public string ReadData(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 string.Join<object>(" ", values);
}
return null;
}
public async Task<object[]> ReadDataArrayAsync(string query)
{
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
await Connection.OpenAsync();
var command = new SQLiteCommand(query, Connection);
var reader = await command.ExecuteReaderAsync();
object[] values = new object[reader.FieldCount];
if (reader.Read())
{
reader.GetValues(values);
return values;
}
return null;
}
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;
}
}
}

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
namespace PluginManager.Interfaces; namespace PluginManager.Interfaces;
@@ -38,11 +37,15 @@ public interface DBCommand
/// 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="context">The disocrd Context</param>
void ExecuteServer(SocketCommandContext context) { } void ExecuteServer(SocketCommandContext context)
{
}
/// <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="context">The disocrd Context</param>
void ExecuteDM(SocketCommandContext context) { } void ExecuteDM(SocketCommandContext context)
{
}
} }

View File

@@ -7,12 +7,12 @@ public interface DBEvent
/// <summary> /// <summary>
/// The name of the event /// The name of the event
/// </summary> /// </summary>
string name { get; } string Name { get; }
/// <summary> /// <summary>
/// The description of the event /// The description of the event
/// </summary> /// </summary>
string description { get; } string Description { get; }
/// <summary> /// <summary>
/// The method that is invoked when the event is loaded into memory /// The method that is invoked when the event is loaded into memory

View File

@@ -0,0 +1,25 @@
using System.Collections.Generic;
using Discord;
using Discord.WebSocket;
namespace PluginManager.Interfaces
{
public interface DBSlashCommand
{
string Name { get; }
string Description { get; }
bool canUseDM { get; }
List<SlashCommandOptionBuilder> Options { get; }
void ExecuteServer(SocketSlashCommand context)
{
}
void ExecuteDM(SocketSlashCommand context) { }
}
}

View File

@@ -1,8 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Others;
namespace PluginManager.Items; namespace PluginManager.Items;
@@ -21,7 +20,7 @@ public class Command
{ {
Author = message.Author; Author = message.Author;
var data = message.Content.Split(' '); var data = message.Content.Split(' ');
Arguments = data.Length > 1 ? new List<string>(data.MergeStrings(1).Split(' ')) : new List<string>(); Arguments = data.Length > 1 ? new List<string>(string.Join(' ', data, 1, data.Length - 1).Split(' ')) : new List<string>();
CommandName = data[0].Substring(1); CommandName = data[0].Substring(1);
PrefixUsed = data[0][0]; PrefixUsed = data[0][0];
} }

View File

@@ -5,7 +5,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Reflection; using System.Reflection;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.WebSocket; using Discord.WebSocket;
@@ -13,38 +12,43 @@ using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using PluginManager.Loaders; using PluginManager.Loaders;
using PluginManager.Online; using PluginManager.Online;
using PluginManager.Online.Helpers;
using PluginManager.Others; using PluginManager.Others;
using OperatingSystem = PluginManager.Others.OperatingSystem;
namespace PluginManager.Items; namespace PluginManager.Items;
public class ConsoleCommandsHandler public class ConsoleCommandsHandler
{ {
private static readonly PluginsManager manager = new("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Plugins.txt"); 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 readonly List<ConsoleCommand> commandList = new();
private static bool isDownloading;
private static bool pluginsLoaded;
private readonly DiscordSocketClient? client; private readonly DiscordSocketClient? client;
private static bool isDownloading = false;
private static bool pluginsLoaded = false;
public ConsoleCommandsHandler(DiscordSocketClient client) public ConsoleCommandsHandler(DiscordSocketClient client)
{ {
this.client = client; this.client = client;
InitializeBasicCommands(); InitializeBasicCommands();
//Console.WriteLine("Initialized console command handler !");
//Settings.Variables.outputStream.WriteLine("Initialized console command handler !");
} }
private void InitializeBasicCommands() private void InitializeBasicCommands()
{ {
commandList.Clear(); commandList.Clear();
AddCommand("help", "Show help", "help <command>", args => AddCommand("help", "Show help", "help <command>", args =>
{ {
if (args.Length <= 1) if (args.Length <= 1)
{ {
Console.WriteLine("Available commands:"); Settings.Variables.outputStream.WriteLine("Available commands:");
List<string[]> items = new List<string[]>(); var items = new List<string[]>();
items.Add(new[] { "-", "-", "-" }); items.Add(new[] { "-", "-", "-" });
items.Add(new[] { "Command", "Description", "Usage" }); items.Add(new[] { "Command", "Description", "Usage" });
items.Add(new[] { " ", " ", "Argument type: <optional> [required]" }); items.Add(new[] { " ", " ", "Argument type: <optional> [required]" });
@@ -52,24 +56,26 @@ public class ConsoleCommandsHandler
foreach (var command in commandList) foreach (var command in commandList)
{ {
var pa = from p in command.Action.Method.GetParameters() where p.Name != null select p.ParameterType.FullName; var pa = from p in command.Action.Method.GetParameters()
where p.Name != null
select p.ParameterType.FullName;
items.Add(new[] { command.CommandName, command.Description, command.Usage }); items.Add(new[] { command.CommandName, command.Description, command.Usage });
} }
items.Add(new[] { "-", "-", "-" }); items.Add(new[] { "-", "-", "-" });
Console_Utilities.FormatAndAlignTable(items, TableFormat.DEFAULT); Utilities.FormatAndAlignTable(items, TableFormat.DEFAULT);
} }
else else
{ {
foreach (var command in commandList) foreach (var command in commandList)
if (command.CommandName == args[1]) if (command.CommandName == args[1])
{ {
Console.WriteLine("Command description: " + command.Description); Settings.Variables.outputStream.WriteLine("Command description: " + command.Description);
Console.WriteLine("Command execution format:" + command.Usage); Settings.Variables.outputStream.WriteLine("Command execution format:" + command.Usage);
return; return;
} }
Console.WriteLine("Command not found"); Settings.Variables.outputStream.WriteLine("Command not found");
} }
} }
); );
@@ -80,24 +86,26 @@ public class ConsoleCommandsHandler
if (pluginsLoaded) if (pluginsLoaded)
return; return;
var loader = new PluginLoader(client!); var loader = new PluginLoader(client!);
ConsoleColor cc = Console.ForegroundColor; var cc = Console.ForegroundColor;
loader.onCMDLoad += (name, typeName, success, exception) => loader.onCMDLoad += (name, typeName, success, exception) =>
{ {
if (name == null || name.Length < 2) if (name == null || name.Length < 2)
name = typeName; name = typeName;
if (success) if (success)
{ {
Console.ForegroundColor = ConsoleColor.Green; Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("[CMD] Successfully loaded command : " + name); Settings.Variables.outputStream.WriteLine("[CMD] Successfully loaded command : " + name);
} }
else else
{ {
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
if (exception is null)
Console.WriteLine("[CMD] Failed to load command : " + name + " because " + exception!.Message); Settings.Variables.outputStream.WriteLine("An error occured while loading: " + name);
else
Settings.Variables.outputStream.WriteLine("[CMD] Failed to load command : " + name + " because " + exception!.Message);
} }
Console.ForegroundColor = cc; Console.ForegroundColor = cc;
}; };
loader.onEVELoad += (name, typeName, success, exception) => loader.onEVELoad += (name, typeName, success, exception) =>
@@ -108,20 +116,39 @@ public class ConsoleCommandsHandler
if (success) if (success)
{ {
Console.ForegroundColor = ConsoleColor.Green; Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("[EVENT] Successfully loaded event : " + name); Settings.Variables.outputStream.WriteLine("[EVENT] Successfully loaded event : " + name);
} }
else else
{ {
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[EVENT] Failed to load event : " + name + " because " + exception!.Message); Settings.Variables.outputStream.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;
Settings.Variables.outputStream.WriteLine("[SLASH] Successfully loaded command : " + name);
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Settings.Variables.outputStream.WriteLine("[SLASH] Failed to load command : " + name + " because " + exception!.Message);
}
Console.ForegroundColor = cc; Console.ForegroundColor = cc;
}; };
loader.LoadPlugins(); loader.LoadPlugins();
Console.ForegroundColor = cc; Console.ForegroundColor = cc;
pluginsLoaded = true; pluginsLoaded = true;
} }
); );
@@ -133,11 +160,11 @@ public class ConsoleCommandsHandler
if (args.Length == 1) if (args.Length == 1)
{ {
isDownloading = false; isDownloading = false;
Console.WriteLine("Please specify plugin name"); Settings.Variables.outputStream.WriteLine("Please specify plugin name");
return; return;
} }
var name = args.MergeStrings(1); var name = string.Join(' ', args, 1, args.Length - 1);
// info[0] = plugin type // info[0] = plugin type
// info[1] = plugin link // info[1] = plugin link
// info[2] = if others are required, or string.Empty if none // info[2] = if others are required, or string.Empty if none
@@ -147,44 +174,42 @@ public class ConsoleCommandsHandler
if (name == "") if (name == "")
{ {
isDownloading = false; isDownloading = false;
Console_Utilities.WriteColorText("Name is invalid"); Utilities.WriteColorText("Name is invalid");
return; return;
} }
isDownloading = false; isDownloading = false;
Console_Utilities.WriteColorText($"Failed to find plugin &b{name} &c!" + " Use &glistplugs &ccommand to display all available plugins !"); Utilities.WriteColorText($"Failed to find plugin &b{name} &c!" +
" Use &glistplugs &ccommand to display all available plugins !");
return; return;
} }
string path; string path;
if (info[0] == "Command" || info[0] == "Event") if (info[0] == "Plugin")
path = "./Data/Plugins/" + info[0] + "s/" + name + "." + (info[0] == "Command" ? PluginLoader.pluginCMDExtension : PluginLoader.pluginEVEExtension); path = "./Data/Plugins/" + name + ".dll";
else else
path = $"./{info[1].Split('/')[info[1].Split('/').Length - 1]}"; path = $"./{info[1].Split('/')[info[1].Split('/').Length - 1]}";
if (Others.OperatingSystem.WINDOWS == Functions.GetOperatingSystem())
if (OperatingSystem.WINDOWS == Functions.GetOperatingSystem())
{ {
await ServerCom.DownloadFileAsync(info[1], path); await ServerCom.DownloadFileAsync(info[1], path);
} }
else if (Others.OperatingSystem.LINUX == Functions.GetOperatingSystem()) else if (OperatingSystem.LINUX == Functions.GetOperatingSystem())
{ {
Others.Console_Utilities.ProgressBar bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END); var bar = new Utilities.ProgressBar(ProgressBarType.NO_END);
bar.Start(); bar.Start();
await ServerCom.DownloadFileNoProgressAsync(info[1], path); await ServerCom.DownloadFileNoProgressAsync(info[1], path);
bar.Stop("Plugin Downloaded !"); bar.Stop("Plugin Downloaded !");
} }
if (info[0] == "Event")
Config.PluginConfig.InstalledPlugins.Add(new(name, PluginType.Event));
else if (info[0] == "Command")
Config.PluginConfig.InstalledPlugins.Add(new(name, PluginType.Command));
Settings.Variables.outputStream.WriteLine("\n");
Console.WriteLine("\n");
// check requirements if any // check requirements if any
if (info.Length == 3 && info[2] != string.Empty && info[2] != null) if (info.Length == 3 && info[2] != string.Empty && info[2] != null)
{ {
Console.WriteLine($"Downloading requirements for plugin : {name}"); Settings.Variables.outputStream.WriteLine($"Downloading requirements for plugin : {name}");
var lines = await ServerCom.ReadTextFromURL(info[2]); var lines = await ServerCom.ReadTextFromURL(info[2]);
@@ -193,44 +218,48 @@ public class ConsoleCommandsHandler
if (!(line.Length > 0 && line.Contains(","))) if (!(line.Length > 0 && line.Contains(",")))
continue; continue;
var split = line.Split(','); var split = line.Split(',');
Console.WriteLine($"\nDownloading item: {split[1]}"); Settings.Variables.outputStream.WriteLine($"\nDownloading item: {split[1]}");
if (File.Exists("./" + split[1])) File.Delete("./" + split[1]); if (File.Exists("./" + split[1])) File.Delete("./" + split[1]);
if (Others.OperatingSystem.WINDOWS == Functions.GetOperatingSystem()) if (OperatingSystem.WINDOWS == Functions.GetOperatingSystem())
await ServerCom.DownloadFileAsync(split[0], "./" + split[1]);
else if (Others.OperatingSystem.LINUX == Functions.GetOperatingSystem())
{ {
Others.Console_Utilities.ProgressBar bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END); await ServerCom.DownloadFileAsync(split[0], "./" + split[1]);
}
else if (OperatingSystem.LINUX == Functions.GetOperatingSystem())
{
var bar = new Utilities.ProgressBar(ProgressBarType.NO_END);
bar.Start(); bar.Start();
await ServerCom.DownloadFileNoProgressAsync(split[0], "./" + split[1]); await ServerCom.DownloadFileNoProgressAsync(split[0], "./" + split[1]);
bar.Stop("Item downloaded !"); bar.Stop("Item downloaded !");
} }
Console.WriteLine();
Settings.Variables.outputStream.WriteLine();
if (split[0].EndsWith(".pak")) if (split[0].EndsWith(".pak"))
{
File.Move("./" + split[1], "./Data/PAKS/" + split[1], true); File.Move("./" + split[1], "./Data/PAKS/" + split[1], true);
}
else if (split[0].EndsWith(".zip") || split[0].EndsWith(".pkg")) else if (split[0].EndsWith(".zip") || split[0].EndsWith(".pkg"))
{ {
Console.WriteLine($"Extracting {split[1]} ..."); Settings.Variables.outputStream.WriteLine($"Extracting {split[1]} ...");
var bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END);// { Max = 100f, Color = ConsoleColor.Green }; var bar = new Utilities.ProgressBar(
ProgressBarType.NO_END);
bar.Start(); bar.Start();
await Functions.ExtractArchive("./" + split[1], "./", null, UnzipProgressType.PercentageFromTotalSize); await Functions.ExtractArchive("./" + split[1], "./", null,
UnzipProgressType.PercentageFromTotalSize);
bar.Stop("Extracted"); bar.Stop("Extracted");
Console.WriteLine("\n"); Settings.Variables.outputStream.WriteLine("\n");
File.Delete("./" + split[1]); File.Delete("./" + split[1]);
} }
} }
Console.WriteLine(); Settings.Variables.outputStream.WriteLine();
} }
VersionString? ver = await VersionString.GetVersionOfPackageFromWeb(name);
var ver = await ServerCom.GetVersionOfPackageFromWeb(name);
if (ver is null) throw new Exception("Incorrect version"); if (ver is null) throw new Exception("Incorrect version");
Config.SetPluginVersion(name, $"{ver.PackageVersionID}.{ver.PackageMainVersion}.{ver.PackageCheckVersion}"); await Config.Plugins.SetVersionAsync(name, ver);
isDownloading = false; isDownloading = false;
} }
); );
@@ -238,11 +267,11 @@ public class ConsoleCommandsHandler
{ {
if (args.Length != 2) if (args.Length != 2)
return; return;
if (!Config.ContainsKey(args[1])) if (!Config.Variables.Exists(args[1]))
return; return;
var data = Config.GetValue<string>(args[1]); var data = Config.Variables.GetValue(args[1]);
Console.WriteLine($"{args[1]} => {data}"); Settings.Variables.outputStream.WriteLine($"{args[1]} => {data}");
} }
); );
@@ -256,12 +285,12 @@ public class ConsoleCommandsHandler
try try
{ {
Config.GetAndAddValueToVariable(key, value, isReadOnly); Config.Variables.Add(key, value, isReadOnly);
Console.WriteLine($"Updated config file with the following command: {args[1]} => {value}"); Settings.Variables.outputStream.WriteLine($"Updated config file with the following command: {args[1]} => {value}");
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine(ex.ToString()); Settings.Variables.outputStream.WriteLine(ex.ToString());
} }
} }
); );
@@ -270,7 +299,7 @@ public class ConsoleCommandsHandler
{ {
if (args.Length < 2) if (args.Length < 2)
return; return;
Config.RemoveKey(args[1]); Config.Variables.RemoveKey(args[1]);
} }
); );
@@ -278,60 +307,63 @@ public class ConsoleCommandsHandler
{ {
if (client is null) if (client is null)
return; return;
Console_Utilities.ProgressBar bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END); var bar = new Utilities.ProgressBar(ProgressBarType.NO_END);
bar.Start(); bar.Start();
await Config.SaveConfig(SaveType.NORMAL);
await Config.SaveConfig(SaveType.BACKUP);
bar.Stop("Saved config !"); bar.Stop("Saved config !");
Console.WriteLine(); Settings.Variables.outputStream.WriteLine();
Settings.sqlDatabase.Stop();
await client.StopAsync(); await client.StopAsync();
await client.DisposeAsync(); await client.DisposeAsync();
await Task.Delay(1000); await Task.Delay(1000);
Environment.Exit(0); Environment.Exit(0);
} }
); );
AddCommand("import", "Load an external command", "import [pluginName]", async (args) => AddCommand("import", "Load an external command", "import [pluginName]", async args =>
{ {
if (args.Length <= 1) return; if (args.Length <= 1) return;
string pName = Functions.MergeStrings(args, 1); try
HttpClient client = new HttpClient(); {
string url = (await manager.GetPluginLinkByName(pName))[1]; var pName = string.Join(' ', args, 1, args.Length - 1);
Stream s = await client.GetStreamAsync(url); var client = new HttpClient();
MemoryStream str = new MemoryStream(); 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); await s.CopyToAsync(str);
var asmb = Assembly.Load(str.ToArray()); var asmb = Assembly.Load(str.ToArray());
var types = asmb.GetTypes(); var types = asmb.GetTypes();
foreach (var type in types) foreach (var type in types)
{
if (type.IsClass && typeof(DBEvent).IsAssignableFrom(type)) if (type.IsClass && typeof(DBEvent).IsAssignableFrom(type))
{ {
DBEvent instance = (DBEvent)Activator.CreateInstance(type); var instance = (DBEvent)Activator.CreateInstance(type);
instance.Start(this.client); instance.Start(this.client);
Console.WriteLine($"Loaded external {type.FullName}!"); Settings.Variables.outputStream.WriteLine($"[EVENT] Loaded external {type.FullName}!");
} }
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type)) else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
{ {
Console.WriteLine("Only events can be loaded from external sources !"); var instance = (DBCommand)Activator.CreateInstance(type);
return; Settings.Variables.outputStream.WriteLine($"[CMD] Instance: {type.FullName} loaded !");
} }
} }
catch (Exception ex)
{
Settings.Variables.outputStream.WriteLine(ex.Message);
}
}); });
AddCommand("remplug", "Remove a plugin", "remplug [plugName]", async args => AddCommand("remplug", "Remove a plugin", "remplug [plugName]", async args =>
{ {
if (args.Length <= 1) return; if (args.Length <= 1) return;
isDownloading = true; isDownloading = true;
string plugName = Functions.MergeStrings(args, 1); var plugName = string.Join(' ', args, 1, args.Length - 1);
if (pluginsLoaded) if (pluginsLoaded)
{ {
if (Functions.GetOperatingSystem() == Others.OperatingSystem.WINDOWS) if (Functions.GetOperatingSystem() == OperatingSystem.WINDOWS)
{ {
Process.Start("DiscordBot.exe", $"/remplug {plugName}"); Process.Start("DiscordBot.exe", $"/remplug {plugName}");
await Task.Delay(100); await Task.Delay(100);
@@ -343,37 +375,23 @@ public class ConsoleCommandsHandler
await Task.Delay(100); await Task.Delay(100);
Environment.Exit(0); Environment.Exit(0);
} }
isDownloading = false; isDownloading = false;
return; return;
} }
string location = "./Data/Plugins/"; var location = $"./Data/Plugins/{plugName}.dll";
location = Config.PluginConfig.GetPluginType(plugName) switch
{
PluginType.Command => location + "Commands/" + plugName + "." + PluginLoader.pluginCMDExtension,
PluginType.Event => location + "Events/" + plugName + "." + PluginLoader.pluginEVEExtension,
PluginType.Unknown => "./",
_ => throw new NotImplementedException("Plugin type incorrect")
};
if (!File.Exists(location)) if (!File.Exists(location))
{ {
Console.WriteLine("The plugin does not exist"); Settings.Variables.outputStream.WriteLine("The plugin does not exist");
return; return;
} }
File.Delete(location); File.Delete(location);
if (Config.PluginConfig.Contains(plugName))
{ Settings.Variables.outputStream.WriteLine("Removed the plugin DLL. Checking for other files ...");
var tuple = Config.PluginConfig.InstalledPlugins.Where(t => t.Item1 == plugName).FirstOrDefault();
Console.WriteLine("Found: " + tuple.ToString());
Config.PluginConfig.InstalledPlugins.Remove(tuple);
Config.RemovePluginVersion(plugName);
await Config.SaveConfig(SaveType.NORMAL);
}
Console.WriteLine("Removed the plugin DLL. Checking for other files ...");
var info = await manager.GetPluginLinkByName(plugName); var info = await manager.GetPluginLinkByName(plugName);
if (info[2] != string.Empty) if (info[2] != string.Empty)
@@ -388,42 +406,46 @@ public class ConsoleCommandsHandler
File.Delete("./" + split[1]); File.Delete("./" + split[1]);
Console.WriteLine("Removed: " + split[1]); Settings.Variables.outputStream.WriteLine("Removed: " + split[1]);
} }
if (Directory.Exists($"./Data/Plugins/{plugName}"))
Directory.Delete($"./Data/Plugins/{plugName}", true);
if (Directory.Exists(plugName)) if (Directory.Exists(plugName))
Directory.Delete(plugName, true); Directory.Delete(plugName, true);
} }
isDownloading = false;
Console.WriteLine(plugName + " has been successfully deleted !");
isDownloading = false;
Settings.Variables.outputStream.WriteLine(plugName + " has been successfully deleted !");
}); });
AddCommand("reload", "Reload the bot with all plugins", () => AddCommand("reload", "Reload the bot with all plugins", () =>
{ {
if (Functions.GetOperatingSystem() == Others.OperatingSystem.WINDOWS) if (Functions.GetOperatingSystem() == OperatingSystem.WINDOWS)
{ {
Process.Start("DiscordBot.exe", $"lp"); Process.Start("DiscordBot.exe", "lp");
HandleCommand("sd"); HandleCommand("sd");
} }
else else
{ {
Process.Start("./DiscordBot", "lp");
Process.Start("./DiscordBot", $"lp");
HandleCommand("sd"); HandleCommand("sd");
} }
}); });
//AddCommand("");
//Sort the commands by name //Sort the commands by name
commandList.Sort((x, y) => x.CommandName.CompareTo(y.CommandName)); commandList.Sort((x, y) => x.CommandName.CompareTo(y.CommandName));
} }
public static void AddCommand(string command, string description, string usage, Action<string[]> action) 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 }); commandList.Add(new ConsoleCommand
{ CommandName = command, Description = description, Action = action, Usage = usage });
Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.White;
Console_Utilities.WriteColorText($"Command &r{command} &cadded to the list of commands"); Utilities.WriteColorText($"Command &r{command} &cadded to the list of commands");
} }
public static void AddCommand(string command, string description, Action action) public static void AddCommand(string command, string description, Action action)
@@ -449,15 +471,11 @@ public class ConsoleCommandsHandler
public static async Task ExecuteCommad(string command) public static async Task ExecuteCommad(string command)
{ {
var args = command.Split(' '); var args = command.Split(' ');
// Console.WriteLine(command);
foreach (var item in commandList.ToList()) foreach (var item in commandList.ToList())
if (item.CommandName == args[0]) if (item.CommandName == args[0])
{ {
item.Action.Invoke(args); item.Action.Invoke(args);
Console.WriteLine();
while (isDownloading) await Task.Delay(1000); while (isDownloading) await Task.Delay(1000);
} }
} }
@@ -471,18 +489,18 @@ public class ConsoleCommandsHandler
if (removeCommandExecution) if (removeCommandExecution)
{ {
Console.SetCursorPosition(0, Console.CursorTop - 1); Console.SetCursorPosition(0, Console.CursorTop - 1);
for (int i = 0; i < command.Length + 30; i++) for (var i = 0; i < command.Length + 30; i++)
Console.Write(" "); Settings.Variables.outputStream.Write(" ");
Console.SetCursorPosition(0, Console.CursorTop); Console.SetCursorPosition(0, Console.CursorTop);
} }
Console.WriteLine(); Settings.Variables.outputStream.WriteLine();
item.Action(args); item.Action(args);
return true; return true;
} }
return false; return false;
//Console.WriteLine($"Executing: {args[0]} with the following parameters: {args.MergeStrings(1)}"); //Settings.Variables.outputStream.WriteLine($"Executing: {args[0]} with the following parameters: {args.MergeStrings(1)}");
} }
} }

View File

@@ -3,9 +3,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
using PluginManager.Online.Updates;
using PluginManager.Others; using PluginManager.Others;
namespace PluginManager.Loaders; namespace PluginManager.Loaders;
@@ -31,11 +29,6 @@ internal class Loader<T>
private string path { get; } private string path { get; }
private string extension { get; } private string extension { get; }
internal delegate void FileLoadedEventHandler(LoaderArgs args);
internal delegate void PluginLoadedEventHandler(LoaderArgs args);
internal event FileLoadedEventHandler? FileLoaded; internal event FileLoadedEventHandler? FileLoaded;
internal event PluginLoadedEventHandler? PluginLoaded; internal event PluginLoadedEventHandler? PluginLoaded;
@@ -52,7 +45,6 @@ internal class Loader<T>
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)
{ {
Assembly.LoadFrom(file); Assembly.LoadFrom(file);
if (FileLoaded != null) if (FileLoaded != null)
{ {
@@ -98,7 +90,14 @@ internal class Loader<T>
} }
catch (Exception ex) catch (Exception ex)
{ {
if (PluginLoaded != null) PluginLoaded.Invoke(new LoaderArgs { Exception = ex, IsLoaded = false, PluginName = type.FullName, TypeName = nameof(T) }); if (PluginLoaded != null)
PluginLoaded.Invoke(new LoaderArgs
{
Exception = ex,
IsLoaded = false,
PluginName = type.FullName,
TypeName = nameof(T)
});
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -109,4 +108,9 @@ internal class Loader<T>
return list; return list;
} }
internal delegate void FileLoadedEventHandler(LoaderArgs args);
internal delegate void PluginLoadedEventHandler(LoaderArgs args);
} }

View File

@@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using PluginManager.Interfaces;
using PluginManager.Others;
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)
{
Assembly.LoadFrom(file);
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)
{
Functions.WriteErrFile(ex.ToString());
return null;
}
return null;
}
}
}

View File

@@ -1,14 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using PluginManager.Interfaces; using PluginManager.Interfaces;
using PluginManager.Online.Helpers; using PluginManager.Online;
using PluginManager.Online.Updates; using PluginManager.Online.Updates;
using PluginManager.Others; using PluginManager.Others;
@@ -20,11 +19,11 @@ public class PluginLoader
public delegate void EVELoaded(string name, string typeName, bool success, Exception? e = null); public delegate void EVELoaded(string name, string typeName, bool success, Exception? e = null);
private const string pluginCMDFolder = @"./Data/Plugins/Commands/"; public delegate void SLSHLoaded(string name, string tyypename, bool success, Exception? e = null);
private const string pluginEVEFolder = @"./Data/Plugins/Events/";
internal const string pluginCMDExtension = "dll"; private const string pluginFolder = @"./Data/Plugins/";
internal const string pluginEVEExtension = "dll";
internal const string pluginExtension = "dll";
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
/// <summary> /// <summary>
@@ -37,6 +36,11 @@ public class PluginLoader
/// </summary> /// </summary>
public EVELoaded? onEVELoad; public EVELoaded? onEVELoad;
/// <summary>
/// Event that is fired when a <see cref="DBEvent" /> is successfully loaded into events list
/// </summary>
public SLSHLoaded? onSLSHLoad;
/// <summary> /// <summary>
/// The Plugin Loader constructor /// The Plugin Loader constructor
/// </summary> /// </summary>
@@ -57,104 +61,91 @@ public class PluginLoader
/// </summary> /// </summary>
public static List<DBEvent>? Events { get; set; } public static List<DBEvent>? Events { get; set; }
/// <summary>
/// A list of <see cref="DBSlashCommand"/> commands
/// </summary>
public static List<DBSlashCommand>? SlashCommands { get; set; }
/// <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 //Check for updates in commands
foreach (var file in Directory.GetFiles("./Data/Plugins/Commands", $"*.{pluginCMDExtension}", SearchOption.AllDirectories)) foreach (var file in Directory.GetFiles("./Data/Plugins/", $"*.{pluginExtension}",
{ SearchOption.AllDirectories))
await Task.Run(async () => await Task.Run(async () =>
{ {
string name = new FileInfo(file).Name.Split('.')[0]; var name = new FileInfo(file).Name.Split('.')[0];
if (!Config.PluginVersionsContainsKey(name)) var version = await ServerCom.GetVersionOfPackageFromWeb(name);
Config.SetPluginVersion(name, (await VersionString.GetVersionOfPackageFromWeb(name))?.PackageVersionID + ".0.0"); if (version is null)
return;
if (Config.Plugins.GetVersion(name) is not null)
Config.Plugins.SetVersion(name, version);
if (await PluginUpdater.CheckForUpdates(name)) if (await PluginUpdater.CheckForUpdates(name))
await PluginUpdater.Download(name); await PluginUpdater.Download(name);
}); });
}
//Check for updates in events
foreach (var file in Directory.GetFiles("./Data/Plugins/Events", $"*.{pluginEVEExtension}", SearchOption.AllDirectories))
{
await Task.Run(async () =>
{
string name = new FileInfo(file).Name.Split('.')[0];
if (!Config.PluginVersionsContainsKey(name))
Config.SetPluginVersion(name, (await VersionString.GetVersionOfPackageFromWeb(name))?.PackageVersionID + ".0.0");
if (await PluginUpdater.CheckForUpdates(name))
await PluginUpdater.Download(name);
});
}
//Save the new config file (after the updates)
await Config.SaveConfig(SaveType.NORMAL);
//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>();
Functions.WriteLogFile("Starting plugin loader ... Client: " + _client.CurrentUser.Username); Functions.WriteLogFile("Starting plugin loader ... Client: " + _client.CurrentUser.Username);
Console.WriteLine("Loading plugins"); Settings.Variables.outputStream.WriteLine("Loading plugins");
var commandsLoader = new Loader<DBCommand>(pluginCMDFolder, pluginCMDExtension);
var eventsLoader = new Loader<DBEvent>(pluginEVEFolder, pluginEVEExtension);
commandsLoader.FileLoaded += OnCommandFileLoaded;
commandsLoader.PluginLoaded += OnCommandLoaded;
eventsLoader.FileLoaded += EventFileLoaded;
eventsLoader.PluginLoaded += OnEventLoaded;
Commands = commandsLoader.Load();
Events = eventsLoader.Load();
var loader = new LoaderV2("./Data/Plugins", "dll");
loader.FileLoaded += (args) => Functions.WriteLogFile($"{args.PluginName} file Loaded");
loader.PluginLoaded += Loader_PluginLoaded;
var res = loader.Load();
Events = res.Item1;
Commands = res.Item2;
SlashCommands = res.Item3;
} }
private void EventFileLoaded(LoaderArgs e) private async void Loader_PluginLoaded(LoaderArgs args)
{ {
if (!e.IsLoaded) // Settings.Variables.outputStream.WriteLine(args.TypeName);
{ switch (args.TypeName)
Functions.WriteLogFile($"[EVENT] Event from file [{e.PluginName}] has been successfully created !");
}
}
private void OnCommandFileLoaded(LoaderArgs e)
{
if (!e.IsLoaded)
{
Functions.WriteLogFile($"[CMD] Command from file [{e.PluginName}] has been successfully loaded !");
}
}
private void OnEventLoaded(LoaderArgs e)
{ {
case "DBCommand":
onCMDLoad?.Invoke(((DBCommand)args.Plugin!).Command, args.TypeName!, args.IsLoaded, args.Exception);
break;
case "DBEvent":
try try
{ {
if (e.IsLoaded) if (args.IsLoaded)
((DBEvent)e.Plugin!).Start(_client); ((DBEvent)args.Plugin!).Start(_client);
onEVELoad?.Invoke(((DBEvent)e.Plugin!).name, e.TypeName!, e.IsLoaded, e.Exception); onEVELoad?.Invoke(((DBEvent)args.Plugin!).Name, args.TypeName!, args.IsLoaded, args.Exception);
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine(ex.ToString()); Settings.Variables.outputStream.WriteLine(ex.ToString());
Console.WriteLine("Plugin: " + e.PluginName); Settings.Variables.outputStream.WriteLine("Plugin: " + args.PluginName);
Console.WriteLine("Type: " + e.TypeName); Settings.Variables.outputStream.WriteLine("Type: " + args.TypeName);
Console.WriteLine("IsLoaded: " + e.IsLoaded); Settings.Variables.outputStream.WriteLine("IsLoaded: " + args.IsLoaded);
} }
} break;
case "DBSlashCommand":
private void OnCommandLoaded(LoaderArgs e) if (args.IsLoaded)
{ {
onCMDLoad?.Invoke(((DBCommand)e.Plugin!).Command, e.TypeName!, e.IsLoaded, e.Exception); var slash = (DBSlashCommand)args.Plugin;
SlashCommandBuilder builder = new SlashCommandBuilder();
builder.WithName(slash.Name);
builder.WithDescription(slash.Description);
builder.WithDMPermission(slash.canUseDM);
builder.Options = slash.Options;
//Settings.Variables.outputStream.WriteLine("Loaded " + slash.Name);
onSLSHLoad?.Invoke(((DBSlashCommand)args.Plugin!).Name, args.TypeName, args.IsLoaded, args.Exception);
await _client.CreateGlobalApplicationCommandAsync(builder.Build());
}
break;
}
} }
} }

View File

@@ -1,24 +1,27 @@
using System; using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO; using System.IO;
using System.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using PluginManager.Others; using PluginManager.Others;
namespace PluginManager.Online.Helpers namespace PluginManager.Online.Helpers;
internal static class OnlineFunctions
{ {
internal static class OnlineFunctions
{
/// <summary> /// <summary>
/// Downloads a <see cref="Stream"/> and saves it to another <see cref="Stream"/>. /// Downloads a <see cref="Stream" /> and saves it to another <see cref="Stream" />.
/// </summary> /// </summary>
/// <param name="client">The <see cref="HttpClient"/> that is used to download the file</param> /// <param name="client">The <see cref="HttpClient" /> that is used to download the file</param>
/// <param name="url">The url to the file</param> /// <param name="url">The url to the file</param>
/// <param name="destination">The <see cref="Stream"/> to save the downloaded data</param> /// <param name="destination">The <see cref="Stream" /> to save the downloaded data</param>
/// <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, IProgress<float>? progress = null, IProgress<long>? downloadedBytes = null, int bufferSize = 81920, CancellationToken cancellation = default) internal static async Task DownloadFileAsync(this HttpClient client, string url, Stream destination,
IProgress<float>? progress = null,
IProgress<long>? downloadedBytes = null, int bufferSize = 81920,
CancellationToken cancellation = default)
{ {
using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellation)) using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellation))
{ {
@@ -60,8 +63,4 @@ namespace PluginManager.Online.Helpers
using var client = new HttpClient(); using var client = new HttpClient();
return await client.GetStringAsync(url, cancellation); return await client.GetStringAsync(url, cancellation);
} }
}
} }

View File

@@ -1,21 +1,16 @@
using PluginManager.Others; using System;
using System; namespace PluginManager.Online.Helpers;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
namespace PluginManager.Online.Helpers public class VersionString
{ {
public class VersionString
{
public int PackageVersionID;
public int PackageMainVersion;
public int PackageCheckVersion; public int PackageCheckVersion;
public int PackageMainVersion;
public int PackageVersionID;
public VersionString(string version) public VersionString(string version)
{ {
string[] data = version.Split('.'); var data = version.Split('.');
try try
{ {
PackageVersionID = int.Parse(data[0]); PackageVersionID = int.Parse(data[0]);
@@ -24,42 +19,15 @@ namespace PluginManager.Online.Helpers
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine(version);
throw new Exception("Failed to write Version", ex); throw new Exception("Failed to write Version", ex);
} }
} }
#region operators
public static bool operator >(VersionString s1, VersionString s2)
{
if (s1.PackageVersionID > s2.PackageVersionID) return true;
if (s1.PackageVersionID == s2.PackageVersionID)
{
if (s1.PackageMainVersion > s2.PackageMainVersion) return true;
if (s1.PackageMainVersion == s2.PackageMainVersion && s1.PackageCheckVersion > s2.PackageCheckVersion) return true;
}
return false;
}
public static bool operator <(VersionString s1, VersionString s2) => !(s1 > s2) && s1 != s2;
public static bool operator ==(VersionString s1, VersionString s2)
{
if (s1.PackageVersionID == s2.PackageVersionID && s1.PackageMainVersion == s2.PackageMainVersion && s1.PackageCheckVersion == s2.PackageCheckVersion) return true;
return false;
}
public static bool operator !=(VersionString s1, VersionString s2) => !(s1 == s2);
public static bool operator <=(VersionString s1, VersionString s2) => (s1 < s2 || s1 == s2);
public static bool operator >=(VersionString s1, VersionString s2) => (s1 > s2 || s1 == s2);
#endregion
public override string ToString() public override string ToString()
{ {
return "{PackageID: " + PackageVersionID + ", PackageVersion: " + PackageMainVersion + ", PackageCheckVersion: " + PackageCheckVersion + "}"; return "{PackageID: " + PackageVersionID + ", PackageVersion: " + PackageMainVersion +
", PackageCheckVersion: " + PackageCheckVersion + "}";
} }
public string ToShortString() public string ToShortString()
@@ -69,23 +37,48 @@ namespace PluginManager.Online.Helpers
return $"{PackageVersionID}.{PackageMainVersion}.{PackageCheckVersion}"; return $"{PackageVersionID}.{PackageMainVersion}.{PackageCheckVersion}";
} }
public static VersionString? GetVersionOfPackage(string pakName)
#region operators
public static bool operator >(VersionString s1, VersionString s2)
{ {
if (!Config.PluginVersionsContainsKey(pakName)) if (s1.PackageVersionID > s2.PackageVersionID) return true;
return null; if (s1.PackageVersionID == s2.PackageVersionID)
return new VersionString(Config.GetPluginVersion(pakName)); {
if (s1.PackageMainVersion > s2.PackageMainVersion) return true;
if (s1.PackageMainVersion == s2.PackageMainVersion &&
s1.PackageCheckVersion > s2.PackageCheckVersion) return true;
} }
public static async Task<VersionString?> GetVersionOfPackageFromWeb(string pakName) return false;
{
string url = "https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Versions";
List<string> data = await ServerCom.ReadTextFromURL(url);
string? version = (from item in data
where !item.StartsWith("#") && item.StartsWith(pakName)
select item.Split(',')[1]).FirstOrDefault();
if (version == default || version == null) return null;
return new VersionString(version);
} }
public static bool operator <(VersionString s1, VersionString s2)
{
return !(s1 > s2) && s1 != s2;
} }
public static bool operator ==(VersionString s1, VersionString s2)
{
if (s1.PackageVersionID == s2.PackageVersionID && s1.PackageMainVersion == s2.PackageMainVersion &&
s1.PackageCheckVersion == s2.PackageCheckVersion) return true;
return false;
}
public static bool operator !=(VersionString s1, VersionString s2)
{
return !(s1 == s2);
}
public static bool operator <=(VersionString s1, VersionString s2)
{
return s1 < s2 || s1 == s2;
}
public static bool operator >=(VersionString s1, VersionString s2)
{
return s1 > s2 || s1 == s2;
}
#endregion
} }

View File

@@ -40,10 +40,10 @@ 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", "Installed" }; string[] titles = { "Name", "Description", "Type", "Version" };
data.Add(new[] { "-", "-", "-", "-", "-" }); data.Add(new[] { "-", "-", "-", "-" });
data.Add(titles); data.Add(titles);
data.Add(new[] { "-", "-", "-", "-", "-" }); 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)
@@ -57,11 +57,9 @@ public class PluginsManager
display[0] = content[0]; display[0] = content[0];
display[1] = content[1]; display[1] = content[1];
display[2] = content[2]; display[2] = content[2];
display[3] = (await VersionString.GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0")).ToShortString(); display[3] =
if (Config.PluginConfig.Contains(content[0]) || Config.PluginConfig.Contains(content[0])) (await ServerCom.GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0"))
display[4] = "✓"; .ToShortString();
else
display[4] = "X";
data.Add(display); data.Add(display);
} }
} }
@@ -72,23 +70,21 @@ public class PluginsManager
display[0] = content[0]; display[0] = content[0];
display[1] = content[1]; display[1] = content[1];
display[2] = content[2]; display[2] = content[2];
display[3] = (await VersionString.GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0")).ToShortString(); display[3] =
if (Config.PluginConfig.Contains(content[0]) || Config.PluginConfig.Contains(content[0])) (await ServerCom.GetVersionOfPackageFromWeb(content[0]) ?? new VersionString("0.0.0"))
display[4] = "✓"; .ToShortString();
else
display[4] = "X";
data.Add(display); data.Add(display);
} }
} }
} }
data.Add(new[] { "-", "-", "-", "-", "-" }); data.Add(new[] { "-", "-", "-", "-" });
Console_Utilities.FormatAndAlignTable(data, TableFormat.CENTER_EACH_COLUMN_BASED); Utilities.FormatAndAlignTable(data, TableFormat.CENTER_EACH_COLUMN_BASED);
} }
catch (Exception exception) catch (Exception exception)
{ {
Console.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message); Settings.Variables.outputStream.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message);
Functions.WriteErrFile(exception.ToString()); Functions.WriteErrFile(exception.ToString());
} }
} }
@@ -120,7 +116,7 @@ public class PluginsManager
} }
catch (Exception exception) catch (Exception exception)
{ {
Console.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message); Settings.Variables.outputStream.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message);
Functions.WriteErrFile(exception.ToString()); Functions.WriteErrFile(exception.ToString());
} }

View File

@@ -1,16 +1,18 @@
using PluginManager.Online.Helpers; 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.Net.Http;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using PluginManager.Online.Helpers;
using PluginManager.Others; using PluginManager.Others;
namespace PluginManager.Online namespace PluginManager.Online;
public static class ServerCom
{ {
public static class ServerCom
{
/// <summary> /// <summary>
/// Read all lines from a file async /// Read all lines from a file async
/// </summary> /// </summary>
@@ -18,8 +20,8 @@ namespace PluginManager.Online
/// <returns></returns> /// <returns></returns>
public static async Task<List<string>> ReadTextFromURL(string link) public static async Task<List<string>> ReadTextFromURL(string link)
{ {
string response = await OnlineFunctions.DownloadStringAsync(link); var response = await OnlineFunctions.DownloadStringAsync(link);
string[] lines = response.Split('\n'); var lines = response.Split('\n');
return lines.ToList(); return lines.ToList();
} }
@@ -28,11 +30,12 @@ namespace PluginManager.Online
/// </summary> /// </summary>
/// <param name="URL">The url to the file</param> /// <param name="URL">The url to the file</param>
/// <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, IProgress<long>? downloadedBytes = null) public static async Task DownloadFileAsync(string URL, string location, IProgress<float> progress,
IProgress<long>? downloadedBytes = null)
{ {
using (var client = new System.Net.Http.HttpClient()) using (var client = new HttpClient())
{ {
client.Timeout = TimeSpan.FromMinutes(5); client.Timeout = TimeSpan.FromMinutes(5);
@@ -51,15 +54,15 @@ namespace PluginManager.Online
/// <returns></returns> /// <returns></returns>
public static async Task DownloadFileAsync(string URL, string location) public static async Task DownloadFileAsync(string URL, string location)
{ {
bool isDownloading = true; var isDownloading = true;
float c_progress = 0; float c_progress = 0;
Console_Utilities.ProgressBar pbar = new Console_Utilities.ProgressBar(ProgressBarType.NORMAL) { Max = 100f, NoColor = true }; var pbar = new Utilities.ProgressBar(ProgressBarType.NORMAL) { Max = 100f, NoColor = true };
IProgress<float> progress = new Progress<float>(percent => { c_progress = percent; }); IProgress<float> progress = new Progress<float>(percent => { c_progress = percent; });
Task updateProgressBarTask = new Task(() => var updateProgressBarTask = new Task(() =>
{ {
while (isDownloading) while (isDownloading)
{ {
@@ -79,11 +82,33 @@ namespace PluginManager.Online
pbar.Update(100f); pbar.Update(100f);
isDownloading = false; isDownloading = false;
} }
public static async Task DownloadFileNoProgressAsync(string URL, string location) public static async Task DownloadFileNoProgressAsync(string URL, string location)
{ {
IProgress<float> progress = new Progress<float>(); IProgress<float> progress = new Progress<float>();
await DownloadFileAsync(URL, location, progress); 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;
} }
} }

View File

@@ -1,21 +1,18 @@
using PluginManager.Items; using System;
using PluginManager.Online.Helpers; using System.Threading.Tasks;
using PluginManager.Items;
using PluginManager.Others; using PluginManager.Others;
using System; namespace PluginManager.Online.Updates;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace PluginManager.Online.Updates public class PluginUpdater
{ {
public class PluginUpdater
{
public static async Task<bool> CheckForUpdates(string pakName) public static async Task<bool> CheckForUpdates(string pakName)
{ {
try try
{ {
var webV = await VersionString.GetVersionOfPackageFromWeb(pakName); var webV = await ServerCom.GetVersionOfPackageFromWeb(pakName);
var local = VersionString.GetVersionOfPackage(pakName); var local = ServerCom.GetVersionOfPackage(pakName);
if (local is null) return true; if (local is null) return true;
if (webV is null) return false; if (webV is null) return false;
@@ -23,7 +20,10 @@ namespace PluginManager.Online.Updates
if (webV == local) return false; if (webV == local) return false;
if (webV > local) return true; if (webV > local) return true;
} }
catch (Exception ex) { Console.WriteLine(ex.Message); } catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return false; return false;
@@ -31,21 +31,21 @@ namespace PluginManager.Online.Updates
public static async Task<Update> DownloadUpdateInfo(string pakName) public static async Task<Update> DownloadUpdateInfo(string pakName)
{ {
string url = "https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Versions"; var url = "https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Versions";
List<string> info = await ServerCom.ReadTextFromURL(url); var info = await ServerCom.ReadTextFromURL(url);
VersionString? version = await VersionString.GetVersionOfPackageFromWeb(pakName); var version = await ServerCom.GetVersionOfPackageFromWeb(pakName);
if (version is null) return Update.Empty; if (version is null) return Update.Empty;
Update update = new Update(pakName, string.Join('\n', info), version); var update = new Update(pakName, string.Join('\n', info), version);
return update; return update;
} }
public static async Task Download(string pakName) public static async Task Download(string pakName)
{ {
Console_Utilities.WriteColorText("An update was found for &g" + pakName + "&c. Version: &r" + (await VersionString.GetVersionOfPackageFromWeb(pakName))?.ToShortString() + "&c. Current Version: &y" + VersionString.GetVersionOfPackage(pakName)?.ToShortString()); 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());
await ConsoleCommandsHandler.ExecuteCommad("dwplug " + pakName); await ConsoleCommandsHandler.ExecuteCommad("dwplug " + pakName);
} }
}
} }

View File

@@ -1,16 +1,17 @@
using PluginManager.Online.Helpers; using System;
using PluginManager.Online.Helpers;
namespace PluginManager.Online.Updates namespace PluginManager.Online.Updates;
public class Update
{ {
public class Update public static Update Empty = new(null, null, null);
{
public static Update Empty = new Update(null, null, null); private readonly bool isEmpty;
public string pakName;
public string UpdateMessage;
public VersionString newVersion; public VersionString newVersion;
public string pakName;
private bool isEmpty; public string UpdateMessage;
public Update(string pakName, string updateMessage, VersionString newVersion) public Update(string pakName, string updateMessage, VersionString newVersion)
{ {
@@ -20,17 +21,14 @@ namespace PluginManager.Online.Updates
if (pakName is null && updateMessage is null && newVersion is null) if (pakName is null && updateMessage is null && newVersion is null)
isEmpty = true; isEmpty = true;
} }
public override string ToString() public override string ToString()
{ {
if (isEmpty) if (isEmpty)
throw new System.Exception("The update is EMPTY. Can not print information about an empty update !"); throw new Exception("The update is EMPTY. Can not print information about an empty update !");
return $"Package Name: {this.pakName}\n" + return $"Package Name: {pakName}\n" +
$"Update Message: {UpdateMessage}\n" + $"Update Message: {UpdateMessage}\n" +
$"Version: {newVersion.ToString()}"; $"Version: {newVersion}";
}
} }
} }

View File

@@ -1,29 +1,208 @@
using Discord; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
namespace PluginManager.Others namespace PluginManager.Others;
public static class Utilities
{ {
public static class Console_Utilities private static Dictionary<char, ConsoleColor> Colors = new()
{
public static void Initialize()
{
if (!Config.ContainsKey("TableVariables"))
Config.AddValueToVariables("TableVariables", new Dictionary<string, string> { { "DefaultSpace", "3" } }, false);
if (!Config.ContainsKey("ColorDataBase"))
Config.AddValueToVariables("ColorDataBase", new Dictionary<char, ConsoleColor>()
{ {
{ 'g', ConsoleColor.Green }, { 'g', ConsoleColor.Green },
{ 'b', ConsoleColor.Blue }, { 'b', ConsoleColor.Blue },
{ 'r', ConsoleColor.Red }, { 'r', ConsoleColor.Red },
{ 'm', ConsoleColor.Magenta }, { 'm', ConsoleColor.Magenta },
{ 'y', ConsoleColor.Yellow }, { 'y', ConsoleColor.Yellow }
}, false };
);
if (!Config.ContainsKey("ColorPrefix")) private static char ColorPrefix = '&';
Config.AddValueToVariables("ColorPrefix", '&', false);
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)
Settings.Variables.outputStream.Write(tableCross);
else
Settings.Variables.outputStream.Write(tableWall);
for (var l = 0; l < row.Length; l++)
{
if (row[l][0] == tableLine)
{
for (var i = 0; i < len[l] + 4; ++i)
Settings.Variables.outputStream.Write(tableLine);
}
else if (row[l].Length == len[l])
{
Settings.Variables.outputStream.Write(" ");
Settings.Variables.outputStream.Write(row[l]);
Settings.Variables.outputStream.Write(" ");
}
else
{
var lenHalf = row[l].Length / 2;
for (var i = 0; i < (len[l] + 4) / 2 - lenHalf; ++i)
Settings.Variables.outputStream.Write(" ");
Settings.Variables.outputStream.Write(row[l]);
for (var i = (len[l] + 4) / 2 + lenHalf + 1; i < len[l] + 4; ++i)
Settings.Variables.outputStream.Write(" ");
if (row[l].Length % 2 == 0)
Settings.Variables.outputStream.Write(" ");
}
Settings.Variables.outputStream.Write(row[l][0] == tableLine ? tableCross : tableWall);
}
Settings.Variables.outputStream.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)
{
Settings.Variables.outputStream.Write("\t");
if (row[0] == "-")
Settings.Variables.outputStream.Write("+");
else
Settings.Variables.outputStream.Write("|");
foreach (var s in row)
{
if (s == "-")
{
for (var i = 0; i < maxLen + 4; ++i)
Settings.Variables.outputStream.Write("-");
}
else if (s.Length == maxLen)
{
Settings.Variables.outputStream.Write(" ");
Settings.Variables.outputStream.Write(s);
Settings.Variables.outputStream.Write(" ");
}
else
{
var lenHalf = s.Length / 2;
for (var i = 0; i < div - lenHalf; ++i)
Settings.Variables.outputStream.Write(" ");
Settings.Variables.outputStream.Write(s);
for (var i = div + lenHalf + 1; i < maxLen + 4; ++i)
Settings.Variables.outputStream.Write(" ");
if (s.Length % 2 == 0)
Settings.Variables.outputStream.Write(" ");
}
if (s == "-")
Settings.Variables.outputStream.Write("+");
else
Settings.Variables.outputStream.Write("|");
}
Settings.Variables.outputStream.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] = " ";
Settings.Variables.outputStream.Write(data[i][j]);
for (var k = 0; k < widths[j] - data[i][j].Length + 1 + space_between_columns; k++)
Settings.Variables.outputStream.Write(" ");
}
Settings.Variables.outputStream.WriteLine();
}
return;
}
throw new Exception("Unknown type of table");
}
public static void WriteColorText(string text, bool appendNewLineAtEnd = true)
{
if (Console.Out != Settings.Variables.outputStream)
{
Settings.Variables.outputStream.Write(text);
if (appendNewLineAtEnd)
Settings.Variables.outputStream.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
{
Settings.Variables.outputStream.Write(input[i]);
}
Console.ForegroundColor = initialForeGround;
if (appendNewLineAtEnd)
Settings.Variables.outputStream.WriteLine();
} }
@@ -32,8 +211,16 @@ namespace PluginManager.Others
/// </summary> /// </summary>
public class ProgressBar public class ProgressBar
{ {
private readonly int BarLength = 32;
private bool isRunning;
private int position = 1;
private bool positive = true;
public ProgressBar(ProgressBarType type) public ProgressBar(ProgressBarType type)
{ {
if (Settings.Variables.outputStream != Console.Out)
throw new Exception("This class (or function) can be used with console only. For UI please use another approach.");
this.type = type; this.type = type;
} }
@@ -44,12 +231,6 @@ namespace PluginManager.Others
public int TotalLength { get; private set; } public int TotalLength { get; private set; }
private int BarLength = 32;
private int position = 1;
private bool positive = true;
private bool isRunning;
public async void Start() public async void Start()
{ {
@@ -62,7 +243,7 @@ namespace PluginManager.Others
while (isRunning) while (isRunning)
{ {
UpdateNoEnd(); UpdateNoEnd();
await System.Threading.Tasks.Task.Delay(100); await Task.Delay(100);
} }
} }
@@ -79,7 +260,7 @@ namespace PluginManager.Others
while (isRunning) while (isRunning)
{ {
UpdateNoEnd(message); UpdateNoEnd(message);
await System.Threading.Tasks.Task.Delay(100); await Task.Delay(100);
} }
} }
@@ -99,10 +280,10 @@ namespace PluginManager.Others
if (message is not null) if (message is not null)
{ {
Console.CursorLeft = 0; Console.CursorLeft = 0;
for (int i = 0; i < BarLength + message.Length + 1; i++) for (var i = 0; i < BarLength + message.Length + 1; i++)
Console.Write(" "); Settings.Variables.outputStream.Write(" ");
Console.CursorLeft = 0; Console.CursorLeft = 0;
Console.WriteLine(message); Settings.Variables.outputStream.WriteLine(message);
} }
} }
@@ -117,16 +298,14 @@ namespace PluginManager.Others
private void UpdateNoEnd(string message) private void UpdateNoEnd(string message)
{ {
Console.CursorLeft = 0; Console.CursorLeft = 0;
Console.Write("["); Settings.Variables.outputStream.Write("[");
for (int i = 1; i <= position; i++) for (var i = 1; i <= position; i++)
Console.Write(" "); Settings.Variables.outputStream.Write(" ");
Console.Write("<==()==>"); Settings.Variables.outputStream.Write("<==()==>");
position += positive ? 1 : -1; position += positive ? 1 : -1;
for (int i = position; i <= BarLength - 1 - (positive ? 0 : 2); i++) for (var i = position; i <= BarLength - 1 - (positive ? 0 : 2); i++)
Console.Write(" "); Settings.Variables.outputStream.Write(" ");
Console.Write("] " + message); Settings.Variables.outputStream.Write("] " + message);
if (position == BarLength - 1 || position == 1) if (position == BarLength - 1 || position == 1)
@@ -136,16 +315,14 @@ namespace PluginManager.Others
private void UpdateNoEnd() private void UpdateNoEnd()
{ {
Console.CursorLeft = 0; Console.CursorLeft = 0;
Console.Write("["); Settings.Variables.outputStream.Write("[");
for (int i = 1; i <= position; i++) for (var i = 1; i <= position; i++)
Console.Write(" "); Settings.Variables.outputStream.Write(" ");
Console.Write("<==()==>"); Settings.Variables.outputStream.Write("<==()==>");
position += positive ? 1 : -1; position += positive ? 1 : -1;
for (int i = position; i <= BarLength - 1 - (positive ? 0 : 2); i++) for (var i = position; i <= BarLength - 1 - (positive ? 0 : 2); i++)
Console.Write(" "); Settings.Variables.outputStream.Write(" ");
Console.Write("]"); Settings.Variables.outputStream.Write("]");
if (position == BarLength - 1 || position == 1) if (position == BarLength - 1 || position == 1)
@@ -155,217 +332,34 @@ namespace PluginManager.Others
private void UpdateNormal(float progress) private void UpdateNormal(float progress)
{ {
Console.CursorLeft = 0; Console.CursorLeft = 0;
Console.Write("["); Settings.Variables.outputStream.Write("[");
Console.CursorLeft = BarLength; Console.CursorLeft = BarLength;
Console.Write("]"); Settings.Variables.outputStream.Write("]");
Console.CursorLeft = 1; Console.CursorLeft = 1;
float onechunk = 30.0f / Max; var onechunk = 30.0f / Max;
int position = 1; var position = 1;
for (int i = 0; i < onechunk * progress; i++) for (var i = 0; i < onechunk * progress; i++)
{ {
Console.BackgroundColor = NoColor ? ConsoleColor.Black : this.Color; Console.BackgroundColor = NoColor ? ConsoleColor.Black : Color;
Console.CursorLeft = position++; Console.CursorLeft = position++;
Console.Write("#"); Settings.Variables.outputStream.Write("#");
} }
for (int i = position; i < BarLength; i++) for (var i = position; i < BarLength; i++)
{ {
Console.BackgroundColor = NoColor ? ConsoleColor.Black : ConsoleColor.DarkGray; Console.BackgroundColor = NoColor ? ConsoleColor.Black : ConsoleColor.DarkGray;
Console.CursorLeft = position++; Console.CursorLeft = position++;
Console.Write(" "); Settings.Variables.outputStream.Write(" ");
} }
Console.CursorLeft = BarLength + 4; Console.CursorLeft = BarLength + 4;
Console.BackgroundColor = ConsoleColor.Black; Console.BackgroundColor = ConsoleColor.Black;
if (progress.CanAproximateTo(Max)) if (progress.CanAproximateTo(Max))
Console.Write(progress + " % ✓"); Settings.Variables.outputStream.Write(progress + " % ✓");
else else
Console.Write(MathF.Round(progress, 2) + " % "); Settings.Variables.outputStream.Write(MathF.Round(progress, 2) + " % ");
}
}
private static bool CanAproximateTo(this float f, float y) => (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)
{
char tableLine = '-';
char tableCross = '+';
char tableWall = '|';
int[] len = new int[data[0].Length];
foreach (var line in data)
for (int i = 0; i < line.Length; i++)
if (line[i].Length > len[i])
len[i] = line[i].Length;
foreach (string[] row in data)
{
if (row[0][0] == tableLine)
Console.Write(tableCross);
else
Console.Write(tableWall);
for (int l = 0; l < row.Length; l++)
{
if (row[l][0] == tableLine)
{
for (int 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
{
int lenHalf = row[l].Length / 2;
for (int i = 0; i < ((len[l] + 4) / 2 - lenHalf); ++i)
Console.Write(" ");
Console.Write(row[l]);
for (int 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)
{
int maxLen = 0;
foreach (string[] row in data)
foreach (string s in row)
if (s.Length > maxLen)
maxLen = s.Length;
int div = (maxLen + 4) / 2;
foreach (string[] row in data)
{
Console.Write("\t");
if (row[0] == "-")
Console.Write("+");
else
Console.Write("|");
foreach (string s in row)
{
if (s == "-")
{
for (int i = 0; i < maxLen + 4; ++i)
Console.Write("-");
}
else if (s.Length == maxLen)
{
Console.Write(" ");
Console.Write(s);
Console.Write(" ");
}
else
{
int lenHalf = s.Length / 2;
for (int i = 0; i < div - lenHalf; ++i)
Console.Write(" ");
Console.Write(s);
for (int 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)
{
int[] widths = new int[data[0].Length];
int space_between_columns = int.Parse(Config.GetValue<Dictionary<string, string>>("TableVariables")?["DefaultSpace"]!);
for (int i = 0; i < data.Count; i++)
{
for (int j = 0; j < data[i].Length; j++)
{
if (data[i][j].Length > widths[j])
widths[j] = data[i][j].Length;
}
}
for (int i = 0; i < data.Count; i++)
{
for (int j = 0; j < data[i].Length; j++)
{
if (data[i][j] == "-")
data[i][j] = " ";
Console.Write(data[i][j]);
for (int 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)
{
ConsoleColor initialForeGround = Console.ForegroundColor;
char[] input = text.ToCharArray();
for (int i = 0; i < input.Length; i++)
{
if (input[i] == Config.GetValue<char>("ColorPrefix"))
{
if (i + 1 < input.Length)
{
if (Config.GetValue<Dictionary<char, ConsoleColor>>("ColorDataBase")!.ContainsKey(input[i + 1]))
{
Console.ForegroundColor = Config.GetValue<Dictionary<char, ConsoleColor>>("ColorDataBase")![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();
} }
} }
} }

View File

@@ -1,13 +1,14 @@
using PluginManager.Interfaces; namespace PluginManager.Others;
namespace PluginManager.Others;
/// <summary> /// <summary>
/// A list of operating systems /// A list of operating systems
/// </summary> /// </summary>
public enum OperatingSystem public enum OperatingSystem
{ {
WINDOWS, LINUX, MAC_OS, UNKNOWN WINDOWS,
LINUX,
MAC_OS,
UNKNOWN
} }
/// <summary> /// <summary>
@@ -15,22 +16,47 @@ public enum OperatingSystem
/// </summary> /// </summary>
public enum Error public enum Error
{ {
UNKNOWN_ERROR, GUILD_NOT_FOUND, STREAM_NOT_FOUND, INVALID_USER, INVALID_CHANNEL, INVALID_PERMISSIONS 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 { NONE, INFO, WARNING, ERROR, CRITICAL } public enum OutputLogLevel
{
NONE,
INFO,
WARNING,
ERROR,
CRITICAL
}
/// <summary> public enum UnzipProgressType
/// Plugin Type {
/// </summary> PercentageFromNumberOfFiles,
public enum PluginType { Command, Event, Unknown } PercentageFromTotalSize
}
public enum UnzipProgressType { PercentageFromNumberOfFiles, PercentageFromTotalSize } public enum TableFormat
{
CENTER_EACH_COLUMN_BASED,
CENTER_OVERALL_LENGTH,
DEFAULT
}
public enum TableFormat { CENTER_EACH_COLUMN_BASED, CENTER_OVERALL_LENGTH, DEFAULT } public enum SaveType
{
NORMAL,
BACKUP
}
public enum SaveType { NORMAL, BACKUP } public enum ProgressBarType
public enum ProgressBarType { NORMAL, NO_END } {
NORMAL,
NO_END
}

View File

@@ -1,23 +1,26 @@
using System.IO.Compression; using System;
using System.IO;
using System;
using System.Threading.Tasks;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography; using System.Security.Cryptography;
using Discord.WebSocket;
using PluginManager.Items;
using System.Threading;
using System.Text.Json;
using System.Text; using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace PluginManager.Others using Discord.WebSocket;
using PluginManager.Items;
namespace PluginManager.Others;
/// <summary>
/// A special class with functions
/// </summary>
public static class Functions
{ {
/// <summary>
/// A special class with functions
/// </summary>
public static class Functions
{
/// <summary> /// <summary>
/// The location for the Resources folder /// The location for the Resources folder
/// </summary> /// </summary>
@@ -61,12 +64,11 @@ namespace PluginManager.Others
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))
{
foreach (var entry in zip.Entries) foreach (var entry in zip.Entries)
{
if (entry.Name == FileName || entry.FullName == FileName) if (entry.Name == FileName || entry.FullName == FileName)
{ using (var s = entry.Open())
using (Stream s = entry.Open()) using (var reader = new StreamReader(s))
using (StreamReader reader = new StreamReader(s))
{ {
textValue = await reader.ReadToEndAsync(); textValue = await reader.ReadToEndAsync();
reader.Close(); reader.Close();
@@ -74,7 +76,7 @@ namespace PluginManager.Others
fs.Close(); fs.Close();
} }
} }
}
return textValue; return textValue;
} }
catch catch
@@ -82,7 +84,6 @@ namespace PluginManager.Others
await Task.Delay(100); await Task.Delay(100);
return await ReadFromPakAsync(FileName, archFile); return await ReadFromPakAsync(FileName, archFile);
} }
} }
@@ -92,7 +93,7 @@ namespace PluginManager.Others
/// <param name="LogMessage">The message to be wrote</param> /// <param name="LogMessage">The message to be wrote</param>
public static void WriteLogFile(string LogMessage) public static void WriteLogFile(string LogMessage)
{ {
string logsPath = logFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Log.txt"; var logsPath = logFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Log.txt";
Directory.CreateDirectory(logFolder); Directory.CreateDirectory(logFolder);
File.AppendAllText(logsPath, LogMessage + " \n"); File.AppendAllText(logsPath, LogMessage + " \n");
} }
@@ -103,7 +104,8 @@ namespace PluginManager.Others
/// <param name="ErrMessage">The message to be wrote</param> /// <param name="ErrMessage">The message to be wrote</param>
public static void WriteErrFile(string ErrMessage) public static void WriteErrFile(string ErrMessage)
{ {
string errPath = errFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Error.txt"; var errPath = errFolder +
$"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Error.txt";
Directory.CreateDirectory(errFolder); Directory.CreateDirectory(errFolder);
File.AppendAllText(errPath, ErrMessage + " \n"); File.AppendAllText(errPath, ErrMessage + " \n");
} }
@@ -113,66 +115,48 @@ namespace PluginManager.Others
WriteErrFile(ex.ToString()); WriteErrFile(ex.ToString());
} }
/// <summary>
/// Merge one array of strings into one string
/// </summary>
/// <param name="s">The array of strings</param>
/// <param name="indexToStart">The index from where the merge should start (included)</param>
/// <returns>A string built based on the array</returns>
public static string MergeStrings(this string[] s, int indexToStart)
{
string r = "";
int len = s.Length;
if (len <= indexToStart) return "";
for (int i = indexToStart; i < len - 1; ++i)
{
r += s[i] + " ";
}
r += s[len - 1];
return r;
}
/// <summary> /// <summary>
/// Get the Operating system you are runnin on /// Get the Operating system you are runnin on
/// </summary> /// </summary>
/// <returns>An Operating system</returns> /// <returns>An Operating system</returns>
public static OperatingSystem GetOperatingSystem() public static OperatingSystem GetOperatingSystem()
{ {
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) return OperatingSystem.WINDOWS; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return OperatingSystem.WINDOWS;
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux)) return OperatingSystem.LINUX; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) return OperatingSystem.LINUX;
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX)) return OperatingSystem.MAC_OS; if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) return OperatingSystem.MAC_OS;
return OperatingSystem.UNKNOWN; return OperatingSystem.UNKNOWN;
} }
public static List<string> GetArguments(SocketMessage message) public static List<string> GetArguments(SocketMessage message)
{ {
Command command = new Command(message); var command = new Command(message);
return command.Arguments; return command.Arguments;
} }
/// <summary> /// <summary>
/// Copy one Stream to another <see langword="async"/> /// Copy one Stream to another <see langword="async" />
/// </summary> /// </summary>
/// <param name="stream">The base stream</param> /// <param name="stream">The base stream</param>
/// <param name="destination">The destination stream</param> /// <param name="destination">The destination stream</param>
/// <param name="bufferSize">The buffer to read</param> /// <param name="bufferSize">The buffer to read</param>
/// <param name="progress">The progress</param> /// <param name="progress">The progress</param>
/// <param name="cancellationToken">The cancellation token</param> /// <param name="cancellationToken">The cancellation token</param>
/// <exception cref="ArgumentNullException">Triggered if any <see cref="Stream"/> is empty</exception> /// <exception cref="ArgumentNullException">Triggered if any <see cref="Stream" /> is empty</exception>
/// <exception cref="ArgumentOutOfRangeException">Triggered if <paramref name="bufferSize"/> is less then or equal to 0</exception> /// <exception cref="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, IProgress<long>? progress = null, CancellationToken cancellationToken = default) public static async Task CopyToOtherStreamAsync(this Stream stream, Stream destination, int bufferSize,
IProgress<long>? progress = null,
CancellationToken cancellationToken = default)
{ {
if (stream == null) throw new ArgumentNullException(nameof(stream)); if (stream == null) throw new ArgumentNullException(nameof(stream));
if (destination == null) throw new ArgumentNullException(nameof(destination)); if (destination == null) throw new ArgumentNullException(nameof(destination));
if (bufferSize <= 0) throw new ArgumentOutOfRangeException(nameof(bufferSize)); if (bufferSize <= 0) throw new ArgumentOutOfRangeException(nameof(bufferSize));
if (!stream.CanRead) throw new InvalidOperationException("The stream is not readable."); if (!stream.CanRead) throw new InvalidOperationException("The stream is not readable.");
if (!destination.CanWrite) throw new ArgumentException("Destination stream is not writable", nameof(destination)); if (!destination.CanWrite)
throw new ArgumentException("Destination stream is not writable", nameof(destination));
byte[] 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)
@@ -181,7 +165,6 @@ namespace PluginManager.Others
totalBytesRead += bytesRead; totalBytesRead += bytesRead;
progress?.Report(totalBytesRead); progress?.Report(totalBytesRead);
} }
} }
/// <summary> /// <summary>
@@ -192,16 +175,17 @@ 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, UnzipProgressType type) public static async Task ExtractArchive(string zip, string folder, IProgress<float> progress,
UnzipProgressType type)
{ {
Directory.CreateDirectory(folder); Directory.CreateDirectory(folder);
using (ZipArchive archive = ZipFile.OpenRead(zip)) using (var archive = ZipFile.OpenRead(zip))
{ {
if (type == UnzipProgressType.PercentageFromNumberOfFiles) if (type == UnzipProgressType.PercentageFromNumberOfFiles)
{ {
int totalZIPFiles = archive.Entries.Count(); var totalZIPFiles = archive.Entries.Count();
int currentZIPFile = 0; var currentZIPFile = 0;
foreach (ZipArchiveEntry entry in archive.Entries) foreach (var entry in archive.Entries)
{ {
if (entry.FullName.EndsWith("/")) // it is a folder if (entry.FullName.EndsWith("/")) // it is a folder
Directory.CreateDirectory(Path.Combine(folder, entry.FullName)); Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
@@ -213,7 +197,7 @@ namespace PluginManager.Others
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}"); Settings.Variables.outputStream.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
} }
currentZIPFile++; currentZIPFile++;
@@ -226,11 +210,11 @@ namespace PluginManager.Others
{ {
ulong zipSize = 0; ulong zipSize = 0;
foreach (ZipArchiveEntry entry in archive.Entries) foreach (var entry in archive.Entries)
zipSize += (ulong)entry.CompressedLength; zipSize += (ulong)entry.CompressedLength;
ulong currentSize = 0; ulong currentSize = 0;
foreach (ZipArchiveEntry entry in archive.Entries) foreach (var entry in archive.Entries)
{ {
if (entry.FullName.EndsWith("/")) if (entry.FullName.EndsWith("/"))
{ {
@@ -245,7 +229,7 @@ namespace PluginManager.Others
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}"); Settings.Variables.outputStream.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
} }
await Task.Delay(10); await Task.Delay(10);
@@ -256,32 +240,6 @@ namespace PluginManager.Others
} }
} }
/// <summary>
/// Convert Bytes to highest measurement unit possible
/// </summary>
/// <param name="bytes">The amount of bytes</param>
/// <returns></returns>
public static (double, string) ConvertBytes(long bytes)
{
List<string> units = new List<string>()
{
"B",
"KB",
"MB",
"GB",
"TB"
};
int i = 0;
while (bytes >= 1024)
{
i++;
bytes /= 1024;
}
return (bytes, units[i]);
}
/// <summary> /// <summary>
/// Save to JSON file /// Save to JSON file
/// </summary> /// </summary>
@@ -291,7 +249,7 @@ namespace PluginManager.Others
/// <returns></returns> /// <returns></returns>
public static async Task SaveToJsonFile<T>(string file, T Data) public static async Task SaveToJsonFile<T>(string file, T Data)
{ {
MemoryStream str = new MemoryStream(); var str = new MemoryStream();
await JsonSerializer.SerializeAsync(str, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true }); await JsonSerializer.SerializeAsync(str, Data, typeof(T), new JsonSerializerOptions { WriteIndented = true });
await File.WriteAllBytesAsync(file, str.ToArray()); await File.WriteAllBytesAsync(file, str.ToArray());
} }
@@ -315,35 +273,6 @@ namespace PluginManager.Others
return (obj ?? default)!; return (obj ?? default)!;
} }
/// <summary>
/// Check if all words from <paramref name="str"/> are in <paramref name="baseString"/><br/>
/// This function returns true if<br/>
/// 1. The <paramref name="str"/> is part of <paramref name="baseString"/><br/>
/// 2. The words (split by a space) of <paramref name="str"/> are located (separately) in <paramref name="baseString"/> <br/>
/// <example>
/// The following example will return <see langword="TRUE"/><br/>
/// <c>STRContains("Hello World !", "I type word Hello and then i typed word World !")</c><br/>
/// The following example will return <see langword="TRUE"/><br/>
/// <c>STRContains("Hello World !", "I typed Hello World !" </c><br/>
/// The following example will return <see langword="TRUE"/><br/>
/// <c>STRContains("Hello World", "I type World then Hello")</c><br/>
/// The following example will return <see langword="FALSE"/><br/>
/// <c>STRContains("Hello World !", "I typed Hello World")</c><br/>
/// </example>
/// </summary>
/// <param name="str">The string you are checking</param>
/// <param name="baseString">The main string that should contain <paramref name="str"/></param>
/// <returns></returns>
public static bool STRContains(this string str, string baseString)
{
if (baseString.Contains(str)) return true;
string[] array = str.Split(' ');
foreach (var s in array)
if (!baseString.Contains(s))
return false;
return true;
}
public static bool TryReadValueFromJson(string input, string codeName, out JsonElement element) public static bool TryReadValueFromJson(string input, string codeName, out JsonElement element)
{ {
Stream text; Stream text;
@@ -361,12 +290,11 @@ namespace PluginManager.Others
public static string CreateMD5(string input) public static string CreateMD5(string input)
{ {
using (MD5 md5 = MD5.Create()) using (var md5 = MD5.Create())
{ {
byte[] inputBytes = Encoding.ASCII.GetBytes(input); var inputBytes = Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes); var hashBytes = md5.ComputeHash(inputBytes);
return Convert.ToHexString(hashBytes); return Convert.ToHexString(hashBytes);
} }
} }
}
} }

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
@@ -17,6 +17,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Discord.Net" Version="3.7.2" /> <PackageReference Include="Discord.Net" Version="3.7.2" />
<PackageReference Include="System.Data.SQLite" Version="1.0.116" />
<PackageReference Include="Terminal.Gui" Version="1.8.2" /> <PackageReference Include="Terminal.Gui" Version="1.8.2" />
</ItemGroup> </ItemGroup>

View File

@@ -0,0 +1,21 @@
using System.IO;
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 TextWriter outputStream;
}
public static SqlDatabase sqlDatabase;
}
}

View File

@@ -7,6 +7,12 @@ 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}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlashCommands", "..\DiscordBotItems\Plugins\SlashCommands\SlashCommands.csproj", "{C2D73BE8-997B-4A4A-8EA5-989BE33EE1DD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LevelingSystem", "..\DiscordBotItems\Plugins\LevelingSystem\LevelingSystem.csproj", "{0138F343-BBB9-4D5F-B499-D9C2978BE9AA}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -21,6 +27,18 @@ 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
{878DFE01-4596-4EBC-9651-0679598CE794}.Debug|Any CPU.Build.0 = Debug|Any CPU
{878DFE01-4596-4EBC-9651-0679598CE794}.Release|Any CPU.ActiveCfg = Release|Any CPU
{878DFE01-4596-4EBC-9651-0679598CE794}.Release|Any CPU.Build.0 = Release|Any CPU
{C2D73BE8-997B-4A4A-8EA5-989BE33EE1DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2D73BE8-997B-4A4A-8EA5-989BE33EE1DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2D73BE8-997B-4A4A-8EA5-989BE33EE1DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2D73BE8-997B-4A4A-8EA5-989BE33EE1DD}.Release|Any CPU.Build.0 = Release|Any CPU
{0138F343-BBB9-4D5F-B499-D9C2978BE9AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0138F343-BBB9-4D5F-B499-D9C2978BE9AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0138F343-BBB9-4D5F-B499-D9C2978BE9AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0138F343-BBB9-4D5F-B499-D9C2978BE9AA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE