Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d5c90323a | |||
| 5b01b15216 | |||
| 4f18f505f4 | |||
| 2d3566a01a | |||
| 22f2cd4e59 | |||
| 1683234376 | |||
| 69d99b4189 | |||
| 4a5e0ef2f3 | |||
| 79731a9704 | |||
| bd53d099d1 | |||
| de61f5de88 | |||
| 0527d43dd2 | |||
| e3511cd96b | |||
| d355d3c9b7 | |||
| 5bb13aa4a6 | |||
| 655f5e2ce0 | |||
| 9014d78a7d | |||
| 1c026e7f49 | |||
| d32b3902c9 | |||
| e5f3aff39a | |||
| 11ec02ef68 | |||
| cad19935d5 | |||
| 47f88f167f | |||
| 9d6c335799 | |||
| cbaf552e7a | |||
| a4975a4578 | |||
| 725d02d152 | |||
| ae7118e89a | |||
| cad3bb5b75 | |||
| 269d7d56ff | |||
| 403c023191 | |||
| 3f7a8e04d4 | |||
| 0abbd24b86 | |||
| 21f1975fbc | |||
| d6f072904e | |||
| 6fc491a0d6 | |||
| 7bc9db03f0 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -98,6 +98,7 @@ StyleCopReport.xml
|
|||||||
*.pidb
|
*.pidb
|
||||||
*.svclog
|
*.svclog
|
||||||
*.scc
|
*.scc
|
||||||
|
*.code-workspace
|
||||||
|
|
||||||
# Chutzpah Test files
|
# Chutzpah Test files
|
||||||
_Chutzpah*
|
_Chutzpah*
|
||||||
@@ -368,3 +369,5 @@ FodyWeavers.xsd
|
|||||||
#folders
|
#folders
|
||||||
/Plugins/
|
/Plugins/
|
||||||
/DiscordBot.rar
|
/DiscordBot.rar
|
||||||
|
/DiscordBot/Data/
|
||||||
|
/DiscordBot/Updater/
|
||||||
@@ -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>
|
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
using System.Linq;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
|
||||||
|
|
||||||
using PluginManager;
|
using PluginManager;
|
||||||
using PluginManager.Interfaces;
|
using PluginManager.Interfaces;
|
||||||
using PluginManager.Loaders;
|
using PluginManager.Loaders;
|
||||||
@@ -43,19 +41,16 @@ internal class Help : DBCommand
|
|||||||
/// The main body of the command
|
/// The main body of the command
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">The command context</param>
|
/// <param name="context">The command context</param>
|
||||||
public void ExecuteServer(SocketCommandContext context)
|
public void ExecuteServer(CmdArgs args)
|
||||||
{
|
{
|
||||||
var args = Functions.GetArguments(context.Message);
|
if (args.arguments is not null)
|
||||||
if (args.Count != 0)
|
|
||||||
{
|
{
|
||||||
foreach (var item in args)
|
var e = GenerateHelpCommand(args.arguments[0]);
|
||||||
{
|
|
||||||
var e = GenerateHelpCommand(item);
|
|
||||||
if (e is null)
|
if (e is null)
|
||||||
context.Channel.SendMessageAsync("Unknown Command " + item);
|
args.context.Channel.SendMessageAsync("Unknown Command " + args.arguments[0]);
|
||||||
else
|
else
|
||||||
context.Channel.SendMessageAsync(embed: e.Build());
|
args.context.Channel.SendMessageAsync(embed: e.Build());
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -66,25 +61,27 @@ 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 + " ";
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
if(adminCommands.Length > 0)
|
||||||
embedBuilder.AddField("Admin Commands", adminCommands);
|
embedBuilder.AddField("Admin Commands", adminCommands);
|
||||||
|
if(normalCommands.Length > 0)
|
||||||
embedBuilder.AddField("Normal Commands", normalCommands);
|
embedBuilder.AddField("Normal Commands", normalCommands);
|
||||||
context.Channel.SendMessageAsync(embed: embedBuilder.Build());
|
args.context.Channel.SendMessageAsync(embed: embedBuilder.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
@@ -1,102 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using Discord.WebSocket;
|
|
||||||
using PluginManager.Interfaces;
|
|
||||||
using PluginManager.Others;
|
|
||||||
using PluginManager.Others.Permissions;
|
|
||||||
using DiscordLibCommands = Discord.Commands;
|
|
||||||
using DiscordLib = Discord;
|
|
||||||
using OperatingSystem = PluginManager.Others.OperatingSystem;
|
|
||||||
|
|
||||||
namespace DiscordBot.Discord.Commands;
|
|
||||||
|
|
||||||
internal class Restart : DBCommand
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Command name
|
|
||||||
/// </summary>
|
|
||||||
public string Command => "restart";
|
|
||||||
|
|
||||||
public List<string> Aliases => null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command Description
|
|
||||||
/// </summary>
|
|
||||||
public string Description => "Restart the bot";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Command usage
|
|
||||||
/// </summary>
|
|
||||||
public string Usage => "restart [-p | -c | -args | -cmd] <args>";
|
|
||||||
|
|
||||||
/// <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 ExecuteServer(DiscordLibCommands.SocketCommandContext context)
|
|
||||||
{
|
|
||||||
var args = Functions.GetArguments(context.Message);
|
|
||||||
var OS = Functions.GetOperatingSystem();
|
|
||||||
if (args.Count == 0)
|
|
||||||
{
|
|
||||||
switch (OS)
|
|
||||||
{
|
|
||||||
case OperatingSystem.WINDOWS:
|
|
||||||
Process.Start("./DiscordBot.exe");
|
|
||||||
break;
|
|
||||||
case OperatingSystem.LINUX:
|
|
||||||
case OperatingSystem.MAC_OS:
|
|
||||||
Process.Start("./DiscordBot");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (args[0])
|
|
||||||
{
|
|
||||||
case "-p":
|
|
||||||
case "-poweroff":
|
|
||||||
case "-c":
|
|
||||||
case "-close":
|
|
||||||
Environment.Exit(0);
|
|
||||||
break;
|
|
||||||
case "-cmd":
|
|
||||||
case "-args":
|
|
||||||
var cmd = "--args";
|
|
||||||
|
|
||||||
if (args.Count > 1)
|
|
||||||
for (var i = 1; i < args.Count; i++)
|
|
||||||
cmd += $" {args[i]}";
|
|
||||||
|
|
||||||
|
|
||||||
switch (OS)
|
|
||||||
{
|
|
||||||
case OperatingSystem.WINDOWS:
|
|
||||||
Functions.WriteLogFile("Restarting the bot with the following arguments: \"" + cmd + "\"");
|
|
||||||
Process.Start("./DiscordBot.exe", cmd);
|
|
||||||
break;
|
|
||||||
case OperatingSystem.LINUX:
|
|
||||||
//case PluginManager.Others.OperatingSystem.MAC_OS: ?? - not tested
|
|
||||||
Process.Start("./DiscordBot", cmd);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Environment.Exit(0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
await context.Channel.SendMessageAsync("Invalid argument. Use `help restart` to see the usage.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Discord;
|
using Discord;
|
||||||
@@ -8,8 +7,6 @@ using Discord.WebSocket;
|
|||||||
|
|
||||||
using PluginManager;
|
using PluginManager;
|
||||||
|
|
||||||
using static PluginManager.Others.Functions;
|
|
||||||
|
|
||||||
namespace DiscordBot.Discord.Core;
|
namespace DiscordBot.Discord.Core;
|
||||||
|
|
||||||
internal class Boot
|
internal class Boot
|
||||||
@@ -63,7 +60,16 @@ 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,
|
||||||
|
|
||||||
|
GatewayIntents = GatewayIntents.All
|
||||||
|
};
|
||||||
|
|
||||||
client = new DiscordSocketClient(config);
|
client = new DiscordSocketClient(config);
|
||||||
service = new CommandService();
|
service = new CommandService();
|
||||||
@@ -71,11 +77,15 @@ 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) ;
|
||||||
}
|
}
|
||||||
@@ -87,27 +97,38 @@ internal class Boot
|
|||||||
client.Log += Log;
|
client.Log += Log;
|
||||||
client.LoggedIn += LoggedIn;
|
client.LoggedIn += LoggedIn;
|
||||||
client.Ready += Ready;
|
client.Ready += Ready;
|
||||||
|
client.Disconnected += Client_Disconnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task Client_LoggedOut()
|
private Task Client_Disconnected(Exception arg)
|
||||||
{
|
{
|
||||||
WriteLogFile("Successfully Logged Out");
|
if (arg.Message.Contains("401"))
|
||||||
Log(new LogMessage(LogSeverity.Info, "Boot", "Successfully logged out from discord !"));
|
{
|
||||||
|
Config.Variables.RemoveKey("token");
|
||||||
|
Program.GenerateStartUI("The token is invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.WriteErrFile(arg);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task Client_LoggedOut()
|
||||||
|
{
|
||||||
|
Logger.WriteLine("Successfully Logged Out");
|
||||||
|
await Log(new LogMessage(LogSeverity.Info, "Boot", "Successfully logged out from discord !"));
|
||||||
|
}
|
||||||
|
|
||||||
private Task Ready()
|
private Task Ready()
|
||||||
{
|
{
|
||||||
Console.Title = "ONLINE";
|
Console.Title = "ONLINE";
|
||||||
isReady = true;
|
isReady = true;
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task LoggedIn()
|
private Task LoggedIn()
|
||||||
{
|
{
|
||||||
Console.Title = "CONNECTED";
|
Console.Title = "CONNECTED";
|
||||||
WriteLogFile("The bot has been logged in at " + DateTime.Now.ToShortDateString() + " (" +
|
Logger.WriteLine("The bot has been logged in at " + DateTime.Now.ToShortDateString() + " (" +
|
||||||
DateTime.Now.ToShortTimeString() + ")"
|
DateTime.Now.ToShortTimeString() + ")"
|
||||||
);
|
);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
@@ -119,7 +140,7 @@ internal class Boot
|
|||||||
{
|
{
|
||||||
case LogSeverity.Error:
|
case LogSeverity.Error:
|
||||||
case LogSeverity.Critical:
|
case LogSeverity.Critical:
|
||||||
WriteErrFile(message.Message);
|
Logger.WriteErrFile(message.Message);
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
Console.WriteLine("[ERROR] " + message.Message);
|
Console.WriteLine("[ERROR] " + message.Message);
|
||||||
@@ -129,7 +150,7 @@ internal class Boot
|
|||||||
|
|
||||||
case LogSeverity.Info:
|
case LogSeverity.Info:
|
||||||
case LogSeverity.Debug:
|
case LogSeverity.Debug:
|
||||||
WriteLogFile(message.Message);
|
Logger.WriteLogFile(message.Message);
|
||||||
|
|
||||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||||
Console.WriteLine("[INFO] " + message.Message);
|
Console.WriteLine("[INFO] " + message.Message);
|
||||||
@@ -141,5 +162,4 @@ internal class Boot
|
|||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,17 @@
|
|||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
using PluginManager.Loaders;
|
using PluginManager.Loaders;
|
||||||
using PluginManager.Others;
|
using PluginManager.Others;
|
||||||
using PluginManager.Others.Permissions;
|
using PluginManager.Others.Permissions;
|
||||||
|
|
||||||
|
using static PluginManager.Logger;
|
||||||
|
|
||||||
namespace DiscordBot.Discord.Core;
|
namespace DiscordBot.Discord.Core;
|
||||||
|
|
||||||
internal class CommandHandler
|
internal class CommandHandler
|
||||||
@@ -28,6 +31,7 @@ internal class CommandHandler
|
|||||||
this.client = client;
|
this.client = client;
|
||||||
this.commandService = commandService;
|
this.commandService = commandService;
|
||||||
this.botPrefix = botPrefix;
|
this.botPrefix = botPrefix;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -37,9 +41,37 @@ 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 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The message handler for the bot
|
/// The message handler for the bot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -47,49 +79,89 @@ internal class CommandHandler
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task MessageHandler(SocketMessage Message)
|
private async Task MessageHandler(SocketMessage Message)
|
||||||
{
|
{
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (Message.Author.IsBot)
|
||||||
|
return;
|
||||||
|
|
||||||
if (Message as SocketUserMessage == null)
|
if (Message as SocketUserMessage == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var message = Message as SocketUserMessage;
|
var message = Message as SocketUserMessage;
|
||||||
|
|
||||||
if (message == null)
|
if (message is null)
|
||||||
return;
|
|
||||||
|
|
||||||
if (!message.Content.StartsWith(botPrefix))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var argPos = 0;
|
var argPos = 0;
|
||||||
|
|
||||||
if (message.HasMentionPrefix(client.CurrentUser, ref argPos))
|
if (!message.Content.StartsWith(botPrefix) && !message.HasMentionPrefix(client.CurrentUser, ref argPos))
|
||||||
{
|
|
||||||
await message.Channel.SendMessageAsync("Can not exec mentioned commands !");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message.Author.IsBot)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var context = new SocketCommandContext(client, message);
|
var context = new SocketCommandContext(client, message);
|
||||||
|
|
||||||
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();
|
DBCommand plugin;
|
||||||
|
string cleanMessage = "";
|
||||||
|
|
||||||
if (plugin is null) throw new System.Exception("Failed to run command. !");
|
if (message.HasMentionPrefix(client.CurrentUser, ref argPos))
|
||||||
|
{
|
||||||
|
string mentionPrefix = "<@" + client.CurrentUser.Id + ">";
|
||||||
|
|
||||||
|
plugin = PluginLoader.Commands!
|
||||||
|
.Where
|
||||||
|
(
|
||||||
|
plug => plug.Command == message.Content.Substring(mentionPrefix.Length+1).Split(' ')[0] ||
|
||||||
|
(
|
||||||
|
plug.Aliases is not null &&
|
||||||
|
plug.Aliases.Contains(message.CleanContent.Substring(mentionPrefix.Length+1).Split(' ')[0])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
cleanMessage = message.Content.Substring(mentionPrefix.Length + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
cleanMessage = message.Content.Substring(botPrefix.Length);
|
||||||
|
}
|
||||||
|
if (plugin is null)
|
||||||
|
throw new Exception($"Failed to run command ! " + message.CleanContent);
|
||||||
|
|
||||||
if (plugin.requireAdmin && !context.Message.Author.isAdmin())
|
if (plugin.requireAdmin && !context.Message.Author.isAdmin())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (context.Channel is SocketDMChannel)
|
string[] split = cleanMessage.Split(' ');
|
||||||
plugin.ExecuteDM(context);
|
|
||||||
else plugin.ExecuteServer(context);
|
|
||||||
|
|
||||||
|
string[] argsClean = null;
|
||||||
|
if(split.Length > 1)
|
||||||
|
argsClean = string.Join(' ', split, 1, split.Length-1).Split(' ');
|
||||||
|
|
||||||
|
CmdArgs cmd = new() {
|
||||||
|
context = context,
|
||||||
|
cleanContent = cleanMessage,
|
||||||
|
commandUsed = split[0],
|
||||||
|
arguments = argsClean
|
||||||
|
};
|
||||||
|
|
||||||
|
if (context.Channel is SocketDMChannel)
|
||||||
|
plugin.ExecuteDM(cmd);
|
||||||
|
else plugin.ExecuteServer(cmd);
|
||||||
}
|
}
|
||||||
catch (System.Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
ex.WriteErrFile();
|
ex.WriteErrFile();
|
||||||
|
|
||||||
|
Console.WriteLine(ex.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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.2</AssemblyVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Discord.Net" Version="3.7.2" />
|
<PackageReference Include="Discord.Net" Version="3.9.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
32
DiscordBot/Entry.cs
Normal file
32
DiscordBot/Entry.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using PluginManager.Others;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DiscordBot
|
||||||
|
{
|
||||||
|
|
||||||
|
public class Entry
|
||||||
|
{
|
||||||
|
internal static StartupArguments startupArguments;
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
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,39 +9,357 @@ 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
|
||||||
{
|
{
|
||||||
private static bool loadPluginsOnStartup;
|
private static bool loadPluginsOnStartup;
|
||||||
private static bool listPluginsAtStartup;
|
|
||||||
private static ConsoleCommandsHandler consoleCommandsHandler;
|
private static ConsoleCommandsHandler consoleCommandsHandler;
|
||||||
|
//private static bool isUI_ON;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main entry point for the application.
|
/// The main entry point for the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[STAThread]
|
[STAThread]
|
||||||
[Obsolete]
|
public static void Startup(string[] args)
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
{
|
||||||
|
PreLoadComponents(args).Wait();
|
||||||
|
|
||||||
Console.WriteLine("Loading resources ...");
|
if (!Config.Variables.Exists("ServerID") || !Config.Variables.Exists("token") ||
|
||||||
PreLoadComponents().Wait();
|
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"))
|
||||||
|
{
|
||||||
|
GenerateStartUI("First time setup. Please fill the following with your discord bot data.\nThis are saved ONLY on YOUR computer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleInput(args).Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The main loop for the discord bot
|
||||||
|
/// </summary>
|
||||||
|
private static void NoGUI()
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
Logger.WriteLine();
|
||||||
|
Logger.WriteLine("Debug mode enabled");
|
||||||
|
Logger.WriteLine();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
if (loadPluginsOnStartup)
|
||||||
|
consoleCommandsHandler.HandleCommand("lp");
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var cmd = Console.ReadLine();
|
||||||
|
if (!consoleCommandsHandler.HandleCommand(cmd!
|
||||||
|
#if DEBUG
|
||||||
|
, false
|
||||||
|
#endif
|
||||||
|
|
||||||
|
) && cmd.Length > 0)
|
||||||
|
Logger.WriteLine("Failed to run command " + cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start the bot without user interface
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns the boot loader for the Discord Bot</returns>
|
||||||
|
private static async Task<Boot> StartNoGui()
|
||||||
|
{
|
||||||
|
Console.Clear();
|
||||||
|
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||||
|
|
||||||
|
var startupMessageList =
|
||||||
|
await ServerCom.ReadTextFromURL(
|
||||||
|
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/StartupMessage");
|
||||||
|
|
||||||
|
foreach (var message in startupMessageList)
|
||||||
|
Logger.WriteLine(message);
|
||||||
|
|
||||||
|
Logger.WriteLine(
|
||||||
|
$"Running on version: {Assembly.GetExecutingAssembly().GetName().Version}");
|
||||||
|
Logger.WriteLine($"Git URL: {Settings.Variables.WebsiteURL}");
|
||||||
|
|
||||||
|
Utilities.WriteColorText(
|
||||||
|
"&rRemember to close the bot using the ShutDown command (&ysd&r) or some settings won't be saved\n");
|
||||||
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
|
|
||||||
|
if (Config.Variables.Exists("LaunchMessage"))
|
||||||
|
Utilities.WriteColorText(Config.Variables.GetValue("LaunchMessage"));
|
||||||
|
|
||||||
|
|
||||||
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"))
|
Utilities.WriteColorText(
|
||||||
|
"Please note that the bot saves a backup save file every time you are using the shudown command (&ysd&c)");
|
||||||
|
Logger.WriteLine("============================ LOG ============================");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string token = "";
|
||||||
|
#if DEBUG
|
||||||
|
if (File.Exists("./Data/Resources/token.txt")) token = File.ReadAllText("./Data/Resources/token.txt");
|
||||||
|
else token = Config.Variables.GetValue("token");
|
||||||
|
#else
|
||||||
|
token = Config.Variables.GetValue("token");
|
||||||
|
#endif
|
||||||
|
var prefix = Config.Variables.GetValue("prefix");
|
||||||
|
var discordbooter = new Boot(token, prefix);
|
||||||
|
await discordbooter.Awake();
|
||||||
|
return discordbooter;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle user input arguments from the startup of the application
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The arguments</param>
|
||||||
|
private static async Task HandleInput(string[] args)
|
||||||
|
{
|
||||||
|
var len = args.Length;
|
||||||
|
|
||||||
|
var b = await StartNoGui();
|
||||||
|
consoleCommandsHandler = new ConsoleCommandsHandler(b.client);
|
||||||
|
|
||||||
|
if (Entry.startupArguments.loadPluginsAtStartup) { loadPluginsOnStartup = true; }
|
||||||
|
|
||||||
|
if (len > 0 && args[0] == "/remplug")
|
||||||
|
{
|
||||||
|
var plugName = string.Join(' ', args, 1, args.Length - 1);
|
||||||
|
Logger.WriteLine("Starting to remove " + plugName);
|
||||||
|
await ConsoleCommandsHandler.ExecuteCommad("remplug " + plugName);
|
||||||
|
loadPluginsOnStartup = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var mainThread = new Thread(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
NoGUI();
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
if (ex.Message == "No process is on the other end of the pipe." || (uint)ex.HResult == 0x800700E9)
|
||||||
|
{
|
||||||
|
if (Config.Variables.Exists("LaunchMessage"))
|
||||||
|
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);
|
||||||
|
Logger.WriteErrFile(ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mainThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task PreLoadComponents(string[] args)
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory("./Data/Resources");
|
||||||
|
Directory.CreateDirectory("./Data/Plugins");
|
||||||
|
Directory.CreateDirectory("./Data/PAKS");
|
||||||
|
|
||||||
|
if (!File.Exists(Functions.dataFolder + "loader.json"))
|
||||||
|
{
|
||||||
|
Entry.startupArguments = new StartupArguments();
|
||||||
|
await Functions.SaveToJsonFile(Functions.dataFolder + "loader.json", Entry.startupArguments);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Entry.startupArguments = await Functions.ConvertFromJson<StartupArguments>(Functions.dataFolder + "loader.json");
|
||||||
|
|
||||||
|
|
||||||
|
Settings.sqlDatabase = new SqlDatabase("SetDB.dat");
|
||||||
|
|
||||||
|
await Settings.sqlDatabase.Open();
|
||||||
|
await Config.Initialize();
|
||||||
|
Logger.Initialize(true);
|
||||||
|
ArchiveManager.Initialize();
|
||||||
|
|
||||||
|
|
||||||
|
Logger.LogEvent += (message) => { Console.Write(message); };
|
||||||
|
|
||||||
|
Logger.WriteLine("Loading resources ...");
|
||||||
|
var main = new Utilities.ProgressBar(ProgressBarType.NO_END);
|
||||||
|
main.Start();
|
||||||
|
|
||||||
|
if (await Config.Variables.ExistsAsync("DeleteLogsAtStartup"))
|
||||||
|
if (await Config.Variables.GetValueAsync("DeleteLogsAtStartup") == "true")
|
||||||
|
foreach (var file in Directory.GetFiles("./Output/Logs/"))
|
||||||
|
File.Delete(file);
|
||||||
|
var OnlineDefaultKeys =
|
||||||
|
await ServerCom.ReadTextFromURL(
|
||||||
|
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/SetupKeys");
|
||||||
|
|
||||||
|
|
||||||
|
if (!await Config.Variables.ExistsAsync("Version"))
|
||||||
|
await Config.Variables.AddAsync("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString(),
|
||||||
|
false);
|
||||||
|
else
|
||||||
|
await Config.Variables.SetValueAsync(
|
||||||
|
"Version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var key in OnlineDefaultKeys)
|
||||||
|
{
|
||||||
|
if (key.Length <= 3 || !key.Contains(' ')) continue;
|
||||||
|
var s = key.Split(' ');
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (await Config.Variables.ExistsAsync(s[0])) await Config.Variables.SetValueAsync(s[0], s[1]);
|
||||||
|
else
|
||||||
|
await Config.Variables.AddAsync(s[0], s[1], s[2].ToLower() == "true");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.WriteErrFile(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var onlineSettingsList =
|
||||||
|
await ServerCom.ReadTextFromURL(
|
||||||
|
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/OnlineData");
|
||||||
|
main.Stop("Loaded online settings. Loading updates ...");
|
||||||
|
foreach (var key in onlineSettingsList)
|
||||||
|
{
|
||||||
|
if (key.Length <= 3 || !key.Contains(' ')) continue;
|
||||||
|
|
||||||
|
var s = key.Split(' ');
|
||||||
|
switch (s[0])
|
||||||
|
{
|
||||||
|
case "CurrentVersion":
|
||||||
|
var newVersion = s[1];
|
||||||
|
if (!newVersion.Equals(await Config.Variables.GetValueAsync("Version")))
|
||||||
|
{
|
||||||
|
var nVer = new VersionString(newVersion.Substring(2));
|
||||||
|
var cVer = new VersionString((await Config.Variables.GetValueAsync("Version")).Substring(2));
|
||||||
|
if (cVer > nVer)
|
||||||
|
{
|
||||||
|
await Config.Variables.SetValueAsync("Version", "1." + cVer.ToShortString() + " (Beta)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.Clear();
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Logger.WriteLine("A new version of the bot is available !");
|
||||||
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
Logger.WriteLine("Current version : " +
|
||||||
|
Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
Logger.WriteLine("New version : " + newVersion);
|
||||||
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
|
|
||||||
|
Logger.WriteLine("Changelog :");
|
||||||
|
|
||||||
|
List<string> changeLog = await ServerCom.ReadTextFromURL(
|
||||||
|
"https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/VersionData/DiscordBot");
|
||||||
|
foreach (var item in changeLog)
|
||||||
|
Utilities.WriteColorText(item);
|
||||||
|
Logger.WriteLine("Do you want to update the bot ? (y/n)");
|
||||||
|
if (Console.ReadKey().Key == ConsoleKey.Y)
|
||||||
|
{
|
||||||
|
if (Functions.GetOperatingSystem() == OperatingSystem.WINDOWS)
|
||||||
|
{
|
||||||
|
var url =
|
||||||
|
$"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0.zip";
|
||||||
|
Process.Start($"{Functions.dataFolder}Applications/Updater.exe",
|
||||||
|
$"{newVersion} {url} {Process.GetCurrentProcess().ProcessName}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var url =
|
||||||
|
$"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0_linux.zip";
|
||||||
|
if (Logger.isConsole)
|
||||||
|
Console.SetCursorPosition(0, Console.CursorTop);
|
||||||
|
Logger.WriteLine($"executing: download_file {url}");
|
||||||
|
|
||||||
|
await ServerCom.DownloadFileAsync(url, "./update.zip", new Progress<float>(percent => { Logger.Write($"\rProgress: {percent}% "); }));
|
||||||
|
await File.WriteAllTextAsync("Install.sh",
|
||||||
|
"#!/bin/bash\nunzip -qq -o update.zip \nrm update.zip\nchmod a+x DiscordBot");
|
||||||
|
Logger.WriteLine();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Logger.WriteLine("executing: chmod a+x Install.sh");
|
||||||
|
Process.Start("chmod", "a+x Install.sh").WaitForExit();
|
||||||
|
Process.Start("Install.sh").WaitForExit();
|
||||||
|
|
||||||
|
Logger.WriteLine("executing: rm Install.sh");
|
||||||
|
Process.Start("rm", "Install.sh").WaitForExit();
|
||||||
|
|
||||||
|
Logger.WriteLine("The new version of the bot has been installed.");
|
||||||
|
Logger.WriteLine("Please restart the bot.");
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.WriteErrFile(ex.Message);
|
||||||
|
if (ex.Message.Contains("Access de"))
|
||||||
|
Logger.WriteLine("Please run the bot as root.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Process.Start(Functions.dataFolder + "Applications/Updater", $"{url}");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "UpdaterVersion":
|
||||||
|
var updaternewversion = s[1];
|
||||||
|
if (Functions.GetOperatingSystem() == OperatingSystem.LINUX)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!await Config.Variables.ExistsAsync("UpdaterVersion"))
|
||||||
|
await Config.Variables.AddAsync("UpdaterVersion", "0.0.0.0", false);
|
||||||
|
if (await Config.Variables.GetValueAsync("UpdaterVersion") != updaternewversion ||
|
||||||
|
!File.Exists(Functions.dataFolder+"Applications/Updater.exe"))
|
||||||
|
{
|
||||||
|
Console.Clear();
|
||||||
|
Logger.WriteLine("Installing updater ...\nDo NOT close the bot during update !");
|
||||||
|
var bar = new Utilities.ProgressBar(ProgressBarType.NO_END);
|
||||||
|
bar.Start();
|
||||||
|
await ServerCom.DownloadFileNoProgressAsync(
|
||||||
|
"https://github.com/Wizzy69/installer/releases/download/release-1-discordbot/Updater.exe",
|
||||||
|
$"{Functions.dataFolder}Applications/Updater.exe");
|
||||||
|
//await ArchiveManager.ExtractArchive("./Updater.zip", "./", null,
|
||||||
|
// UnzipProgressType.PercentageFromTotalSize);
|
||||||
|
await Config.Variables.SetValueAsync("UpdaterVersion", updaternewversion);
|
||||||
|
// File.Delete("Updater.zip");
|
||||||
|
bar.Stop("Updater has been updated !");
|
||||||
|
Console.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void GenerateStartUI(string titleMessage)
|
||||||
{
|
{
|
||||||
Application.Init();
|
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 +370,7 @@ 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(titleMessage)
|
||||||
{
|
{
|
||||||
X = Pos.Center(),
|
X = Pos.Center(),
|
||||||
Y = 2
|
Y = 2
|
||||||
@@ -66,7 +383,7 @@ public class Program
|
|||||||
Y = 5
|
Y = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
var textFiledToken = new TextField("")
|
var textFiledToken = new TextField(Config.Variables.GetValue("token") ?? "")
|
||||||
{
|
{
|
||||||
X = Pos.Left(labelToken) + labelToken.Text.Length + 2,
|
X = Pos.Left(labelToken) + labelToken.Text.Length + 2,
|
||||||
Y = labelToken.Y,
|
Y = labelToken.Y,
|
||||||
@@ -78,7 +395,7 @@ public class Program
|
|||||||
X = 5,
|
X = 5,
|
||||||
Y = 8
|
Y = 8
|
||||||
};
|
};
|
||||||
var textFiledPrefix = new TextField("")
|
var textFiledPrefix = new TextField(Config.Variables.GetValue("prefix") ?? "")
|
||||||
{
|
{
|
||||||
X = Pos.Left(labelPrefix) + labelPrefix.Text.Length + 2,
|
X = Pos.Left(labelPrefix) + labelPrefix.Text.Length + 2,
|
||||||
Y = labelPrefix.Y,
|
Y = labelPrefix.Y,
|
||||||
@@ -88,10 +405,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(Config.Variables.GetValue("ServerID") ?? "")
|
||||||
{
|
{
|
||||||
X = Pos.Left(labelServerid) + labelServerid.Text.Length + 2,
|
X = Pos.Left(labelServerid) + labelServerid.Text.Length + 2,
|
||||||
Y = labelServerid.Y,
|
Y = labelServerid.Y,
|
||||||
@@ -110,15 +426,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,384 +446,55 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleInput(args).Wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The main loop for the discord bot
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="discordbooter">The discord booter used to start the application</param>
|
|
||||||
private static void NoGUI(Boot discordbooter)
|
|
||||||
{
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
Console.WriteLine();
|
|
||||||
ConsoleCommandsHandler.ExecuteCommad("lp").Wait();
|
|
||||||
#else
|
|
||||||
if (loadPluginsOnStartup) consoleCommandsHandler.HandleCommand("lp");
|
|
||||||
if (listPluginsAtStartup) consoleCommandsHandler.HandleCommand("listplugs");
|
|
||||||
#endif
|
|
||||||
Config.SaveConfig(SaveType.NORMAL).Wait();
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
|
|
||||||
var cmd = Console.ReadLine();
|
|
||||||
if (!consoleCommandsHandler.HandleCommand(cmd!
|
|
||||||
#if DEBUG
|
|
||||||
, false
|
|
||||||
#endif
|
|
||||||
|
|
||||||
) && cmd.Length > 0)
|
|
||||||
Console.WriteLine("Failed to run command " + cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Start the bot without user interface
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Returns the boot loader for the Discord Bot</returns>
|
|
||||||
private static async Task<Boot> StartNoGUI()
|
|
||||||
{
|
|
||||||
Console.Clear();
|
|
||||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
|
||||||
|
|
||||||
List<string> startupMessageList = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/StartupMessage");
|
|
||||||
|
|
||||||
foreach (var message in startupMessageList)
|
|
||||||
Console.WriteLine(message);
|
|
||||||
|
|
||||||
Console.WriteLine($"Running on version: {Config.GetValue<string>("Version") ?? System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()}");
|
|
||||||
Console.WriteLine($"Git URL: {Config.GetValue<string>("GitURL") ?? " Could not find Git URL"}");
|
|
||||||
|
|
||||||
Console_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;
|
|
||||||
|
|
||||||
if (Config.ContainsKey("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 ============================");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var token = Config.GetValue<string>("token");
|
|
||||||
#if DEBUG
|
|
||||||
Console.WriteLine("Starting in DEBUG MODE");
|
|
||||||
if (!Directory.Exists("./Data/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");
|
|
||||||
|
|
||||||
//Debug mode code...
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var prefix = Config.GetValue<string>("prefix");
|
|
||||||
var discordbooter = new Boot(token, prefix);
|
|
||||||
await discordbooter.Awake();
|
|
||||||
return discordbooter;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(ex);
|
|
||||||
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>
|
|
||||||
/// Handle user input arguments from the startup of the application
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="args">The arguments</param>
|
|
||||||
private static async Task HandleInput(string[] args)
|
|
||||||
{
|
|
||||||
|
|
||||||
var len = args.Length;
|
|
||||||
|
|
||||||
if (len == 3 && args[0] == "/download")
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (len > 0 && args[0] == "/remplug")
|
|
||||||
{
|
|
||||||
|
|
||||||
string plugName = Functions.MergeStrings(args, 1);
|
|
||||||
Console.WriteLine("Starting to remove " + plugName);
|
|
||||||
await ConsoleCommandsHandler.ExecuteCommad("remplug " + plugName);
|
|
||||||
loadPluginsOnStartup = true;
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len > 0 && args[0] == "/updateplug")
|
|
||||||
{
|
|
||||||
string plugName = args.MergeStrings(1);
|
|
||||||
Console.WriteLine("Updating " + plugName);
|
|
||||||
await ConsoleCommandsHandler.ExecuteCommad("dwplug" + plugName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == 0 || (args[0] != "--exec" && args[0] != "--execute"))
|
|
||||||
{
|
|
||||||
|
|
||||||
Thread mainThread = new Thread(() =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
NoGUI(b);
|
|
||||||
}
|
|
||||||
catch (IOException ex)
|
|
||||||
{
|
|
||||||
if (ex.Message == "No process is on the other end of the pipe." || (uint)ex.HResult == 0x800700E9)
|
|
||||||
{
|
|
||||||
if (!Config.ContainsKey("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);
|
|
||||||
Functions.WriteErrFile(ex.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
Console_Utilities.ProgressBar main = new Console_Utilities.ProgressBar(ProgressBarType.NO_END);
|
|
||||||
main.Start();
|
|
||||||
Directory.CreateDirectory("./Data/Resources");
|
|
||||||
Directory.CreateDirectory("./Data/Plugins/Commands");
|
|
||||||
Directory.CreateDirectory("./Data/Plugins/Events");
|
|
||||||
Directory.CreateDirectory("./Data/PAKS");
|
|
||||||
await Config.LoadConfig();
|
|
||||||
if (Config.ContainsKey("DeleteLogsAtStartup"))
|
|
||||||
if (Config.GetValue<bool>("DeleteLogsAtStartup"))
|
|
||||||
foreach (var file in Directory.GetFiles("./Output/Logs/"))
|
|
||||||
File.Delete(file);
|
|
||||||
List<string> OnlineDefaultKeys = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/SetupKeys");
|
|
||||||
|
|
||||||
Config.PluginConfig.Load();
|
|
||||||
|
|
||||||
if (!Config.ContainsKey("Version"))
|
|
||||||
Config.AddValueToVariables("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString(), false);
|
|
||||||
else
|
|
||||||
Config.SetValue("Version", Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
|
||||||
|
|
||||||
foreach (var key in OnlineDefaultKeys)
|
|
||||||
{
|
|
||||||
if (key.Length <= 3 || !key.Contains(' ')) continue;
|
|
||||||
string[] s = key.Split(' ');
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Config.ContainsKey(s[0])) Config.SetValue(s[0], s[1]);
|
|
||||||
else Config.GetAndAddValueToVariable(s[0], s[1], s[2].Equals("true", StringComparison.CurrentCultureIgnoreCase));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Functions.WriteErrFile(ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
List<string> onlineSettingsList = await ServerCom.ReadTextFromURL("https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/OnlineData");
|
|
||||||
main.Stop("Loaded online settings. Loading updates ...");
|
|
||||||
foreach (var key in onlineSettingsList)
|
|
||||||
{
|
|
||||||
if (key.Length <= 3 || !key.Contains(' ')) continue;
|
|
||||||
|
|
||||||
string[] s = key.Split(' ');
|
|
||||||
switch (s[0])
|
|
||||||
{
|
|
||||||
case "CurrentVersion":
|
|
||||||
string newVersion = s[1];
|
|
||||||
if (!newVersion.Equals(Config.GetValue<string>("Version")))
|
|
||||||
{
|
|
||||||
if (Functions.GetOperatingSystem() == PluginManager.Others.OperatingSystem.WINDOWS)
|
|
||||||
{
|
|
||||||
|
|
||||||
string url = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0.zip";
|
|
||||||
//string url2 = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}-preview/net6.0.zip";
|
|
||||||
|
|
||||||
Process.Start(".\\Updater\\Updater.exe", $"{newVersion} {url} {Process.GetCurrentProcess().ProcessName}");
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string url = $"https://github.com/Wizzy69/SethDiscordBot/releases/download/v{newVersion}/net6.0_linux.zip";
|
|
||||||
Console.WriteLine("Downloading update ...");
|
|
||||||
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");
|
|
||||||
Process.Start("Install.sh").WaitForExit();
|
|
||||||
Environment.Exit(0);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case "UpdaterVersion":
|
|
||||||
string updaternewversion = s[1];
|
|
||||||
if (Config.UpdaterVersion != updaternewversion && Functions.GetOperatingSystem() == PluginManager.Others.OperatingSystem.WINDOWS)
|
|
||||||
{
|
|
||||||
Console.Clear();
|
|
||||||
Console.WriteLine("Installing updater ...\nDo NOT close the bot during update !");
|
|
||||||
Console_Utilities.ProgressBar bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END);
|
|
||||||
bar.Start();
|
|
||||||
await ServerCom.DownloadFileNoProgressAsync("https://github.com/Wizzy69/installer/releases/download/release-1-discordbot/Updater.zip", "./Updater.zip");
|
|
||||||
await Functions.ExtractArchive("./Updater.zip", "./", null, UnzipProgressType.PercentageFromTotalSize);
|
|
||||||
Config.UpdaterVersion = updaternewversion;
|
|
||||||
File.Delete("Updater.zip");
|
|
||||||
await Config.SaveConfig(SaveType.NORMAL);
|
|
||||||
bar.Stop("Updater has been updated !");
|
|
||||||
Console.Clear();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Console_Utilities.Initialize();
|
|
||||||
await Config.SaveConfig(SaveType.NORMAL);
|
|
||||||
Console.Clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
14
DiscordBot/StartupArguments.cs
Normal file
14
DiscordBot/StartupArguments.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DiscordBot
|
||||||
|
{
|
||||||
|
internal class StartupArguments
|
||||||
|
{
|
||||||
|
public string runArgs { get; } = "";
|
||||||
|
public bool loadPluginsAtStartup { get; } = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,239 +1,202 @@
|
|||||||
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))
|
||||||
|
{
|
||||||
|
if (GetValue(VarName) == Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SetValue(VarName, Value);
|
||||||
|
SetReadOnly(VarName, ReadOnly);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Settings.sqlDatabase.Insert("Variables", VarName, Value, ReadOnly ? "true" : "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task RemoveKeyAsync(string VarName)
|
||||||
|
{
|
||||||
|
if (!IsLoaded)
|
||||||
|
throw new Exception("Config is not loaded");
|
||||||
|
await Settings.sqlDatabase.RemoveKeyAsync("Variables", "VarName", VarName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemoveKey(string VarName)
|
||||||
|
{
|
||||||
|
if (!IsLoaded)
|
||||||
|
throw new Exception("Config is not loaded");
|
||||||
|
Settings.sqlDatabase.RemoveKey("Variables", "VarName", VarName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Plugins
|
||||||
|
{
|
||||||
|
public static async Task<string> GetVersionAsync(string pluginName)
|
||||||
|
{
|
||||||
|
if (!IsLoaded)
|
||||||
|
throw new Exception("Config is not loaded yet");
|
||||||
|
|
||||||
|
string result = await Settings.sqlDatabase.GetValueAsync("Plugins", "PluginName", pluginName, "Version");
|
||||||
|
if (result is null)
|
||||||
|
return "0.0.0";
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetVersion(string pluginName)
|
||||||
|
{
|
||||||
|
if (!IsLoaded)
|
||||||
|
throw new Exception("Config is not loaded yet");
|
||||||
|
|
||||||
|
string result = Settings.sqlDatabase.GetValue("Plugins", "PluginName", pluginName, "Version");
|
||||||
|
if (result is null)
|
||||||
|
return "0.0.0";
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task SetVersionAsync(string pluginName, VersionString version)
|
||||||
|
{
|
||||||
|
if (!IsLoaded)
|
||||||
|
throw new Exception("Config is not loaded yet");
|
||||||
|
|
||||||
|
if (!await Settings.sqlDatabase.KeyExistsAsync("Plugins", "PluginName", pluginName))
|
||||||
|
{
|
||||||
|
await Settings.sqlDatabase.InsertAsync("Plugins", pluginName, version.ToShortString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await Settings.sqlDatabase.SetValueAsync("Plugins", "PluginName", pluginName, "Version", version.ToShortString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetVersion(string pluginName, VersionString version)
|
||||||
|
{
|
||||||
|
if (!IsLoaded)
|
||||||
|
throw new Exception("Config is not loaded yet");
|
||||||
|
|
||||||
|
if (!Settings.sqlDatabase.KeyExists("Plugins", "PluginName", pluginName))
|
||||||
|
{
|
||||||
|
Settings.sqlDatabase.Insert("Plugins", pluginName, version.ToShortString());
|
||||||
return;
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
327
PluginManager/Database/SqlDatabase.cs
Normal file
327
PluginManager/Database/SqlDatabase.cs
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
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 (!fileName.StartsWith("./Data/Resources/"))
|
||||||
|
fileName = Path.Combine("./Data/Resources", 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 async Task<List<string[]>?> ReadAllRowsAsync(string query)
|
||||||
|
{
|
||||||
|
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
|
||||||
|
await Connection.OpenAsync();
|
||||||
|
var command = new SQLiteCommand(query, Connection);
|
||||||
|
var reader = await command.ExecuteReaderAsync();
|
||||||
|
|
||||||
|
if (!reader.HasRows)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
List<string[]> rows = new();
|
||||||
|
while (await reader.ReadAsync())
|
||||||
|
{
|
||||||
|
string[] values = new string[reader.FieldCount];
|
||||||
|
reader.GetValues(values);
|
||||||
|
rows.Add(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rows.Count == 0) return null;
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object[]? ReadDataArray(string query)
|
||||||
|
{
|
||||||
|
if (!Connection.State.HasFlag(System.Data.ConnectionState.Open))
|
||||||
|
Connection.Open();
|
||||||
|
var command = new SQLiteCommand(query, Connection);
|
||||||
|
var reader = command.ExecuteReader();
|
||||||
|
|
||||||
|
object[] values = new object[reader.FieldCount];
|
||||||
|
if (reader.Read())
|
||||||
|
{
|
||||||
|
reader.GetValues(values);
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using PluginManager.Others;
|
||||||
|
|
||||||
namespace PluginManager.Interfaces;
|
namespace PluginManager.Interfaces;
|
||||||
|
|
||||||
@@ -38,11 +38,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(CmdArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main body of the command. This is what is executed when user calls the command in DM
|
/// The main body of the command. This is what is executed when user calls the command in DM
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">The disocrd Context</param>
|
/// <param name="context">The disocrd Context</param>
|
||||||
void ExecuteDM(SocketCommandContext context) { }
|
void ExecuteDM(CmdArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
25
PluginManager/Interfaces/DBSlashCommand.cs
Normal file
25
PluginManager/Interfaces/DBSlashCommand.cs
Normal 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) { }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,51 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using PluginManager.Others;
|
|
||||||
|
|
||||||
namespace PluginManager.Items;
|
namespace PluginManager.Items;
|
||||||
|
|
||||||
public class Command
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The author of the command
|
|
||||||
/// </summary>
|
|
||||||
public SocketUser? Author;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The Command class contructor
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message that was sent</param>
|
|
||||||
public Command(SocketMessage message)
|
|
||||||
{
|
|
||||||
Author = message.Author;
|
|
||||||
var data = message.Content.Split(' ');
|
|
||||||
Arguments = data.Length > 1 ? new List<string>(data.MergeStrings(1).Split(' ')) : new List<string>();
|
|
||||||
CommandName = data[0].Substring(1);
|
|
||||||
PrefixUsed = data[0][0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The list of arguments
|
|
||||||
/// </summary>
|
|
||||||
public List<string> Arguments { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The command that is executed
|
|
||||||
/// </summary>
|
|
||||||
public string CommandName { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The prefix that is used for the command
|
|
||||||
/// </summary>
|
|
||||||
public char PrefixUsed { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ConsoleCommand
|
public class ConsoleCommand
|
||||||
{
|
{
|
||||||
public string CommandName { get; init; }
|
public string? CommandName { get; init; }
|
||||||
public string Description { get; init; }
|
public string? Description { get; init; }
|
||||||
public string Usage { get; init; }
|
public string? Usage { get; init; }
|
||||||
public Action<string[]> Action { get; init; }
|
public Action<string[]>? Action { get; init; }
|
||||||
}
|
}
|
||||||
@@ -5,46 +5,50 @@ 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;
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
if (!Logger.isConsole) throw new Exception("Can not use ConsoleCommandsHandler for Non console apps");
|
||||||
this.client = client;
|
this.client = client;
|
||||||
InitializeBasicCommands();
|
InitializeBasicCommands();
|
||||||
//Console.WriteLine("Initialized console command handler !");
|
|
||||||
|
|
||||||
|
//Logger.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:");
|
Logger.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,24 @@ 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;
|
if (!command.CommandName.StartsWith("_"))
|
||||||
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);
|
Logger.WriteLine("Command description: " + command.Description);
|
||||||
Console.WriteLine("Command execution format:" + command.Usage);
|
Logger.WriteLine("Command execution format:" + command.Usage);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine("Command not found");
|
Logger.WriteLine("Command not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -80,24 +84,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);
|
Logger.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);
|
Logger.WriteLine("An error occured while loading: " + name);
|
||||||
|
else
|
||||||
|
Logger.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 +114,39 @@ public class ConsoleCommandsHandler
|
|||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
Console.WriteLine("[EVENT] Successfully loaded event : " + name);
|
Logger.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);
|
Logger.WriteLine("[EVENT] Failed to load event : " + name + " because " + exception!.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.ForegroundColor = cc;
|
||||||
|
};
|
||||||
|
|
||||||
|
loader.onSLSHLoad += (name, typeName, success, exception) =>
|
||||||
|
{
|
||||||
|
if (name == null || name.Length < 2)
|
||||||
|
name = typeName;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
Logger.WriteLine("[SLASH] Successfully loaded command : " + name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
Logger.WriteLine("[SLASH] Failed to load command : " + name + " because " + exception!.Message);
|
||||||
|
}
|
||||||
|
|
||||||
Console.ForegroundColor = cc;
|
Console.ForegroundColor = cc;
|
||||||
};
|
};
|
||||||
|
|
||||||
loader.LoadPlugins();
|
loader.LoadPlugins();
|
||||||
Console.ForegroundColor = cc;
|
Console.ForegroundColor = cc;
|
||||||
pluginsLoaded = true;
|
pluginsLoaded = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -133,11 +158,11 @@ public class ConsoleCommandsHandler
|
|||||||
if (args.Length == 1)
|
if (args.Length == 1)
|
||||||
{
|
{
|
||||||
isDownloading = false;
|
isDownloading = false;
|
||||||
Console.WriteLine("Please specify plugin name");
|
Logger.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 +172,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));
|
|
||||||
|
|
||||||
|
Logger.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}");
|
Logger.WriteLine($"Downloading requirements for plugin : {name}");
|
||||||
|
|
||||||
var lines = await ServerCom.ReadTextFromURL(info[2]);
|
var lines = await ServerCom.ReadTextFromURL(info[2]);
|
||||||
|
|
||||||
@@ -193,44 +216,50 @@ 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]}");
|
Logger.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();
|
|
||||||
|
Logger.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]} ...");
|
Logger.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 ArchiveManager.ExtractArchive("./" + split[1], "./", null,
|
||||||
|
UnzipProgressType.PercentageFromTotalSize);
|
||||||
bar.Stop("Extracted");
|
bar.Stop("Extracted");
|
||||||
Console.WriteLine("\n");
|
Logger.WriteLine("\n");
|
||||||
File.Delete("./" + split[1]);
|
File.Delete("./" + split[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine();
|
Logger.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;
|
||||||
|
|
||||||
|
await ExecuteCommad("localload " + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -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}");
|
Logger.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}");
|
Logger.WriteLine($"Updated config file with the following command: {args[1]} => {value}");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine(ex.ToString());
|
Logger.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,67 @@ public class ConsoleCommandsHandler
|
|||||||
{
|
{
|
||||||
if (client is null)
|
if (client is null)
|
||||||
return;
|
return;
|
||||||
Console_Utilities.ProgressBar bar = new Console_Utilities.ProgressBar(ProgressBarType.NO_END);
|
|
||||||
|
|
||||||
bar.Start();
|
Settings.sqlDatabase.Stop();
|
||||||
await Config.SaveConfig(SaveType.NORMAL);
|
|
||||||
await Config.SaveConfig(SaveType.BACKUP);
|
|
||||||
bar.Stop("Saved config !");
|
|
||||||
Console.WriteLine();
|
|
||||||
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);
|
using (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();
|
await PluginLoader.LoadPluginFromAssembly(asmb, this.client);
|
||||||
foreach (var type in types)
|
|
||||||
{
|
|
||||||
if (type.IsClass && typeof(DBEvent).IsAssignableFrom(type))
|
|
||||||
{
|
|
||||||
DBEvent instance = (DBEvent)Activator.CreateInstance(type);
|
|
||||||
instance.Start(this.client);
|
|
||||||
Console.WriteLine($"Loaded external {type.FullName}!");
|
|
||||||
}
|
}
|
||||||
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
|
|
||||||
{
|
|
||||||
Console.WriteLine("Only events can be loaded from external sources !");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.WriteLine(ex.Message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddCommand("localload", "Load a local command", "local [pluginName]", async args =>
|
||||||
|
{
|
||||||
|
if (args.Length <= 1) return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var pName = string.Join(' ', args, 1, args.Length - 1);
|
||||||
|
var asmb = Assembly.LoadFile(Path.GetFullPath("./Data/Plugins/" + pName + ".dll"));
|
||||||
|
|
||||||
|
await PluginLoader.LoadPluginFromAssembly(asmb, this.client);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.WriteLine(ex.Message);
|
||||||
|
Logger.WriteErrFile(ex);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AddCommand("remplug", "Remove a plugin", "remplug [plugName]", async args =>
|
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 +379,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");
|
Logger.WriteLine("The plugin does not exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
File.Delete(location);
|
File.Delete(location);
|
||||||
if (Config.PluginConfig.Contains(plugName))
|
|
||||||
{
|
Logger.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 +410,47 @@ public class ConsoleCommandsHandler
|
|||||||
File.Delete("./" + split[1]);
|
File.Delete("./" + split[1]);
|
||||||
|
|
||||||
|
|
||||||
Console.WriteLine("Removed: " + split[1]);
|
Logger.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;
|
||||||
|
Logger.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
|
||||||
{
|
{
|
||||||
|
//HandleCommand("sd");
|
||||||
Process.Start("./DiscordBot", $"lp");
|
Console.WriteLine("This command can not be used outside of Windows yet. Please restart the bot using the manual way");
|
||||||
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)
|
||||||
@@ -446,43 +473,61 @@ public class ConsoleCommandsHandler
|
|||||||
return commandList.FirstOrDefault(t => t.CommandName == command);
|
return commandList.FirstOrDefault(t => t.CommandName == command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* public static async Task ExecuteSpecialCommand(string command)
|
||||||
|
{
|
||||||
|
if (!command.StartsWith("_")) return;
|
||||||
|
|
||||||
|
string[] args = command.Split(' ');
|
||||||
|
foreach (var item in commandList)
|
||||||
|
if (item.CommandName == args[0])
|
||||||
|
{
|
||||||
|
Logger.WriteLine();
|
||||||
|
item.Action(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
public static async Task ExecuteCommad(string command)
|
public static async Task ExecuteCommad(string command)
|
||||||
{
|
{
|
||||||
|
if (!Logger.isConsole)
|
||||||
|
throw new Exception("Can not use console based commands on non console based application !");
|
||||||
var args = command.Split(' ');
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HandleCommand(string command, bool removeCommandExecution = true)
|
public bool HandleCommand(string command, bool removeCommandExecution = true)
|
||||||
{
|
{
|
||||||
|
if (!Logger.isConsole)
|
||||||
|
throw new Exception("Can not use console based commands on non console based application !");
|
||||||
Console.ForegroundColor = ConsoleColor.White;
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
var args = command.Split(' ');
|
var args = command.Split(' ');
|
||||||
foreach (var item in commandList.ToList())
|
foreach (var item in commandList.ToList())
|
||||||
if (item.CommandName == args[0])
|
if (item.CommandName == args[0])
|
||||||
{
|
{
|
||||||
|
if (args[0].StartsWith("_"))
|
||||||
|
throw new Exception("This command is reserved for internal worker and can not be executed manually !");
|
||||||
|
|
||||||
|
if (Logger.isConsole)
|
||||||
if (removeCommandExecution)
|
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(" ");
|
Logger.Write(" ");
|
||||||
Console.SetCursorPosition(0, Console.CursorTop);
|
Console.SetCursorPosition(0, Console.CursorTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine();
|
Logger.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)}");
|
//Logger.WriteLine($"Executing: {args[0]} with the following parameters: {args.MergeStrings(1)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,10 +3,6 @@ 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;
|
|
||||||
|
|
||||||
namespace PluginManager.Loaders;
|
namespace PluginManager.Loaders;
|
||||||
|
|
||||||
@@ -31,11 +27,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 +43,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,15 +88,27 @@ 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)
|
||||||
{
|
{
|
||||||
Functions.WriteErrFile(ex.ToString());
|
Logger.WriteErrFile(ex.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal delegate void FileLoadedEventHandler(LoaderArgs args);
|
||||||
|
|
||||||
|
internal delegate void PluginLoadedEventHandler(LoaderArgs args);
|
||||||
}
|
}
|
||||||
136
PluginManager/Loaders/LoaderV2.cs
Normal file
136
PluginManager/Loaders/LoaderV2.cs
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
|
||||||
|
namespace PluginManager.Loaders
|
||||||
|
{
|
||||||
|
internal class LoaderV2
|
||||||
|
{
|
||||||
|
internal LoaderV2(string path, string extension)
|
||||||
|
{
|
||||||
|
this.path = path;
|
||||||
|
this.extension = extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private string path { get; }
|
||||||
|
private string extension { get; }
|
||||||
|
|
||||||
|
internal event FileLoadedEventHandler? FileLoaded;
|
||||||
|
|
||||||
|
internal event PluginLoadedEventHandler? PluginLoaded;
|
||||||
|
|
||||||
|
|
||||||
|
internal delegate void FileLoadedEventHandler(LoaderArgs args);
|
||||||
|
|
||||||
|
internal delegate void PluginLoadedEventHandler(LoaderArgs args);
|
||||||
|
|
||||||
|
|
||||||
|
internal (List<DBEvent>?, List<DBCommand>?, List<DBSlashCommand>?) Load()
|
||||||
|
{
|
||||||
|
|
||||||
|
List<DBEvent> events = new();
|
||||||
|
List<DBSlashCommand> slashCommands = new();
|
||||||
|
List<DBCommand> commands = new();
|
||||||
|
|
||||||
|
if (!Directory.Exists(path))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(path);
|
||||||
|
return (null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var files = Directory.GetFiles(path, $"*.{extension}", SearchOption.AllDirectories);
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assembly.LoadFrom(file);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.WriteLine(ex.Message);
|
||||||
|
Logger.WriteLine("PluginName: " + new FileInfo(file).Name.Split('.')[0] + " not loaded");
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (FileLoaded != null)
|
||||||
|
{
|
||||||
|
var args = new LoaderArgs
|
||||||
|
{
|
||||||
|
Exception = null,
|
||||||
|
TypeName = null,
|
||||||
|
IsLoaded = false,
|
||||||
|
PluginName = new FileInfo(file).Name.Split('.')[0],
|
||||||
|
Plugin = null
|
||||||
|
};
|
||||||
|
FileLoaded.Invoke(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (LoadItems<DBEvent>(), LoadItems<DBCommand>(), LoadItems<DBSlashCommand>());
|
||||||
|
}
|
||||||
|
|
||||||
|
internal List<T> LoadItems<T>()
|
||||||
|
{
|
||||||
|
List<T> list = new();
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var interfaceType = typeof(T);
|
||||||
|
var types = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
.SelectMany(a => a.GetTypes())
|
||||||
|
.Where(p => interfaceType.IsAssignableFrom(p) && p.IsClass)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
|
||||||
|
list.Clear();
|
||||||
|
foreach (var type in types)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var plugin = (T)Activator.CreateInstance(type)!;
|
||||||
|
list.Add(plugin);
|
||||||
|
|
||||||
|
|
||||||
|
if (PluginLoaded != null)
|
||||||
|
PluginLoaded.Invoke(new LoaderArgs
|
||||||
|
{
|
||||||
|
Exception = null,
|
||||||
|
IsLoaded = true,
|
||||||
|
PluginName = type.FullName,
|
||||||
|
TypeName = typeof(T) == typeof(DBCommand) ? "DBCommand" : typeof(T) == typeof(DBEvent) ? "DBEvent" : "DBSlashCommand",
|
||||||
|
Plugin = plugin
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (PluginLoaded != null)
|
||||||
|
PluginLoaded.Invoke(new LoaderArgs
|
||||||
|
{
|
||||||
|
Exception = ex,
|
||||||
|
IsLoaded = false,
|
||||||
|
PluginName = type.FullName,
|
||||||
|
TypeName = nameof(T)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.WriteErrFile(ex.ToString());
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Reflection;
|
||||||
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;
|
|
||||||
|
|
||||||
namespace PluginManager.Loaders;
|
namespace PluginManager.Loaders;
|
||||||
|
|
||||||
@@ -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,123 @@ 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);
|
Logger.WriteLogFile("Starting plugin loader ... Client: " + _client.CurrentUser.Username);
|
||||||
Console.WriteLine("Loading plugins");
|
Logger.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) => Logger.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)
|
|
||||||
{
|
|
||||||
Functions.WriteLogFile($"[EVENT] Event from file [{e.PluginName}] has been successfully created !");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnCommandFileLoaded(LoaderArgs e)
|
switch (args.TypeName)
|
||||||
{
|
|
||||||
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());
|
Logger.WriteLine(ex.ToString());
|
||||||
Console.WriteLine("Plugin: " + e.PluginName);
|
Logger.WriteLine("Plugin: " + args.PluginName);
|
||||||
Console.WriteLine("Type: " + e.TypeName);
|
Logger.WriteLine("Type: " + args.TypeName);
|
||||||
Console.WriteLine("IsLoaded: " + e.IsLoaded);
|
Logger.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;
|
||||||
|
|
||||||
|
onSLSHLoad?.Invoke(((DBSlashCommand)args.Plugin!).Name, args.TypeName, args.IsLoaded, args.Exception);
|
||||||
|
await _client.CreateGlobalApplicationCommandAsync(builder.Build());
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static async Task LoadPluginFromAssembly(Assembly asmb, DiscordSocketClient client)
|
||||||
|
{
|
||||||
|
var types = asmb.GetTypes();
|
||||||
|
foreach (var type in types)
|
||||||
|
if (type.IsClass && typeof(DBEvent).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
var instance = (DBEvent)Activator.CreateInstance(type);
|
||||||
|
instance.Start(client);
|
||||||
|
PluginLoader.Events.Add(instance);
|
||||||
|
Logger.WriteLine($"[EVENT] Loaded external {type.FullName}!");
|
||||||
|
}
|
||||||
|
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
var instance = (DBCommand)Activator.CreateInstance(type);
|
||||||
|
PluginLoader.Commands.Add(instance);
|
||||||
|
Logger.WriteLine($"[CMD] Instance: {type.FullName} loaded !");
|
||||||
|
}
|
||||||
|
else if (type.IsClass && typeof(DBSlashCommand).IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
var instance = (DBSlashCommand)Activator.CreateInstance(type);
|
||||||
|
SlashCommandBuilder builder = new SlashCommandBuilder();
|
||||||
|
builder.WithName(instance.Name);
|
||||||
|
builder.WithDescription(instance.Description);
|
||||||
|
builder.WithDMPermission(instance.canUseDM);
|
||||||
|
builder.Options = instance.Options;
|
||||||
|
|
||||||
|
await client.CreateGlobalApplicationCommandAsync(builder.Build());
|
||||||
|
PluginLoader.SlashCommands.Add(instance);
|
||||||
|
Logger.WriteLine($"[SLASH] Instance: {type.FullName} loaded !");
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
131
PluginManager/Logger.cs
Normal file
131
PluginManager/Logger.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
using Discord;
|
||||||
|
|
||||||
|
namespace PluginManager
|
||||||
|
{
|
||||||
|
public static class Logger
|
||||||
|
{
|
||||||
|
|
||||||
|
public static bool isConsole { get; private set; }
|
||||||
|
private static bool isInitialized;
|
||||||
|
|
||||||
|
private static string? logFolder;
|
||||||
|
private static string? errFolder;
|
||||||
|
|
||||||
|
public static void Initialize(bool console)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (isInitialized) throw new Exception("Logger is already initialized");
|
||||||
|
|
||||||
|
if (!Config.Variables.Exists("LogFolder"))
|
||||||
|
Config.Variables.Add("LogFolder", "./Data/Output/Logs/");
|
||||||
|
|
||||||
|
if (!Config.Variables.Exists("ErrorFolder"))
|
||||||
|
Config.Variables.Add("ErrorFolder", "./Data/Output/Errors/");
|
||||||
|
|
||||||
|
isInitialized = true;
|
||||||
|
logFolder = Config.Variables.GetValue("LogFolder");
|
||||||
|
errFolder = Config.Variables.GetValue("ErrorFolder");
|
||||||
|
isConsole = console;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public delegate void LogEventHandler(string Message);
|
||||||
|
public static event LogEventHandler LogEvent;
|
||||||
|
|
||||||
|
public static void Log(string Message)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("Logger is not initialized");
|
||||||
|
LogEvent?.Invoke(Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Log(string Message, params object[] Args)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("Logger is not initialized");
|
||||||
|
LogEvent?.Invoke(string.Format(Message, Args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Log(IMessage message, bool newLine)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("Logger is not initialized");
|
||||||
|
LogEvent?.Invoke(message.Content);
|
||||||
|
if (newLine)
|
||||||
|
LogEvent?.Invoke("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void WriteLine(string? message)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("Logger is not initialized");
|
||||||
|
if (message is not null)
|
||||||
|
LogEvent?.Invoke(message + '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogError(System.Exception ex)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("Logger is not initialized");
|
||||||
|
string message = "[ERROR]" + ex.Message;
|
||||||
|
LogEvent?.Invoke(message + '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LogError(string? message)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("Logger is not initialized");
|
||||||
|
if (message is not null)
|
||||||
|
LogEvent?.Invoke("[ERROR]" + message + '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void WriteLine()
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("Logger is not initialized");
|
||||||
|
LogEvent?.Invoke("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(string message)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("Logger is not initialized");
|
||||||
|
LogEvent?.Invoke(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void Write<T>(T c)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("Logger is not initialized");
|
||||||
|
LogEvent?.Invoke($"{c}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Write logs to file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="LogMessage">The message to be wrote</param>
|
||||||
|
public static void WriteLogFile(string LogMessage)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("Logger is not initialized");
|
||||||
|
var logsPath = logFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Log.txt";
|
||||||
|
Directory.CreateDirectory(logFolder);
|
||||||
|
File.AppendAllTextAsync(logsPath, LogMessage + " \n").Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Write error to file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ErrMessage">The message to be wrote</param>
|
||||||
|
public static void WriteErrFile(string ErrMessage)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("Logger is not initialized");
|
||||||
|
var errPath = errFolder +
|
||||||
|
$"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Error.txt";
|
||||||
|
Directory.CreateDirectory(errFolder);
|
||||||
|
File.AppendAllText(errPath, ErrMessage + " \n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void WriteErrFile(this Exception ex)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("Logger is not initialized");
|
||||||
|
WriteErrFile(ex.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,28 @@
|
|||||||
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))
|
||||||
{
|
{
|
||||||
@@ -37,14 +41,14 @@ namespace PluginManager.Online.Helpers
|
|||||||
// Convert absolute progress (bytes downloaded) into relative progress (0% - 100%)
|
// Convert absolute progress (bytes downloaded) into relative progress (0% - 100%)
|
||||||
var relativeProgress = new Progress<long>(totalBytes =>
|
var relativeProgress = new Progress<long>(totalBytes =>
|
||||||
{
|
{
|
||||||
progress.Report((float)totalBytes / contentLength.Value * 100);
|
progress?.Report((float)totalBytes / contentLength.Value * 100);
|
||||||
downloadedBytes?.Report(totalBytes);
|
downloadedBytes?.Report(totalBytes);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Use extension method to report progress while downloading
|
// Use extension method to report progress while downloading
|
||||||
await download.CopyToOtherStreamAsync(destination, bufferSize, relativeProgress, cancellation);
|
await download.CopyToOtherStreamAsync(destination, bufferSize, relativeProgress, cancellation);
|
||||||
progress.Report(1);
|
progress.Report(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,8 +64,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
@@ -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,24 +70,22 @@ 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);
|
Logger.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message);
|
||||||
Functions.WriteErrFile(exception.ToString());
|
Logger.WriteErrFile(exception.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,8 +116,8 @@ public class PluginsManager
|
|||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message);
|
Logger.WriteLine("Failed to execute command: listplugs\nReason: " + exception.Message);
|
||||||
Functions.WriteErrFile(exception.ToString());
|
Logger.WriteErrFile(exception.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new string[] { null!, null!, null! };
|
return new string[] { null!, null!, null! };
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
using PluginManager.Online.Helpers;
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,20 @@
|
|||||||
using PluginManager.Items;
|
using System;
|
||||||
using PluginManager.Online.Helpers;
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
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,29 +22,31 @@ 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)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<Update> DownloadUpdateInfo(string pakName)
|
public static async Task<List<string>> GetInfo(string pakName)
|
||||||
{
|
{
|
||||||
string url = "https://raw.githubusercontent.com/Wizzy69/installer/discord-bot-files/Versions";
|
|
||||||
List<string> info = await ServerCom.ReadTextFromURL(url);
|
|
||||||
VersionString? version = await VersionString.GetVersionOfPackageFromWeb(pakName);
|
|
||||||
|
|
||||||
if (version is null) return Update.Empty;
|
Utilities.WriteColorText("An update was found for &g" + pakName + "&c. Version: &r" +
|
||||||
Update update = new Update(pakName, string.Join('\n', info), version);
|
(await ServerCom.GetVersionOfPackageFromWeb(pakName))?.ToShortString() +
|
||||||
return update;
|
"&c. Current Version: &y" +
|
||||||
|
ServerCom.GetVersionOfPackage(pakName)?.ToShortString());
|
||||||
|
|
||||||
|
List<string> fileInfo = await ServerCom.ReadTextFromURL("");
|
||||||
|
return fileInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
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());
|
var pakUpdateInfo = await GetInfo(pakName);
|
||||||
|
Logger.Log(string.Join("\n", pakUpdateInfo));
|
||||||
await ConsoleCommandsHandler.ExecuteCommad("dwplug " + pakName);
|
await ConsoleCommandsHandler.ExecuteCommad("dwplug " + pakName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
using PluginManager.Online.Helpers;
|
|
||||||
|
|
||||||
namespace PluginManager.Online.Updates
|
|
||||||
{
|
|
||||||
public class Update
|
|
||||||
{
|
|
||||||
public static Update Empty = new Update(null, null, null);
|
|
||||||
public string pakName;
|
|
||||||
public string UpdateMessage;
|
|
||||||
|
|
||||||
public VersionString newVersion;
|
|
||||||
|
|
||||||
private bool isEmpty;
|
|
||||||
|
|
||||||
public Update(string pakName, string updateMessage, VersionString newVersion)
|
|
||||||
{
|
|
||||||
this.pakName = pakName;
|
|
||||||
UpdateMessage = updateMessage;
|
|
||||||
this.newVersion = newVersion;
|
|
||||||
|
|
||||||
if (pakName is null && updateMessage is null && newVersion is null)
|
|
||||||
isEmpty = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
if (isEmpty)
|
|
||||||
throw new System.Exception("The update is EMPTY. Can not print information about an empty update !");
|
|
||||||
return $"Package Name: {this.pakName}\n" +
|
|
||||||
$"Update Message: {UpdateMessage}\n" +
|
|
||||||
$"Version: {newVersion.ToString()}";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
139
PluginManager/Others/ArchiveManager.cs
Normal file
139
PluginManager/Others/ArchiveManager.cs
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PluginManager.Others
|
||||||
|
{
|
||||||
|
public static class ArchiveManager
|
||||||
|
{
|
||||||
|
public static bool isInitialized { get; private set; }
|
||||||
|
private static string archiveFolder;
|
||||||
|
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
if (isInitialized) throw new Exception("ArchiveManager is already initialized");
|
||||||
|
|
||||||
|
if (!Config.Variables.Exists("ArchiveFolder"))
|
||||||
|
Config.Variables.Add("ArchiveFolder", "./Data/PAKS/");
|
||||||
|
|
||||||
|
isInitialized = true;
|
||||||
|
archiveFolder = Config.Variables.GetValue("ArchiveFolder");
|
||||||
|
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Read data from a file that is inside an archive (ZIP format)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="FileName">The file name that is inside the archive or its full path</param>
|
||||||
|
/// <param name="archFile">The archive location from the PAKs folder</param>
|
||||||
|
/// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns>
|
||||||
|
public static async Task<string> ReadFromPakAsync(string FileName, string archFile)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("ArchiveManager is not initialized");
|
||||||
|
archFile = archiveFolder + archFile;
|
||||||
|
if (!File.Exists(archFile))
|
||||||
|
throw new Exception("Failed to load file !");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string textValue = null;
|
||||||
|
using (var fs = new FileStream(archFile, FileMode.Open))
|
||||||
|
using (var zip = new ZipArchive(fs, ZipArchiveMode.Read))
|
||||||
|
{
|
||||||
|
foreach (var entry in zip.Entries)
|
||||||
|
if (entry.Name == FileName || entry.FullName == FileName)
|
||||||
|
using (var s = entry.Open())
|
||||||
|
using (var reader = new StreamReader(s))
|
||||||
|
{
|
||||||
|
textValue = await reader.ReadToEndAsync();
|
||||||
|
reader.Close();
|
||||||
|
s.Close();
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return textValue;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await Task.Delay(100);
|
||||||
|
return await ReadFromPakAsync(FileName, archFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extract zip to location
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="zip">The zip location</param>
|
||||||
|
/// <param name="folder">The target location</param>
|
||||||
|
/// <param name="progress">The progress that is updated as a file is processed</param>
|
||||||
|
/// <param name="type">The type of progress</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task ExtractArchive(string zip, string folder, IProgress<float> progress,
|
||||||
|
UnzipProgressType type)
|
||||||
|
{
|
||||||
|
if (!isInitialized) throw new Exception("ArchiveManager is not initialized");
|
||||||
|
Directory.CreateDirectory(folder);
|
||||||
|
using (var archive = ZipFile.OpenRead(zip))
|
||||||
|
{
|
||||||
|
if (type == UnzipProgressType.PercentageFromNumberOfFiles)
|
||||||
|
{
|
||||||
|
var totalZIPFiles = archive.Entries.Count();
|
||||||
|
var currentZIPFile = 0;
|
||||||
|
foreach (var entry in archive.Entries)
|
||||||
|
{
|
||||||
|
if (entry.FullName.EndsWith("/")) // it is a folder
|
||||||
|
Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
|
||||||
|
|
||||||
|
else
|
||||||
|
try
|
||||||
|
{
|
||||||
|
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
currentZIPFile++;
|
||||||
|
await Task.Delay(10);
|
||||||
|
if (progress != null)
|
||||||
|
progress.Report((float)currentZIPFile / totalZIPFiles * 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == UnzipProgressType.PercentageFromTotalSize)
|
||||||
|
{
|
||||||
|
ulong zipSize = 0;
|
||||||
|
|
||||||
|
foreach (var entry in archive.Entries)
|
||||||
|
zipSize += (ulong)entry.CompressedLength;
|
||||||
|
|
||||||
|
ulong currentSize = 0;
|
||||||
|
foreach (var entry in archive.Entries)
|
||||||
|
{
|
||||||
|
if (entry.FullName.EndsWith("/"))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
|
||||||
|
currentSize += (ulong)entry.CompressedLength;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(10);
|
||||||
|
if (progress != null)
|
||||||
|
progress.Report((float)currentSize / zipSize * 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using Discord;
|
|
||||||
|
|
||||||
namespace PluginManager.Others;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A class that handles the sending of messages to the user.
|
|
||||||
/// </summary>
|
|
||||||
public static class ChannelManagement
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Get the text channel by name from server
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="server">The server</param>
|
|
||||||
/// <param name="name">The channel name</param>
|
|
||||||
/// <returns>
|
|
||||||
/// <see cref="IGuildChannel" />
|
|
||||||
/// </returns>
|
|
||||||
public static IGuildChannel GetTextChannel(this IGuild server, string name)
|
|
||||||
{
|
|
||||||
return server.GetTextChannel(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the voice channel by name from server
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="server">The server</param>
|
|
||||||
/// <param name="name">The channel name</param>
|
|
||||||
/// <returns>
|
|
||||||
/// <see cref="IGuildChannel" />
|
|
||||||
/// </returns>
|
|
||||||
public static IGuildChannel GetVoiceChannel(this IGuild server, string name)
|
|
||||||
{
|
|
||||||
return server.GetVoiceChannel(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the DM channel between <see cref="Discord.WebSocket.DiscordSocketClient" /> and <see cref="IGuildUser" />
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user"></param>
|
|
||||||
/// <returns>
|
|
||||||
/// <see cref="IDMChannel" />
|
|
||||||
/// </returns>
|
|
||||||
public static async Task<IDMChannel> GetDMChannel(IGuildUser user)
|
|
||||||
{
|
|
||||||
return await user.CreateDMChannelAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the channel where the message was sent
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">The message</param>
|
|
||||||
/// <returns>
|
|
||||||
/// <see cref="IChannel" />
|
|
||||||
/// </returns>
|
|
||||||
public static IChannel GetChannel(IMessage message)
|
|
||||||
{
|
|
||||||
return message.Channel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
19
PluginManager/Others/CmdArgs.cs
Normal file
19
PluginManager/Others/CmdArgs.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PluginManager.Others
|
||||||
|
{
|
||||||
|
public class CmdArgs
|
||||||
|
{
|
||||||
|
public SocketCommandContext context { get; init; }
|
||||||
|
public string cleanContent { get; init; }
|
||||||
|
public string commandUsed { get;init; }
|
||||||
|
public string[] arguments { get;init; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,29 +1,211 @@
|
|||||||
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)
|
||||||
|
Logger.Write(tableCross);
|
||||||
|
else
|
||||||
|
Logger.Write(tableWall);
|
||||||
|
for (var l = 0; l < row.Length; l++)
|
||||||
|
{
|
||||||
|
if (row[l][0] == tableLine)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < len[l] + 4; ++i)
|
||||||
|
Logger.Write(tableLine);
|
||||||
|
}
|
||||||
|
else if (row[l].Length == len[l])
|
||||||
|
{
|
||||||
|
Logger.Write(" ");
|
||||||
|
Logger.Write(row[l]);
|
||||||
|
Logger.Write(" ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var lenHalf = row[l].Length / 2;
|
||||||
|
for (var i = 0; i < (len[l] + 4) / 2 - lenHalf; ++i)
|
||||||
|
Logger.Write(" ");
|
||||||
|
Logger.Write(row[l]);
|
||||||
|
for (var i = (len[l] + 4) / 2 + lenHalf + 1; i < len[l] + 4; ++i)
|
||||||
|
Logger.Write(" ");
|
||||||
|
if (row[l].Length % 2 == 0)
|
||||||
|
Logger.Write(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Write(row[l][0] == tableLine ? tableCross : tableWall);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.WriteLine(); //end line
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format == TableFormat.CENTER_OVERALL_LENGTH)
|
||||||
|
{
|
||||||
|
var maxLen = 0;
|
||||||
|
foreach (var row in data)
|
||||||
|
foreach (var s in row)
|
||||||
|
if (s.Length > maxLen)
|
||||||
|
maxLen = s.Length;
|
||||||
|
|
||||||
|
var div = (maxLen + 4) / 2;
|
||||||
|
|
||||||
|
foreach (var row in data)
|
||||||
|
{
|
||||||
|
Logger.Write("\t");
|
||||||
|
if (row[0] == "-")
|
||||||
|
Logger.Write("+");
|
||||||
|
else
|
||||||
|
Logger.Write("|");
|
||||||
|
|
||||||
|
foreach (var s in row)
|
||||||
|
{
|
||||||
|
if (s == "-")
|
||||||
|
{
|
||||||
|
for (var i = 0; i < maxLen + 4; ++i)
|
||||||
|
Logger.Write("-");
|
||||||
|
}
|
||||||
|
else if (s.Length == maxLen)
|
||||||
|
{
|
||||||
|
Logger.Write(" ");
|
||||||
|
Logger.Write(s);
|
||||||
|
Logger.Write(" ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var lenHalf = s.Length / 2;
|
||||||
|
for (var i = 0; i < div - lenHalf; ++i)
|
||||||
|
Logger.Write(" ");
|
||||||
|
Logger.Write(s);
|
||||||
|
for (var i = div + lenHalf + 1; i < maxLen + 4; ++i)
|
||||||
|
Logger.Write(" ");
|
||||||
|
if (s.Length % 2 == 0)
|
||||||
|
Logger.Write(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s == "-")
|
||||||
|
Logger.Write("+");
|
||||||
|
else
|
||||||
|
Logger.Write("|");
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.WriteLine(); //end line
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format == TableFormat.DEFAULT)
|
||||||
|
{
|
||||||
|
var widths = new int[data[0].Length];
|
||||||
|
var space_between_columns = 3;
|
||||||
|
for (var i = 0; i < data.Count; i++)
|
||||||
|
for (var j = 0; j < data[i].Length; j++)
|
||||||
|
if (data[i][j].Length > widths[j])
|
||||||
|
widths[j] = data[i][j].Length;
|
||||||
|
|
||||||
|
for (var i = 0; i < data.Count; i++)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < data[i].Length; j++)
|
||||||
|
{
|
||||||
|
if (data[i][j] == "-")
|
||||||
|
data[i][j] = " ";
|
||||||
|
Logger.Write(data[i][j]);
|
||||||
|
for (var k = 0; k < widths[j] - data[i][j].Length + 1 + space_between_columns; k++)
|
||||||
|
Logger.Write(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("Unknown type of table");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void WriteColorText(string text, bool appendNewLineAtEnd = true)
|
||||||
|
{
|
||||||
|
if (!Logger.isConsole)
|
||||||
|
{
|
||||||
|
foreach (var item in Colors)
|
||||||
|
text = text.Replace($"{ColorPrefix}{item.Key}", "").Replace("&c", "");
|
||||||
|
Logger.Write(text);
|
||||||
|
if (appendNewLineAtEnd)
|
||||||
|
Logger.WriteLine();
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
var initialForeGround = Console.ForegroundColor;
|
||||||
|
var input = text.ToCharArray();
|
||||||
|
for (var i = 0; i < input.Length; i++)
|
||||||
|
if (input[i] == ColorPrefix)
|
||||||
|
{
|
||||||
|
if (i + 1 < input.Length)
|
||||||
|
{
|
||||||
|
if (Colors.ContainsKey(input[i + 1]))
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = Colors[input[i + 1]];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if (input[i + 1] == 'c')
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = initialForeGround;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Write(input[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.ForegroundColor = initialForeGround;
|
||||||
|
if (appendNewLineAtEnd)
|
||||||
|
Logger.WriteLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -32,8 +214,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 (!Logger.isConsole)
|
||||||
|
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 +234,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 +246,7 @@ namespace PluginManager.Others
|
|||||||
while (isRunning)
|
while (isRunning)
|
||||||
{
|
{
|
||||||
UpdateNoEnd();
|
UpdateNoEnd();
|
||||||
await System.Threading.Tasks.Task.Delay(100);
|
await Task.Delay(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +263,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 +283,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(" ");
|
Logger.Write(" ");
|
||||||
Console.CursorLeft = 0;
|
Console.CursorLeft = 0;
|
||||||
Console.WriteLine(message);
|
Logger.WriteLine(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,16 +301,14 @@ namespace PluginManager.Others
|
|||||||
private void UpdateNoEnd(string message)
|
private void UpdateNoEnd(string message)
|
||||||
{
|
{
|
||||||
Console.CursorLeft = 0;
|
Console.CursorLeft = 0;
|
||||||
Console.Write("[");
|
Logger.Write("[");
|
||||||
for (int i = 1; i <= position; i++)
|
for (var i = 1; i <= position; i++)
|
||||||
Console.Write(" ");
|
Logger.Write(" ");
|
||||||
Console.Write("<==()==>");
|
Logger.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(" ");
|
Logger.Write(" ");
|
||||||
Console.Write("] " + message);
|
Logger.Write("] " + message);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (position == BarLength - 1 || position == 1)
|
if (position == BarLength - 1 || position == 1)
|
||||||
@@ -136,16 +318,14 @@ namespace PluginManager.Others
|
|||||||
private void UpdateNoEnd()
|
private void UpdateNoEnd()
|
||||||
{
|
{
|
||||||
Console.CursorLeft = 0;
|
Console.CursorLeft = 0;
|
||||||
Console.Write("[");
|
Logger.Write("[");
|
||||||
for (int i = 1; i <= position; i++)
|
for (var i = 1; i <= position; i++)
|
||||||
Console.Write(" ");
|
Logger.Write(" ");
|
||||||
Console.Write("<==()==>");
|
Logger.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(" ");
|
Logger.Write(" ");
|
||||||
Console.Write("]");
|
Logger.Write("]");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (position == BarLength - 1 || position == 1)
|
if (position == BarLength - 1 || position == 1)
|
||||||
@@ -155,217 +335,34 @@ namespace PluginManager.Others
|
|||||||
private void UpdateNormal(float progress)
|
private void UpdateNormal(float progress)
|
||||||
{
|
{
|
||||||
Console.CursorLeft = 0;
|
Console.CursorLeft = 0;
|
||||||
Console.Write("[");
|
Logger.Write("[");
|
||||||
Console.CursorLeft = BarLength;
|
Console.CursorLeft = BarLength;
|
||||||
Console.Write("]");
|
Logger.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("#");
|
Logger.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(" ");
|
Logger.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 + " % ✓");
|
Logger.Write(progress + " % ✓");
|
||||||
else
|
else
|
||||||
Console.Write(MathF.Round(progress, 2) + " % ");
|
Logger.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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -1,178 +1,65 @@
|
|||||||
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.Security.Cryptography;
|
using System.IO;
|
||||||
using Discord.WebSocket;
|
using System.Runtime.InteropServices;
|
||||||
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>
|
||||||
public static readonly string dataFolder = @"./Data/Resources/";
|
public static readonly string dataFolder = @"./Data/Resources/";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The location for all logs
|
|
||||||
/// </summary>
|
|
||||||
public static readonly string logFolder = @"./Data/Output/Logs/";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The location for all errors
|
|
||||||
/// </summary>
|
|
||||||
public static readonly string errFolder = @"./Data/Output/Errors/";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Archives folder
|
|
||||||
/// </summary>
|
|
||||||
public static readonly string pakFolder = @"./Data/PAKS/";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Beta testing folder
|
|
||||||
/// </summary>
|
|
||||||
public static readonly string betaFolder = @"./Data/BetaTest/";
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Read data from a file that is inside an archive (ZIP format)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="FileName">The file name that is inside the archive or its full path</param>
|
|
||||||
/// <param name="archFile">The archive location from the PAKs folder</param>
|
|
||||||
/// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns>
|
|
||||||
public static async Task<string> ReadFromPakAsync(string FileName, string archFile)
|
|
||||||
{
|
|
||||||
archFile = pakFolder + archFile;
|
|
||||||
if (!File.Exists(archFile))
|
|
||||||
throw new Exception("Failed to load file !");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string textValue = null;
|
|
||||||
using (var fs = new FileStream(archFile, FileMode.Open))
|
|
||||||
using (var zip = new ZipArchive(fs, ZipArchiveMode.Read))
|
|
||||||
foreach (var entry in zip.Entries)
|
|
||||||
{
|
|
||||||
if (entry.Name == FileName || entry.FullName == FileName)
|
|
||||||
{
|
|
||||||
using (Stream s = entry.Open())
|
|
||||||
using (StreamReader reader = new StreamReader(s))
|
|
||||||
{
|
|
||||||
textValue = await reader.ReadToEndAsync();
|
|
||||||
reader.Close();
|
|
||||||
s.Close();
|
|
||||||
fs.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return textValue;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await Task.Delay(100);
|
|
||||||
return await ReadFromPakAsync(FileName, archFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Write logs to file
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="LogMessage">The message to be wrote</param>
|
|
||||||
public static void WriteLogFile(string LogMessage)
|
|
||||||
{
|
|
||||||
string logsPath = logFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Log.txt";
|
|
||||||
Directory.CreateDirectory(logFolder);
|
|
||||||
File.AppendAllText(logsPath, LogMessage + " \n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Write error to file
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ErrMessage">The message to be wrote</param>
|
|
||||||
public static void WriteErrFile(string ErrMessage)
|
|
||||||
{
|
|
||||||
string errPath = errFolder + $"{DateTime.Today.ToShortDateString().Replace("/", "-").Replace("\\", "-")} Error.txt";
|
|
||||||
Directory.CreateDirectory(errFolder);
|
|
||||||
File.AppendAllText(errPath, ErrMessage + " \n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void WriteErrFile(this Exception ex)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
Command command = new Command(message);
|
|
||||||
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,105 +68,6 @@ namespace PluginManager.Others
|
|||||||
totalBytesRead += bytesRead;
|
totalBytesRead += bytesRead;
|
||||||
progress?.Report(totalBytesRead);
|
progress?.Report(totalBytesRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extract zip to location
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="zip">The zip location</param>
|
|
||||||
/// <param name="folder">The target location</param>
|
|
||||||
/// <param name="progress">The progress that is updated as a file is processed</param>
|
|
||||||
/// <param name="type">The type of progress</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static async Task ExtractArchive(string zip, string folder, IProgress<float> progress, UnzipProgressType type)
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(folder);
|
|
||||||
using (ZipArchive archive = ZipFile.OpenRead(zip))
|
|
||||||
{
|
|
||||||
if (type == UnzipProgressType.PercentageFromNumberOfFiles)
|
|
||||||
{
|
|
||||||
int totalZIPFiles = archive.Entries.Count();
|
|
||||||
int currentZIPFile = 0;
|
|
||||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
|
||||||
{
|
|
||||||
if (entry.FullName.EndsWith("/")) // it is a folder
|
|
||||||
Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
|
|
||||||
|
|
||||||
else
|
|
||||||
try
|
|
||||||
{
|
|
||||||
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
currentZIPFile++;
|
|
||||||
await Task.Delay(10);
|
|
||||||
if (progress != null)
|
|
||||||
progress.Report((float)currentZIPFile / totalZIPFiles * 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (type == UnzipProgressType.PercentageFromTotalSize)
|
|
||||||
{
|
|
||||||
ulong zipSize = 0;
|
|
||||||
|
|
||||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
|
||||||
zipSize += (ulong)entry.CompressedLength;
|
|
||||||
|
|
||||||
ulong currentSize = 0;
|
|
||||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
|
||||||
{
|
|
||||||
if (entry.FullName.EndsWith("/"))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(Path.Combine(folder, entry.FullName));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
entry.ExtractToFile(Path.Combine(folder, entry.FullName), true);
|
|
||||||
currentSize += (ulong)entry.CompressedLength;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Failed to extract {entry.Name}. Exception: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
await Task.Delay(10);
|
|
||||||
if (progress != null)
|
|
||||||
progress.Report((float)currentSize / zipSize * 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <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>
|
||||||
@@ -291,9 +79,11 @@ 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());
|
||||||
|
await str.FlushAsync();
|
||||||
|
str.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -311,62 +101,8 @@ namespace PluginManager.Others
|
|||||||
text = new MemoryStream(Encoding.ASCII.GetBytes(input));
|
text = new MemoryStream(Encoding.ASCII.GetBytes(input));
|
||||||
text.Position = 0;
|
text.Position = 0;
|
||||||
var obj = await JsonSerializer.DeserializeAsync<T>(text);
|
var obj = await JsonSerializer.DeserializeAsync<T>(text);
|
||||||
|
await text.FlushAsync();
|
||||||
text.Close();
|
text.Close();
|
||||||
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)
|
|
||||||
{
|
|
||||||
Stream text;
|
|
||||||
if (File.Exists(input))
|
|
||||||
text = File.OpenRead(input);
|
|
||||||
|
|
||||||
else
|
|
||||||
text = new MemoryStream(Encoding.ASCII.GetBytes(input));
|
|
||||||
|
|
||||||
var jsonObject = JsonDocument.Parse(text);
|
|
||||||
|
|
||||||
var data = jsonObject.RootElement.TryGetProperty(codeName, out element);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string CreateMD5(string input)
|
|
||||||
{
|
|
||||||
using (MD5 md5 = MD5.Create())
|
|
||||||
{
|
|
||||||
byte[] inputBytes = Encoding.ASCII.GetBytes(input);
|
|
||||||
byte[] hashBytes = md5.ComputeHash(inputBytes);
|
|
||||||
return Convert.ToHexString(hashBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
@@ -16,7 +16,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Discord.Net" Version="3.7.2" />
|
<PackageReference Include="Discord.Net" Version="3.8.1" />
|
||||||
|
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.117" />
|
||||||
<PackageReference Include="Terminal.Gui" Version="1.8.2" />
|
<PackageReference Include="Terminal.Gui" Version="1.8.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
17
PluginManager/Variables.cs
Normal file
17
PluginManager/Variables.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using PluginManager.Database;
|
||||||
|
|
||||||
|
namespace PluginManager
|
||||||
|
{
|
||||||
|
public class Settings
|
||||||
|
{
|
||||||
|
|
||||||
|
public static class Variables
|
||||||
|
{
|
||||||
|
public static string WebsiteURL = "https://wizzy69.github.io/SethDiscordBot";
|
||||||
|
public static string UpdaterURL = "https://github.com/Wizzy69/installer/releases/download/release-1-discordbot/Updater.zip";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SqlDatabase sqlDatabase;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
137
README.md
137
README.md
@@ -15,84 +15,81 @@ This project is based on:
|
|||||||
Plugin Types:
|
Plugin Types:
|
||||||
1. Commands
|
1. Commands
|
||||||
2. Events
|
2. Events
|
||||||
|
3. Slash Commands
|
||||||
|
|
||||||
### How to create a plugin
|
### How to create a plugin
|
||||||
|
|
||||||
First of all, Create a new project (class library) in Visual Studio.
|
First of all, Create a new project (class library) in Visual Studio.
|
||||||

|
Then import the PluginManager.dll as project to your project.
|
||||||
|
|
||||||

|
## 1. Commands
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Now, let's add the PluginManager reference. It can be found inside the bot's main folder under
|
|
||||||
`DiscordBot/bin/Debug/net6.0/PluginManager.dll` or `PluginManager/bin/Debug/net6.0/PluginManager.dll`
|
|
||||||
after one successfull build.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
1. Commands
|
|
||||||
|
|
||||||
Commands are loaded when all plugins are loaded into memory. When an user executes the command, only then the Execute function is called.
|
Commands are loaded when all plugins are loaded into memory. When an user executes the command, only then the Execute function is called.
|
||||||
Commands are plugins that allow users to interact with them.
|
Commands are plugins that allow users to interact with them.
|
||||||
Here is an example of class that is a command class
|
Here is an example:
|
||||||
```cs
|
```cs
|
||||||
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
|
||||||
|
|
||||||
using PluginManager.Interfaces;
|
using PluginManager.Interfaces;
|
||||||
|
|
||||||
namespace CMD_Utils
|
namespace LevelingSystem;
|
||||||
|
|
||||||
|
internal class LevelCommand : DBCommand
|
||||||
{
|
{
|
||||||
class FlipCoin : DBCommand
|
public string Command => "level";
|
||||||
{
|
|
||||||
public string Command => "flip";
|
|
||||||
|
|
||||||
public string Description => "Flip a coin";
|
public List<string> Aliases => new() { "lvl" };
|
||||||
|
|
||||||
public string Usage => "flip";
|
public string Description => "Display tour current level";
|
||||||
|
|
||||||
public bool canUseDM => true;
|
public string Usage => "level";
|
||||||
|
|
||||||
public bool canUseServer => true;
|
|
||||||
|
|
||||||
public bool requireAdmin => false;
|
public bool requireAdmin => false;
|
||||||
|
|
||||||
public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM)
|
public async void ExecuteServer(SocketCommandContext context)
|
||||||
{
|
{
|
||||||
System.Random random = new System.Random();
|
object[] user = await Variables.database.ReadDataArrayAsync($"SELECT * FROM Levels WHERE UserID='{context.Message.Author.Id}'");
|
||||||
int r = random.Next(1, 3);
|
if (user is null)
|
||||||
if (r == 1)
|
{
|
||||||
await message.Channel.SendMessageAsync("Heads");
|
await context.Channel.SendMessageAsync("You are now unranked !");
|
||||||
else await message.Channel.SendMessageAsync("Tails");
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int level = (int)user[1];
|
||||||
|
int exp = (int)user[2];
|
||||||
|
|
||||||
|
var builder = new EmbedBuilder();
|
||||||
|
var r = new Random();
|
||||||
|
builder.WithColor(r.Next(256), r.Next(256), r.Next(256));
|
||||||
|
builder.AddField("Current Level", level, true)
|
||||||
|
.AddField("Current EXP", exp, true)
|
||||||
|
.AddField("Required Exp", (level * 8 + 24).ToString(), true);
|
||||||
|
builder.WithTimestamp(DateTimeOffset.Now);
|
||||||
|
builder.WithAuthor(context.Message.Author.Mention);
|
||||||
|
await context.Channel.SendMessageAsync(embed: builder.Build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
#### Code description:
|
#### Code description:
|
||||||
- Command - The keyword that triggers the execution for the command. This is what players must type in order to execute your command
|
- Command - The keyword that triggers the execution for the command. This is what players must type in order to execute your command
|
||||||
|
- Aliases - The aliases that can be used instead of the full name to execute the command
|
||||||
- Description - The description of your command. Can be anything you like
|
- Description - The description of your command. Can be anything you like
|
||||||
- Usage - The usage of your command. This is what `help [Command]` command will display
|
- Usage - The usage of your command. This is what `help [Command]` command will display
|
||||||
- canUseDM - true if you plan to let users execute this command in DM chat with bot
|
|
||||||
- canUseServer - true if you plan to let the users execute this command in a server chat
|
|
||||||
- requireAdmin - true if this command requres an user with Administrator permission in the server
|
- requireAdmin - true if this command requres an user with Administrator permission in the server
|
||||||
- Execute () - the function of your command.
|
- ExecuteServer () - the function that is executed only when the command is invoked in a server channel. (optional)
|
||||||
|
- context - the command context
|
||||||
|
- ExecuteDM () - the function that is executed only when the command is invoked in a private (DM) channel. (optional)
|
||||||
- context - the command context
|
- context - the command context
|
||||||
- message - the message itself
|
|
||||||
- client - the discord bot client
|
|
||||||
- isDM - true if the message was sent from DM chat
|
|
||||||
|
|
||||||
From here on, start coding. When your plugin is done, build it as any DLL project then add it to the following path
|
From here on, start coding. When your plugin is done, build it as any DLL project then add it to the following path
|
||||||
`{bot_executable}/Data/Plugins/Commands/<optional subfolder>/yourDLLName.dll`
|
`{bot_executable}/Data/Plugins/<optional subfolder>/[your dll name].dll`
|
||||||
Then, reload bot and execute command `lp` in bot's console. The plugin should be loaded into memory or an error is thrown if not. If an error is thrown, then
|
Then, reload bot and execute command `lp` in bot's console. The plugin should be loaded into memory or an error is thrown if not. If an error is thrown, then
|
||||||
there is something wrong in your command's code.
|
there is something wrong in your command's code.
|
||||||
|
|
||||||
2. Events
|
## 2. Events
|
||||||
|
|
||||||
Events are loaded when all plugins are loaded. At the moment when they are loaded, the Start function is called.
|
Events are loaded when all plugins are loaded. At the moment when they are loaded, the Start function is called.
|
||||||
Events are used if you want the bot to do something when something happens in server. The following example shows you how to catch when a user joins the server
|
Events are used if you want the bot to do something when something happens in server. The following example shows you how to catch when a user joins the server
|
||||||
@@ -125,3 +122,61 @@ public class OnUserJoin : DBEvent
|
|||||||
- Start() - The main body of your event. This is executed when the bot loads all plugins
|
- Start() - The main body of your event. This is executed when the bot loads all plugins
|
||||||
- client - the discord bot client
|
- client - the discord bot client
|
||||||
|
|
||||||
|
|
||||||
|
## 3. Slash Commands
|
||||||
|
|
||||||
|
|
||||||
|
Slash commands are server based commands. They work the same way as normal commands, but they require the `/` prefix as they are integrated
|
||||||
|
with the UI of Discord.
|
||||||
|
Here is an example:
|
||||||
|
```cs
|
||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
|
||||||
|
namespace SlashCommands
|
||||||
|
{
|
||||||
|
public class Random : DBSlashCommand
|
||||||
|
{
|
||||||
|
public string Name => "random";
|
||||||
|
|
||||||
|
public string Description => "Generates a random nunber between 2 values";
|
||||||
|
|
||||||
|
public bool canUseDM => true;
|
||||||
|
|
||||||
|
public List<SlashCommandOptionBuilder> Options => new List<SlashCommandOptionBuilder>()
|
||||||
|
{
|
||||||
|
new SlashCommandOptionBuilder() {Name = "min-value", Description = "Minimum value", IsRequired=true, Type = ApplicationCommandOptionType.Integer, MinValue = 0, MaxValue = int.MaxValue-1},
|
||||||
|
new SlashCommandOptionBuilder() {Name="max-value", Description = "Maximum value", IsRequired=true, Type=ApplicationCommandOptionType.Integer,MinValue = 0, MaxValue = int.MaxValue-1}
|
||||||
|
};
|
||||||
|
|
||||||
|
public async void ExecuteServer(SocketSlashCommand command)
|
||||||
|
{
|
||||||
|
var rnd = new System.Random();
|
||||||
|
var options = command.Data.Options.ToArray();
|
||||||
|
if (options.Count() != 2)
|
||||||
|
{
|
||||||
|
await command.RespondAsync("Invalid parameters", ephemeral: true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Int64 numberOne = (Int64)options[0].Value;
|
||||||
|
Int64 numberTwo = (Int64)options[1].Value;
|
||||||
|
|
||||||
|
await command.RespondAsync("Your generated number is " + rnd.Next((int)numberOne, (int)numberTwo), ephemeral: true);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Code description:
|
||||||
|
- Name - the command name (execute with /{Name})
|
||||||
|
- Description - The description of the command
|
||||||
|
- canUseDM - true id this command can be activated in DM chat, false otherwise
|
||||||
|
- Options - the arguments of the command
|
||||||
|
- ExecuteServer() - this function will be called if the command is invoked in a server channel (optional)
|
||||||
|
- context - the command context
|
||||||
|
- ExecuteDM() - this function will be called if the command is invoked in a DM channel (optional)
|
||||||
|
- context - the command context
|
||||||
|
|||||||
@@ -7,6 +7,16 @@ 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
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Roles", "..\DiscordBotItems\Roles\Roles.csproj", "{0900B4CB-B531-4A8D-98D8-E709A7C2E098}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DBEconomy", "..\DiscordBotItems\Plugins\DBEconomy\DBEconomy.csproj", "{0321365B-4ADC-4B1D-BD98-F573D36E83B2}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -21,6 +31,26 @@ 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
|
||||||
|
{0900B4CB-B531-4A8D-98D8-E709A7C2E098}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0900B4CB-B531-4A8D-98D8-E709A7C2E098}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0900B4CB-B531-4A8D-98D8-E709A7C2E098}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0900B4CB-B531-4A8D-98D8-E709A7C2E098}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0321365B-4ADC-4B1D-BD98-F573D36E83B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0321365B-4ADC-4B1D-BD98-F573D36E83B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0321365B-4ADC-4B1D-BD98-F573D36E83B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0321365B-4ADC-4B1D-BD98-F573D36E83B2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
Reference in New Issue
Block a user