Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3858156393 | |||
| 6279c5c3a9 | |||
| f58a57c6cd | |||
| d00ebfd7ed | |||
| ab279bd284 | |||
| 89c4932cd7 | |||
| c577f625c2 | |||
| 58624f4037 | |||
| c9249dc71b | |||
| 5e4f1ca35f | |||
| 0d8fdb5904 | |||
| 92a18e3495 | |||
| e929646e8e | |||
| 6315d13d18 | |||
| ee527bb36f | |||
| 86514d1770 | |||
| 9e8ed1e911 |
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using PluginManager;
|
|
||||||
using PluginManager.Interfaces;
|
using PluginManager.Interfaces;
|
||||||
using PluginManager.Others;
|
using PluginManager.Others;
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,8 @@ public class Exit : ICommandAction
|
|||||||
{
|
{
|
||||||
if (args is null || args.Length == 0)
|
if (args is null || args.Length == 0)
|
||||||
{
|
{
|
||||||
Config.Logger.Log("Exiting...", "Exit", isInternal: false);
|
Config.Logger.Log("Exiting...", source: typeof(ICommandAction), type: LogType.WARNING);
|
||||||
await Config.AppSettings.SaveToFile();
|
await Config.AppSettings.SaveToFile();
|
||||||
await Config.Logger.SaveToFile();
|
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -34,7 +33,7 @@ public class Exit : ICommandAction
|
|||||||
|
|
||||||
case "-f":
|
case "-f":
|
||||||
case "force":
|
case "force":
|
||||||
Config.Logger.Log("Exiting (FORCE)...", "Exit", LogLevel.WARNING, false);
|
Config.Logger.Log("Exiting (FORCE)...", source: typeof(ICommandAction), type: LogType.WARNING);
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
204
DiscordBot/Bot/Actions/Extra/PluginMethods.cs
Normal file
204
DiscordBot/Bot/Actions/Extra/PluginMethods.cs
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using DiscordBot.Utilities;
|
||||||
|
using PluginManager;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
using PluginManager.Loaders;
|
||||||
|
using PluginManager.Online;
|
||||||
|
using PluginManager.Others;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace DiscordBot.Bot.Actions.Extra;
|
||||||
|
|
||||||
|
internal static class PluginMethods
|
||||||
|
{
|
||||||
|
private static readonly PluginsManager PluginsManager = new();
|
||||||
|
|
||||||
|
internal static async Task List()
|
||||||
|
{
|
||||||
|
var data = await ConsoleUtilities.ExecuteWithProgressBar(PluginsManager.GetAvailablePlugins(), "Loading plugins...");
|
||||||
|
|
||||||
|
TableData tableData = new(new List<string> { "Name", "Description", "Type", "Version" });
|
||||||
|
foreach (var plugin in data) tableData.AddRow(plugin);
|
||||||
|
|
||||||
|
tableData.HasRoundBorders = false;
|
||||||
|
tableData.PrintAsTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static async Task RefreshPlugins(bool quiet)
|
||||||
|
{
|
||||||
|
await Program.internalActionManager.Execute("plugin", "load", quiet ? "-q" : string.Empty);
|
||||||
|
await Program.internalActionManager.Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static async Task DownloadPlugin(PluginsManager manager, string pluginName)
|
||||||
|
{
|
||||||
|
var pluginData = await manager.GetPluginLinkByName(pluginName);
|
||||||
|
if (pluginData.Length == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Plugin {pluginName} not found. Please check the spelling and try again.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pluginType = pluginData[0];
|
||||||
|
var pluginLink = pluginData[1];
|
||||||
|
var pluginRequirements = pluginData[2];
|
||||||
|
|
||||||
|
|
||||||
|
await AnsiConsole.Progress()
|
||||||
|
.Columns(new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(),
|
||||||
|
new ProgressBarColumn(),
|
||||||
|
new PercentageColumn()
|
||||||
|
})
|
||||||
|
.StartAsync(async ctx =>
|
||||||
|
{
|
||||||
|
var downloadTask = ctx.AddTask("Downloading plugin...");
|
||||||
|
|
||||||
|
IProgress<float> progress = new Progress<float>(p => { downloadTask.Value = p; });
|
||||||
|
|
||||||
|
await ServerCom.DownloadFileAsync(pluginLink, $"./Data/{pluginType}s/{pluginName}.dll", progress);
|
||||||
|
|
||||||
|
downloadTask.Increment(100);
|
||||||
|
|
||||||
|
ctx.Refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (pluginRequirements == string.Empty)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Finished installing " + pluginName + " successfully");
|
||||||
|
await RefreshPlugins(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<string> requirementsUrLs = new();
|
||||||
|
|
||||||
|
await AnsiConsole.Progress()
|
||||||
|
.Columns(new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(),
|
||||||
|
new ProgressBarColumn(),
|
||||||
|
new PercentageColumn()
|
||||||
|
})
|
||||||
|
.StartAsync(async ctx =>
|
||||||
|
{
|
||||||
|
var gatherInformationTask = ctx.AddTask("Gathering info...");
|
||||||
|
gatherInformationTask.IsIndeterminate = true;
|
||||||
|
requirementsUrLs = await ServerCom.ReadTextFromURL(pluginRequirements);
|
||||||
|
await Task.Delay(2000);
|
||||||
|
gatherInformationTask.Increment(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
await AnsiConsole.Progress()
|
||||||
|
.Columns(new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(),
|
||||||
|
new ProgressBarColumn(),
|
||||||
|
new PercentageColumn()
|
||||||
|
})
|
||||||
|
.StartAsync(async ctx =>
|
||||||
|
{
|
||||||
|
List<Tuple<ProgressTask, IProgress<float>, Task>> downloadTasks = new();
|
||||||
|
|
||||||
|
foreach (var info in requirementsUrLs)
|
||||||
|
{
|
||||||
|
if (info.Length < 2) continue;
|
||||||
|
string[] data = info.Split(',');
|
||||||
|
string url = data[0];
|
||||||
|
string fileName = data[1];
|
||||||
|
|
||||||
|
var task = ctx.AddTask($"Downloading {fileName}...");
|
||||||
|
IProgress<float> progress = new Progress<float>(p =>
|
||||||
|
{
|
||||||
|
task.Value = p;
|
||||||
|
});
|
||||||
|
|
||||||
|
var downloadTask = ServerCom.DownloadFileAsync(url, $"./{fileName}", progress);
|
||||||
|
downloadTasks.Add(new Tuple<ProgressTask, IProgress<float>, Task>(task, progress, downloadTask));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var task in downloadTasks)
|
||||||
|
{
|
||||||
|
await task.Item3;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
await RefreshPlugins(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static async Task<bool> LoadPlugins(string[] args)
|
||||||
|
{
|
||||||
|
var loader = new PluginLoader(Config.DiscordBot.client);
|
||||||
|
if (args.Length == 2 && args[1] == "-q")
|
||||||
|
{
|
||||||
|
loader.LoadPlugins();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cc = Console.ForegroundColor;
|
||||||
|
loader.onCMDLoad += (name, typeName, success, exception) =>
|
||||||
|
{
|
||||||
|
if (name == null || name.Length < 2)
|
||||||
|
name = typeName;
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Successfully loaded command : " + name, source: typeof(ICommandAction),
|
||||||
|
type: LogType.INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Failed to load command : " + name + " because " + exception?.Message,
|
||||||
|
source: typeof(ICommandAction), type: LogType.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.ForegroundColor = cc;
|
||||||
|
};
|
||||||
|
loader.onEVELoad += (name, typeName, success, exception) =>
|
||||||
|
{
|
||||||
|
if (name == null || name.Length < 2)
|
||||||
|
name = typeName;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Successfully loaded event : " + name, source: typeof(ICommandAction),
|
||||||
|
type: LogType.INFO);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Failed to load event : " + name + " because " + exception?.Message,
|
||||||
|
source: typeof(ICommandAction), type: LogType.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.ForegroundColor = cc;
|
||||||
|
};
|
||||||
|
|
||||||
|
loader.onSLSHLoad += (name, typeName, success, exception) =>
|
||||||
|
{
|
||||||
|
if (name == null || name.Length < 2)
|
||||||
|
name = typeName;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Successfully loaded slash command : " + name, source: typeof(ICommandAction),
|
||||||
|
type: LogType.INFO);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Failed to load slash command : " + name + " because " + exception?.Message,
|
||||||
|
source: typeof(ICommandAction), type: LogType.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.ForegroundColor = cc;
|
||||||
|
};
|
||||||
|
|
||||||
|
loader.LoadPlugins();
|
||||||
|
Console.ForegroundColor = cc;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
43
DiscordBot/Bot/Actions/Extra/SettingsConfigExtra.cs
Normal file
43
DiscordBot/Bot/Actions/Extra/SettingsConfigExtra.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using PluginManager;
|
||||||
|
|
||||||
|
namespace DiscordBot.Bot.Actions.Extra;
|
||||||
|
|
||||||
|
internal static class SettingsConfigExtra
|
||||||
|
{
|
||||||
|
internal static void SetSettings(string key, params string[] value)
|
||||||
|
{
|
||||||
|
if (key is null) return;
|
||||||
|
|
||||||
|
if (value is null) return;
|
||||||
|
|
||||||
|
if (!Config.AppSettings.ContainsKey(key))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Config.AppSettings[key] = string.Join(' ', value);
|
||||||
|
// Config.AppSettings.SaveToFile().Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void RemoveSettings(string key)
|
||||||
|
{
|
||||||
|
if (key is null) return;
|
||||||
|
|
||||||
|
if(!Config.AppSettings.ContainsKey(key))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Config.AppSettings.Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void AddSettings(string key, params string[] value)
|
||||||
|
{
|
||||||
|
if (key is null) return;
|
||||||
|
|
||||||
|
if (value is null) return;
|
||||||
|
|
||||||
|
if (Config.AppSettings.ContainsKey(key))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Config.AppSettings.Add(key, string.Join(' ', value));
|
||||||
|
// Config.AppSettings.SaveToFile().Wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ public class Help : ICommandAction
|
|||||||
|
|
||||||
items.Add(new[] { "-", "-", "-" });
|
items.Add(new[] { "-", "-", "-" });
|
||||||
|
|
||||||
Utilities.Utilities.FormatAndAlignTable(items,
|
ConsoleUtilities.FormatAndAlignTable(items,
|
||||||
TableFormat.CENTER_EACH_COLUMN_BASED
|
TableFormat.CENTER_EACH_COLUMN_BASED
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
@@ -55,7 +55,7 @@ public class Help : ICommandAction
|
|||||||
new[] { "-", "-", "-" }
|
new[] { "-", "-", "-" }
|
||||||
};
|
};
|
||||||
|
|
||||||
Utilities.Utilities.FormatAndAlignTable(actionData,
|
ConsoleUtilities.FormatAndAlignTable(actionData,
|
||||||
TableFormat.CENTER_EACH_COLUMN_BASED
|
TableFormat.CENTER_EACH_COLUMN_BASED
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using DiscordBot.Utilities;
|
using System.Windows.Input;
|
||||||
|
using DiscordBot.Bot.Actions.Extra;
|
||||||
using PluginManager;
|
using PluginManager;
|
||||||
using PluginManager.Interfaces;
|
using PluginManager.Interfaces;
|
||||||
using PluginManager.Loaders;
|
using PluginManager.Loaders;
|
||||||
using PluginManager.Online;
|
using PluginManager.Online;
|
||||||
using PluginManager.Others;
|
using PluginManager.Others;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
namespace DiscordBot.Bot.Actions;
|
namespace DiscordBot.Bot.Actions;
|
||||||
|
|
||||||
public class Plugin : ICommandAction
|
public class Plugin : ICommandAction
|
||||||
{
|
{
|
||||||
private bool pluginsLoaded;
|
private bool pluginsLoaded;
|
||||||
public string ActionName => "plugin";
|
public string ActionName => "plugin";
|
||||||
public string Description => "Manages plugins. Use plugin help for more info.";
|
public string Description => "Manages plugins. Use plugin help for more info.";
|
||||||
public string Usage => "plugin [help|list|load|install]";
|
public string Usage => "plugin [help|list|load|install|refresh]";
|
||||||
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
|
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
|
||||||
|
|
||||||
public async Task Execute(string[] args)
|
public async Task Execute(string[] args)
|
||||||
{
|
{
|
||||||
@@ -27,103 +29,36 @@ public class Plugin : ICommandAction
|
|||||||
Console.WriteLine("list : Lists all plugins");
|
Console.WriteLine("list : Lists all plugins");
|
||||||
Console.WriteLine("load : Loads all plugins");
|
Console.WriteLine("load : Loads all plugins");
|
||||||
Console.WriteLine("install : Installs a plugin");
|
Console.WriteLine("install : Installs a plugin");
|
||||||
|
Console.WriteLine("refresh : Refreshes the plugin list");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ( args[0] )
|
var manager = new PluginsManager();
|
||||||
|
|
||||||
|
switch (args[0])
|
||||||
{
|
{
|
||||||
case "list":
|
case "refresh":
|
||||||
var manager =
|
await PluginMethods.RefreshPlugins(true);
|
||||||
new PluginsManager(Program.URLs["PluginList"], Program.URLs["PluginVersions"]);
|
break;
|
||||||
|
|
||||||
var data = await manager.GetAvailablePlugins();
|
case "list":
|
||||||
var items = new List<string[]>
|
await PluginMethods.List();
|
||||||
{
|
|
||||||
new[] { "-", "-", "-", "-" },
|
|
||||||
new[] { "Name", "Description", "Type", "Version" },
|
|
||||||
new[] { "-", "-", "-", "-" }
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var plugin in data) items.Add(new[] { plugin[0], plugin[1], plugin[2], plugin[3] });
|
|
||||||
|
|
||||||
items.Add(new[] { "-", "-", "-", "-" });
|
|
||||||
|
|
||||||
Utilities.Utilities.FormatAndAlignTable(items, TableFormat.DEFAULT);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case "load":
|
case "load":
|
||||||
if (pluginsLoaded)
|
if (pluginsLoaded)
|
||||||
|
{
|
||||||
|
Config.Logger.Log("Plugins already loaded", source: typeof(ICommandAction), type: LogType.WARNING);
|
||||||
break;
|
break;
|
||||||
var loader = new PluginLoader(Config.DiscordBot.client);
|
}
|
||||||
var cc = Console.ForegroundColor;
|
|
||||||
loader.onCMDLoad += (name, typeName, success, exception) =>
|
if (Config.DiscordBot is null)
|
||||||
{
|
{
|
||||||
if (name == null || name.Length < 2)
|
Config.Logger.Log("DiscordBot is null", source: typeof(ICommandAction), type: LogType.WARNING);
|
||||||
name = typeName;
|
break;
|
||||||
if (success)
|
}
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
|
||||||
Console.WriteLine("[CMD] Successfully loaded command : " + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
pluginsLoaded = await PluginMethods.LoadPlugins(args);
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
|
||||||
if (exception is null)
|
|
||||||
Console.WriteLine("An error occured while loading: " + name);
|
|
||||||
else
|
|
||||||
Console.WriteLine("[CMD] Failed to load command : " + name + " because " +
|
|
||||||
exception!.Message
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.ForegroundColor = cc;
|
|
||||||
};
|
|
||||||
loader.onEVELoad += (name, typeName, success, exception) =>
|
|
||||||
{
|
|
||||||
if (name == null || name.Length < 2)
|
|
||||||
name = typeName;
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
|
||||||
Console.WriteLine("[EVENT] Successfully loaded event : " + name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
|
||||||
Console.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;
|
|
||||||
Console.WriteLine("[SLASH] Successfully loaded command : " + name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
|
||||||
Console.WriteLine("[SLASH] Failed to load command : " + name + " because " +
|
|
||||||
exception!.Message
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.ForegroundColor = cc;
|
|
||||||
};
|
|
||||||
|
|
||||||
loader.LoadPlugins();
|
|
||||||
Console.ForegroundColor = cc;
|
|
||||||
pluginsLoaded = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "install":
|
case "install":
|
||||||
@@ -140,58 +75,8 @@ public class Plugin : ICommandAction
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var pluginManager =
|
await PluginMethods.DownloadPlugin(manager, pluginName);
|
||||||
new PluginsManager(Program.URLs["PluginList"], Program.URLs["PluginVersions"]);
|
|
||||||
var pluginData = await pluginManager.GetPluginLinkByName(pluginName);
|
|
||||||
if (pluginData == null || pluginData.Length == 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Plugin {pluginName} not found. Please check the spelling and try again.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pluginType = pluginData[0];
|
|
||||||
var pluginLink = pluginData[1];
|
|
||||||
var pluginRequirements = pluginData[2];
|
|
||||||
|
|
||||||
|
|
||||||
Console.WriteLine("Downloading plugin...");
|
|
||||||
//download plugin progress bar for linux and windows terminals
|
|
||||||
var spinner = new Utilities.Utilities.Spinner();
|
|
||||||
spinner.Start();
|
|
||||||
IProgress<float> progress = new Progress<float>(p => { spinner.Message = $"Downloading {pluginName}... {Math.Round(p, 2)}% "; });
|
|
||||||
await ServerCom.DownloadFileAsync(pluginLink, $"./Data/{pluginType}s/{pluginName}.dll", progress);
|
|
||||||
spinner.Stop();
|
|
||||||
Console.WriteLine();
|
|
||||||
|
|
||||||
if (pluginRequirements == string.Empty)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Plugin installed successfully");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("Downloading plugin requirements...");
|
|
||||||
var requirementsURLs = await ServerCom.ReadTextFromURL(pluginRequirements);
|
|
||||||
|
|
||||||
foreach (var requirement in requirementsURLs)
|
|
||||||
{
|
|
||||||
if (requirement.Length < 2)
|
|
||||||
continue;
|
|
||||||
var reqdata = requirement.Split(',');
|
|
||||||
var url = reqdata[0];
|
|
||||||
var filename = reqdata[1];
|
|
||||||
|
|
||||||
Console.WriteLine($"Downloading {filename}... ");
|
|
||||||
spinner.Start();
|
|
||||||
|
|
||||||
await ServerCom.DownloadFileAsync(url, $"./{filename}.dll", null);
|
|
||||||
spinner.Stop();
|
|
||||||
await Task.Delay(1000);
|
|
||||||
Console.WriteLine("Downloaded " + filename + " successfully");
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("Finished installing " + pluginName + " successfully");
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
67
DiscordBot/Bot/Actions/SettingsConfig.cs
Normal file
67
DiscordBot/Bot/Actions/SettingsConfig.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using DiscordBot.Bot.Actions.Extra;
|
||||||
|
using PluginManager;
|
||||||
|
using PluginManager.Interfaces;
|
||||||
|
using PluginManager.Others;
|
||||||
|
|
||||||
|
namespace DiscordBot.Bot.Actions;
|
||||||
|
|
||||||
|
public class SettingsConfig : ICommandAction
|
||||||
|
{
|
||||||
|
public string ActionName => "config";
|
||||||
|
public string Description => "Change the settings of the bot";
|
||||||
|
public string Usage => "config [options] <setting?> <value?>";
|
||||||
|
public InternalActionRunType RunType => InternalActionRunType.ON_CALL;
|
||||||
|
public Task Execute(string[] args)
|
||||||
|
{
|
||||||
|
if (args is null)
|
||||||
|
{
|
||||||
|
foreach (var settings in Config.AppSettings)
|
||||||
|
Console.WriteLine(settings.Key + ": " + settings.Value);
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (args[0])
|
||||||
|
{
|
||||||
|
case "-s":
|
||||||
|
case "set":
|
||||||
|
if(args.Length < 3)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
SettingsConfigExtra.SetSettings(args[1],args[2..]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "-r":
|
||||||
|
case "remove":
|
||||||
|
if(args.Length < 2)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
SettingsConfigExtra.RemoveSettings(args[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "-a":
|
||||||
|
case "add":
|
||||||
|
if(args.Length < 3)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
SettingsConfigExtra.AddSettings(args[1], args[2..]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "-h":
|
||||||
|
case "-help":
|
||||||
|
Console.WriteLine("Options:");
|
||||||
|
Console.WriteLine("-s <settingName> <newValue>: Set a setting");
|
||||||
|
Console.WriteLine("-r <settingName>: Remove a setting");
|
||||||
|
Console.WriteLine("-a <settingName> <newValue>: Add a setting");
|
||||||
|
Console.WriteLine("-h: Show this help message");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Console.WriteLine("Invalid option");
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
<StartupObject/>
|
<StartupObject/>
|
||||||
<SignAssembly>False</SignAssembly>
|
<SignAssembly>False</SignAssembly>
|
||||||
<IsPublishable>True</IsPublishable>
|
<IsPublishable>True</IsPublishable>
|
||||||
<AssemblyVersion>1.0.2.2</AssemblyVersion>
|
<AssemblyVersion>1.0.3.1</AssemblyVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
@@ -34,7 +34,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Discord.Net" Version="3.11.0"/>
|
<PackageReference Include="Discord.Net" Version="3.11.0"/>
|
||||||
<PackageReference Include="Sodium.Core" Version="1.3.3"/>
|
<PackageReference Include="pythonnet" Version="3.0.1" />
|
||||||
|
<PackageReference Include="Spectre.Console" Version="0.47.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\PluginManager\PluginManager.csproj"/>
|
<ProjectReference Include="..\PluginManager\PluginManager.csproj"/>
|
||||||
|
|||||||
@@ -4,18 +4,28 @@ using System.Reflection;
|
|||||||
|
|
||||||
namespace DiscordBot;
|
namespace DiscordBot;
|
||||||
|
|
||||||
public class Entry
|
public static class Entry
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
if (args.Length == 1 && args[0] == "/purge_plugins")
|
||||||
|
{
|
||||||
|
foreach (var plugin in Directory.GetFiles("./Data/Plugins", "*.dll", SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
File.Delete(plugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
var currentDomain = AppDomain.CurrentDomain;
|
var currentDomain = AppDomain.CurrentDomain;
|
||||||
currentDomain.AssemblyResolve += LoadFromSameFolder;
|
currentDomain.AssemblyResolve += LoadFromSameFolder;
|
||||||
|
|
||||||
static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args)
|
static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args)
|
||||||
{
|
{
|
||||||
var folderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
|
var folderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!, "./Libraries");
|
||||||
"./Libraries"
|
|
||||||
);
|
|
||||||
var assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll");
|
var assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll");
|
||||||
if (!File.Exists(assemblyPath)) return null;
|
if (!File.Exists(assemblyPath)) return null;
|
||||||
var assembly = Assembly.LoadFrom(assemblyPath);
|
var assembly = Assembly.LoadFrom(assemblyPath);
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using PluginManager;
|
using PluginManager;
|
||||||
using PluginManager.Online;
|
using Spectre.Console;
|
||||||
|
|
||||||
namespace DiscordBot;
|
namespace DiscordBot;
|
||||||
|
|
||||||
@@ -10,55 +7,22 @@ public static class Installer
|
|||||||
{
|
{
|
||||||
public static void GenerateStartupConfig()
|
public static void GenerateStartupConfig()
|
||||||
{
|
{
|
||||||
Console.WriteLine("Welcome to the SethBot installer !");
|
AnsiConsole.MarkupLine("Welcome to the [bold]SethBot[/] installer !");
|
||||||
Console.WriteLine("First, we need to configure the bot. Don't worry, it will be quick !");
|
AnsiConsole.MarkupLine("First, we need to configure the bot. Don't worry, it will be quick !");
|
||||||
Console.WriteLine("The following information will be stored in the config.json file in the ./Data/Resources folder. You can change it later from there.");
|
|
||||||
Console.WriteLine("The bot token is required to run the bot. You can get it from the Discord Developer Portal. (https://discord.com/developers/applications)");
|
var token = AnsiConsole.Ask<string>("Please enter the bot [yellow]token[/]:");
|
||||||
|
var prefix = AnsiConsole.Ask<string>("Please enter the bot [yellow]prefix[/]:");
|
||||||
|
var serverId = AnsiConsole.Ask<string>("Please enter the [yellow]Server ID[/]:");
|
||||||
|
|
||||||
if (!Config.AppSettings.ContainsKey("token"))
|
if (string.IsNullOrWhiteSpace(serverId)) serverId = "NULL";
|
||||||
{
|
Config.AppSettings.Add("token", token);
|
||||||
Console.WriteLine("Please enter the bot token :");
|
Config.AppSettings.Add("prefix", prefix);
|
||||||
var token = Console.ReadLine();
|
Config.AppSettings.Add("ServerID", serverId);
|
||||||
Config.AppSettings.Add("token", token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Config.AppSettings.ContainsKey("prefix"))
|
|
||||||
{
|
|
||||||
Console.WriteLine("Please enter the bot prefix :");
|
|
||||||
var prefix = Console.ReadLine();
|
|
||||||
Config.AppSettings.Add("prefix", prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Config.AppSettings.ContainsKey("ServerID"))
|
|
||||||
{
|
|
||||||
Console.WriteLine("Please enter the Server ID :");
|
|
||||||
var serverId = Console.ReadLine();
|
|
||||||
Config.AppSettings.Add("ServerID", serverId);
|
|
||||||
}
|
|
||||||
|
|
||||||
Config.Logger.Log("Config Saved", "Installer", isInternal: true);
|
|
||||||
|
|
||||||
Config.AppSettings.SaveToFile();
|
Config.AppSettings.SaveToFile();
|
||||||
|
|
||||||
Console.WriteLine("Config saved !");
|
AnsiConsole.MarkupLine("[bold]Config saved ![/]");
|
||||||
}
|
|
||||||
|
Config.Logger.Log("Config Saved", source: typeof(Installer));
|
||||||
public static async Task SetupPluginDatabase()
|
|
||||||
{
|
|
||||||
Console.WriteLine("The plugin database is required to run the bot but there is nothing configured yet.");
|
|
||||||
Console.WriteLine("Downloading the default database...");
|
|
||||||
await DownloadPluginDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task DownloadPluginDatabase(
|
|
||||||
string url = "https://raw.githubusercontent.com/andreitdr/SethDiscordBot/gh-pages/defaultURLs.json")
|
|
||||||
{
|
|
||||||
var path = "./Data/Resources/URLs.json";
|
|
||||||
|
|
||||||
Directory.CreateDirectory("./Data/Resources");
|
|
||||||
var spinner = new Utilities.Utilities.Spinner();
|
|
||||||
spinner.Start();
|
|
||||||
await ServerCom.DownloadFileAsync(url, path, null);
|
|
||||||
spinner.Stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,32 @@
|
|||||||
using System;
|
using System;
|
||||||
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 System.Threading.Tasks;
|
||||||
|
using DiscordBot.Utilities;
|
||||||
using PluginManager.Bot;
|
using PluginManager.Bot;
|
||||||
using PluginManager.Online;
|
|
||||||
using PluginManager.Online.Helpers;
|
|
||||||
using PluginManager.Others;
|
using PluginManager.Others;
|
||||||
using PluginManager.Others.Actions;
|
using PluginManager.Others.Actions;
|
||||||
|
using Spectre.Console;
|
||||||
using static PluginManager.Config;
|
using static PluginManager.Config;
|
||||||
|
|
||||||
namespace DiscordBot;
|
namespace DiscordBot;
|
||||||
|
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
public static SettingsDictionary<string, string> URLs;
|
public static InternalActionManager internalActionManager;
|
||||||
public static InternalActionManager internalActionManager;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The main entry point for the application.
|
/// The main entry point for the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[STAThread]
|
|
||||||
public static void Startup(string[] args)
|
public static void Startup(string[] args)
|
||||||
{
|
{
|
||||||
PreLoadComponents(args).Wait();
|
PreLoadComponents(args).Wait();
|
||||||
|
|
||||||
|
if (!AppSettings.ContainsKey("ServerID") || !AppSettings.ContainsKey("token") || !AppSettings.ContainsKey("prefix"))
|
||||||
|
Installer.GenerateStartupConfig();
|
||||||
|
|
||||||
if (!AppSettings.ContainsKey("ServerID") || !AppSettings.ContainsKey("token") ||
|
HandleInput().Wait();
|
||||||
AppSettings["token"] == null ||
|
|
||||||
AppSettings["token"]?.Length != 70 && AppSettings["token"]?.Length != 59 ||
|
|
||||||
!AppSettings.ContainsKey("prefix") || AppSettings["prefix"] == null ||
|
|
||||||
AppSettings["prefix"]?.Length != 1 ||
|
|
||||||
args.Length == 1 && args[0] == "/reset")
|
|
||||||
Installer.GenerateStartupConfig();
|
|
||||||
|
|
||||||
HandleInput(args.ToList()).Wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -42,11 +34,11 @@ public class Program
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static void NoGUI()
|
private static void NoGUI()
|
||||||
{
|
{
|
||||||
#if DEBUG
|
internalActionManager.Initialize().Wait();
|
||||||
Console.WriteLine("Debug mode enabled");
|
internalActionManager.Execute("plugin", "load").Wait();
|
||||||
internalActionManager.Execute("plugin", "load").Wait(); // Load plugins at startup
|
internalActionManager.Refresh().Wait();
|
||||||
#endif
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var cmd = Console.ReadLine();
|
var cmd = Console.ReadLine();
|
||||||
@@ -64,56 +56,31 @@ public class Program
|
|||||||
/// Start the bot without user interface
|
/// Start the bot without user interface
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns the boot loader for the Discord Bot</returns>
|
/// <returns>Returns the boot loader for the Discord Bot</returns>
|
||||||
private static async Task<Boot> StartNoGui()
|
private static async Task StartNoGui()
|
||||||
{
|
{
|
||||||
Console.Clear();
|
Console.Clear();
|
||||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
||||||
|
|
||||||
var startupMessageList =
|
Console.WriteLine($"Running on version: {Assembly.GetExecutingAssembly().GetName().Version}");
|
||||||
await ServerCom.ReadTextFromURL(URLs["StartupMessage"]);
|
Console.WriteLine("Git SethBot: https://github.com/andreitdr/SethDiscordBot");
|
||||||
|
Console.WriteLine("Git Plugins: https://github.com/andreitdr/SethPlugins");
|
||||||
|
|
||||||
|
ConsoleUtilities.WriteColorText("&rRemember to close the bot using the ShutDown command (&yexit&r) or some settings won't be saved");
|
||||||
|
|
||||||
foreach (var message in startupMessageList)
|
ConsoleUtilities.WriteColorText($"Running on &m{Functions.GetOperatingSystem()}");
|
||||||
Console.WriteLine(message);
|
|
||||||
|
|
||||||
Console.WriteLine(
|
|
||||||
$"Running on version: {Assembly.GetExecutingAssembly().GetName().Version}"
|
|
||||||
);
|
|
||||||
Console.WriteLine($"Git URL: {AppSettings["GitURL"]}");
|
|
||||||
|
|
||||||
Utilities.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 (AppSettings.ContainsKey("LaunchMessage"))
|
|
||||||
Utilities.Utilities.WriteColorText(AppSettings["LaunchMessage"]);
|
|
||||||
|
|
||||||
|
|
||||||
Utilities.Utilities.WriteColorText(
|
|
||||||
"Please note that the bot saves a backup save file every time you are using the shudown command (&ysd&c)"
|
|
||||||
);
|
|
||||||
|
|
||||||
Console.WriteLine("Running on " + Functions.GetOperatingSystem());
|
|
||||||
Console.WriteLine("============================ LOG ============================");
|
Console.WriteLine("============================ LOG ============================");
|
||||||
|
|
||||||
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var token = "";
|
var token = AppSettings["token"];
|
||||||
#if DEBUG
|
|
||||||
if (File.Exists("./Data/Resources/token.txt")) token = File.ReadAllText("./Data/Resources/token.txt");
|
|
||||||
else token = AppSettings["token"];
|
|
||||||
#else
|
|
||||||
token = AppSettings["token"];
|
|
||||||
#endif
|
|
||||||
var prefix = AppSettings["prefix"];
|
var prefix = AppSettings["prefix"];
|
||||||
var discordbooter = new Boot(token, prefix);
|
var discordbooter = new Boot(token, prefix);
|
||||||
await discordbooter.Awake();
|
await discordbooter.Awake();
|
||||||
return discordbooter;
|
|
||||||
}
|
}
|
||||||
catch ( Exception ex )
|
catch ( Exception ex )
|
||||||
{
|
{
|
||||||
Logger.Log(ex.ToString(), "Bot", LogLevel.ERROR);
|
Logger.Log(ex.ToString(), source: typeof(Program), type: LogType.CRITICAL);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,27 +88,12 @@ public class Program
|
|||||||
/// Handle user input arguments from the startup of the application
|
/// Handle user input arguments from the startup of the application
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">The arguments</param>
|
/// <param name="args">The arguments</param>
|
||||||
private static async Task HandleInput(List<string> args)
|
private static async Task HandleInput()
|
||||||
{
|
{
|
||||||
Console.WriteLine("Loading Core ...");
|
await StartNoGui();
|
||||||
|
|
||||||
//Handle arguments here:
|
|
||||||
|
|
||||||
if (args.Contains("--gui"))
|
|
||||||
{
|
|
||||||
// GUI not implemented yet
|
|
||||||
Console.WriteLine("GUI not implemented yet");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Starting bot after all arguments are handled
|
|
||||||
|
|
||||||
var b = await StartNoGui();
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
internalActionManager = new InternalActionManager("./Data/Actions", "*.dll");
|
internalActionManager = new InternalActionManager("./Data/Plugins", "*.dll");
|
||||||
await internalActionManager.Initialize();
|
|
||||||
|
|
||||||
NoGUI();
|
NoGUI();
|
||||||
}
|
}
|
||||||
catch ( IOException ex )
|
catch ( IOException ex )
|
||||||
@@ -150,12 +102,12 @@ public class Program
|
|||||||
{
|
{
|
||||||
if (AppSettings.ContainsKey("LaunchMessage"))
|
if (AppSettings.ContainsKey("LaunchMessage"))
|
||||||
AppSettings.Add("LaunchMessage",
|
AppSettings.Add("LaunchMessage",
|
||||||
"An error occured while closing the bot last time. Please consider closing the bot using the &rsd&c method !\nThere is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !"
|
"An error occured while closing the bot last time. Please consider closing the bot using the &rexit&c method !\n" +
|
||||||
);
|
"There is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !");
|
||||||
Logger
|
|
||||||
.Log("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 !",
|
Logger.Log("An error occured while closing the bot last time. Please consider closing the bot using the &rexit&c method !\n" +
|
||||||
"Bot", LogLevel.ERROR
|
"There is a risk of losing all data or corruption of the save file, which in some cases requires to reinstall the bot !",
|
||||||
);
|
source: typeof(Program), type: LogType.ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,84 +116,27 @@ public class Program
|
|||||||
{
|
{
|
||||||
await Initialize();
|
await Initialize();
|
||||||
|
|
||||||
Logger.LogEvent += (message, type, isInternal) =>
|
Logger.OnLog += (sender, logMessage) =>
|
||||||
{
|
{
|
||||||
if (type == LogLevel.INFO)
|
string messageColor = logMessage.Type switch
|
||||||
Console.ForegroundColor = ConsoleColor.Green;
|
{
|
||||||
else if (type == LogLevel.WARNING)
|
LogType.INFO => "[green]",
|
||||||
Console.ForegroundColor = ConsoleColor.DarkYellow;
|
LogType.WARNING => "[yellow]",
|
||||||
else if (type == LogLevel.ERROR)
|
LogType.ERROR => "[red]",
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
LogType.CRITICAL => "[red]",
|
||||||
else if (type == LogLevel.CRITICAL)
|
_ => "[white]"
|
||||||
Console.ForegroundColor = ConsoleColor.DarkRed;
|
};
|
||||||
|
|
||||||
Console.WriteLine($"[{type.ToString()}] {message}");
|
if (logMessage.Message.Contains('['))
|
||||||
Console.ResetColor();
|
{
|
||||||
|
// If the message contains a tag, just print it as it is. No need to format it
|
||||||
|
Console.WriteLine(logMessage.Message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnsiConsole.MarkupLine($"{messageColor}{logMessage.ThrowTime} {logMessage.Message} [/]");
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!Directory.Exists("./Data/Resources") || !File.Exists("./Data/Resources/URLs.json"))
|
|
||||||
await Installer.SetupPluginDatabase();
|
|
||||||
|
|
||||||
|
|
||||||
URLs = new SettingsDictionary<string, string>("./Data/Resources/URLs.json");
|
|
||||||
|
|
||||||
|
|
||||||
Console.WriteLine("Loading resources ...");
|
|
||||||
|
|
||||||
if (AppSettings.ContainsKey("DeleteLogsAtStartup"))
|
|
||||||
if (AppSettings["DeleteLogsAtStartup"] == "true")
|
|
||||||
foreach (var file in Directory.GetFiles("./Output/Logs/"))
|
|
||||||
File.Delete(file);
|
|
||||||
|
|
||||||
var OnlineDefaultKeys = await ServerCom.ReadTextFromURL(URLs["SetupKeys"]);
|
|
||||||
|
|
||||||
|
|
||||||
AppSettings["Version"] = Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
|
||||||
|
|
||||||
foreach (var key in OnlineDefaultKeys)
|
|
||||||
{
|
|
||||||
if (key.Length <= 3 || !key.Contains(' ')) continue;
|
|
||||||
var s = key.Split(' ');
|
|
||||||
try
|
|
||||||
{
|
|
||||||
AppSettings[s[0]] = s[1];
|
|
||||||
}
|
|
||||||
catch ( Exception ex )
|
|
||||||
{
|
|
||||||
Logger.Log(ex.ToString(), "Bot", LogLevel.ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var onlineSettingsList = await ServerCom.ReadTextFromURL(URLs["Versions"]);
|
AppSettings["Version"] = Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
||||||
foreach (var key in onlineSettingsList)
|
|
||||||
{
|
|
||||||
if (key.Length <= 3 || !key.Contains(' ')) continue;
|
|
||||||
|
|
||||||
var s = key.Split(' ');
|
|
||||||
switch ( s[0] )
|
|
||||||
{
|
|
||||||
case "CurrentVersion":
|
|
||||||
var currentVersion = AppSettings["Version"];
|
|
||||||
var newVersion = s[1];
|
|
||||||
if (new VersionString(newVersion) != new VersionString(newVersion))
|
|
||||||
{
|
|
||||||
Console.WriteLine("A new updated was found. Check the changelog for more information.");
|
|
||||||
var changeLog = await ServerCom.ReadTextFromURL(URLs["Changelog"]);
|
|
||||||
foreach (var item in changeLog)
|
|
||||||
Utilities.Utilities.WriteColorText(item);
|
|
||||||
Console.WriteLine("Current version: " + currentVersion);
|
|
||||||
Console.WriteLine("Latest version: " + newVersion);
|
|
||||||
|
|
||||||
Console.WriteLine("Download from here: https://github.com/andreitdr/SethDiscordBot/releases");
|
|
||||||
|
|
||||||
Console.WriteLine("Press any key to continue ...");
|
|
||||||
Console.ReadKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,86 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
namespace DiscordBot.Utilities;
|
namespace DiscordBot.Utilities;
|
||||||
|
|
||||||
public static class Utilities
|
public class TableData
|
||||||
{
|
{
|
||||||
|
public List<string> Columns;
|
||||||
|
public List<string[]> Rows;
|
||||||
|
|
||||||
|
public bool IsEmpty => Rows.Count == 0;
|
||||||
|
public bool HasRoundBorders { get; set; } = true;
|
||||||
|
|
||||||
|
public TableData(List<string> columns)
|
||||||
|
{
|
||||||
|
Columns = columns;
|
||||||
|
Rows = new List<string[]>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TableData(string[] columns)
|
||||||
|
{
|
||||||
|
Columns = columns.ToList();
|
||||||
|
Rows = new List<string[]>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRow(string[] row)
|
||||||
|
{
|
||||||
|
Rows.Add(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ConsoleUtilities
|
||||||
|
{
|
||||||
|
|
||||||
|
public static async Task<T> ExecuteWithProgressBar<T>(Task<T> function, string message)
|
||||||
|
{
|
||||||
|
T result = default;
|
||||||
|
await AnsiConsole.Progress()
|
||||||
|
.Columns(
|
||||||
|
new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(),
|
||||||
|
new ProgressBarColumn(),
|
||||||
|
new PercentageColumn(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.StartAsync(
|
||||||
|
async ctx =>
|
||||||
|
{
|
||||||
|
var task = ctx.AddTask(message);
|
||||||
|
task.IsIndeterminate = true;
|
||||||
|
result = await function;
|
||||||
|
task.Increment(100);
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task ExecuteWithProgressBar(Task function, string message)
|
||||||
|
{
|
||||||
|
await AnsiConsole.Progress()
|
||||||
|
.Columns(new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(),
|
||||||
|
new ProgressBarColumn(),
|
||||||
|
new PercentageColumn(),
|
||||||
|
})
|
||||||
|
.StartAsync(async ctx =>
|
||||||
|
{
|
||||||
|
var task = ctx.AddTask(message);
|
||||||
|
task.IsIndeterminate = true;
|
||||||
|
await function;
|
||||||
|
task.Increment(100);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly Dictionary<char, ConsoleColor> Colors = new()
|
private static readonly Dictionary<char, ConsoleColor> Colors = new()
|
||||||
{
|
{
|
||||||
{ 'g', ConsoleColor.Green },
|
{ 'g', ConsoleColor.Green },
|
||||||
@@ -16,20 +91,44 @@ public static class Utilities
|
|||||||
};
|
};
|
||||||
|
|
||||||
private static readonly char ColorPrefix = '&';
|
private static readonly char ColorPrefix = '&';
|
||||||
|
|
||||||
|
|
||||||
private static bool CanAproximateTo(this float f, float y)
|
private static bool CanAproximateTo(this float f, float y)
|
||||||
{
|
{
|
||||||
return MathF.Abs(f - y) < 0.000001;
|
return MathF.Abs(f - y) < 0.000001;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void PrintAsTable(this TableData tableData)
|
||||||
|
{
|
||||||
|
var table = new Table();
|
||||||
|
table.Border(tableData.HasRoundBorders ? TableBorder.Rounded : TableBorder.Square);
|
||||||
|
table.AddColumns(tableData.Columns.ToArray());
|
||||||
|
foreach (var row in tableData.Rows)
|
||||||
|
table.AddRow(row);
|
||||||
|
|
||||||
|
AnsiConsole.Write(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A way to create a table based on input data
|
/// A way to create a table based on input data
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="data">The List of arrays of strings that represent the rows.</param>
|
/// <param name="data">The List of arrays of string that represent the rows.</param>
|
||||||
public static void FormatAndAlignTable(List<string[]> data, TableFormat format)
|
public static void FormatAndAlignTable(List<string[]> data, TableFormat format)
|
||||||
{
|
{
|
||||||
|
if (format == TableFormat.SPECTRE_CONSOLE)
|
||||||
|
{
|
||||||
|
var table = new Table();
|
||||||
|
table.Border(TableBorder.Rounded);
|
||||||
|
table.AddColumns(data[0]);
|
||||||
|
data.RemoveAt(0);
|
||||||
|
foreach (var row in data)
|
||||||
|
table.AddRow(row);
|
||||||
|
|
||||||
|
AnsiConsole.Write(table);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (format == TableFormat.CENTER_EACH_COLUMN_BASED)
|
if (format == TableFormat.CENTER_EACH_COLUMN_BASED)
|
||||||
{
|
{
|
||||||
var tableLine = '-';
|
var tableLine = '-';
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
public enum TableFormat
|
public enum TableFormat
|
||||||
{
|
{
|
||||||
|
SPECTRE_CONSOLE,
|
||||||
CENTER_EACH_COLUMN_BASED,
|
CENTER_EACH_COLUMN_BASED,
|
||||||
CENTER_OVERALL_LENGTH,
|
CENTER_OVERALL_LENGTH,
|
||||||
DEFAULT
|
DEFAULT
|
||||||
|
|||||||
@@ -78,16 +78,13 @@ public 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);
|
|
||||||
|
|
||||||
Config._DiscordBotClient = this;
|
Config._DiscordBotClient = this;
|
||||||
|
|
||||||
while (!isReady) ;
|
while (!isReady) ;
|
||||||
@@ -108,8 +105,7 @@ public class Boot
|
|||||||
if (arg.Message.Contains("401"))
|
if (arg.Message.Contains("401"))
|
||||||
{
|
{
|
||||||
Config.AppSettings.Remove("token");
|
Config.AppSettings.Remove("token");
|
||||||
Config.Logger.Log("The token is invalid. Please restart the bot and enter a valid token.", this,
|
Config.Logger.Log("The token is invalid. Please restart the bot and enter a valid token.", source:typeof(Boot), type: LogType.CRITICAL);
|
||||||
LogLevel.ERROR);
|
|
||||||
await Config.AppSettings.SaveToFile();
|
await Config.AppSettings.SaveToFile();
|
||||||
await Task.Delay(4000);
|
await Task.Delay(4000);
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
@@ -118,7 +114,7 @@ public class Boot
|
|||||||
|
|
||||||
private async Task Client_LoggedOut()
|
private async Task Client_LoggedOut()
|
||||||
{
|
{
|
||||||
Config.Logger.Log("Successfully Logged Out", this);
|
Config.Logger.Log("Successfully Logged Out", source: typeof(Boot));
|
||||||
await Log(new LogMessage(LogSeverity.Info, "Boot", "Successfully logged out from discord !"));
|
await Log(new LogMessage(LogSeverity.Info, "Boot", "Successfully logged out from discord !"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +126,7 @@ public class Boot
|
|||||||
|
|
||||||
private Task LoggedIn()
|
private Task LoggedIn()
|
||||||
{
|
{
|
||||||
Config.Logger.Log("Successfully Logged In", this);
|
Config.Logger.Log("Successfully Logged In", source: typeof(Boot));
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,13 +136,12 @@ public class Boot
|
|||||||
{
|
{
|
||||||
case LogSeverity.Error:
|
case LogSeverity.Error:
|
||||||
case LogSeverity.Critical:
|
case LogSeverity.Critical:
|
||||||
Config.Logger.Log(message.Message, this, LogLevel.ERROR);
|
Config.Logger.Log(message.Message, source: typeof(Boot), type: LogType.ERROR);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LogSeverity.Info:
|
case LogSeverity.Info:
|
||||||
case LogSeverity.Debug:
|
case LogSeverity.Debug:
|
||||||
Config.Logger.Log(message.Message, this);
|
Config.Logger.Log(message.Message, source: typeof(Boot), type: LogType.INFO);
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ internal class CommandHandler
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Config.Logger.Log(ex.Message, "CommandHandler", LogLevel.ERROR);
|
Config.Logger.Log(ex.Message, type: LogType.ERROR, source: typeof(CommandHandler));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
@@ -124,10 +124,9 @@ internal class CommandHandler
|
|||||||
.Substring(botPrefix.Length))));
|
.Substring(botPrefix.Length))));
|
||||||
cleanMessage = message.Content.Substring(botPrefix.Length);
|
cleanMessage = message.Content.Substring(botPrefix.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plugin is null)
|
if (plugin is null)
|
||||||
throw new Exception("Failed to run command ! " + message.CleanContent + " (user: " +
|
return;
|
||||||
context.Message.Author.Username + " - " + context.Message.Author.Id + ")");
|
|
||||||
|
|
||||||
if (plugin.requireAdmin && !context.Message.Author.isAdmin())
|
if (plugin.requireAdmin && !context.Message.Author.isAdmin())
|
||||||
return;
|
return;
|
||||||
@@ -139,14 +138,20 @@ internal class CommandHandler
|
|||||||
argsClean = string.Join(' ', split, 1, split.Length - 1).Split(' ');
|
argsClean = string.Join(' ', split, 1, split.Length - 1).Split(' ');
|
||||||
|
|
||||||
DBCommandExecutingArguments cmd = new(context, cleanMessage, split[0], argsClean);
|
DBCommandExecutingArguments cmd = new(context, cleanMessage, split[0], argsClean);
|
||||||
|
|
||||||
|
Config.Logger.Log(
|
||||||
|
message: $"User ({context.User.Username}) from Guild \"{context.Guild.Name}\" executed command \"{cmd.cleanContent}\"",
|
||||||
|
source: typeof(CommandHandler),
|
||||||
|
type: LogType.INFO
|
||||||
|
);
|
||||||
|
|
||||||
if (context.Channel is SocketDMChannel)
|
if (context.Channel is SocketDMChannel)
|
||||||
plugin.ExecuteDM(cmd);
|
plugin.ExecuteDM(cmd);
|
||||||
else plugin.ExecuteServer(cmd);
|
else plugin.ExecuteServer(cmd);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Config.Logger.Log(ex.Message, this, LogLevel.ERROR);
|
Config.Logger.Log(ex.Message, type: LogType.ERROR, source: typeof(CommandHandler));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ namespace PluginManager;
|
|||||||
|
|
||||||
public class Config
|
public class Config
|
||||||
{
|
{
|
||||||
private static bool IsLoaded;
|
private static bool _isLoaded;
|
||||||
public static DBLogger Logger;
|
public static Logger Logger;
|
||||||
public static SettingsDictionary<string, string>? AppSettings;
|
public static SettingsDictionary<string, string> AppSettings;
|
||||||
|
|
||||||
internal static Boot? _DiscordBotClient;
|
internal static Boot? _DiscordBotClient;
|
||||||
|
|
||||||
@@ -19,8 +19,8 @@ public class Config
|
|||||||
|
|
||||||
public static async Task Initialize()
|
public static async Task Initialize()
|
||||||
{
|
{
|
||||||
if (IsLoaded) return;
|
if (_isLoaded) return;
|
||||||
|
|
||||||
Directory.CreateDirectory("./Data/Resources");
|
Directory.CreateDirectory("./Data/Resources");
|
||||||
Directory.CreateDirectory("./Data/Plugins");
|
Directory.CreateDirectory("./Data/Plugins");
|
||||||
Directory.CreateDirectory("./Data/PAKS");
|
Directory.CreateDirectory("./Data/PAKS");
|
||||||
@@ -30,15 +30,14 @@ public class Config
|
|||||||
AppSettings = new SettingsDictionary<string, string>("./Data/Resources/config.json");
|
AppSettings = new SettingsDictionary<string, string>("./Data/Resources/config.json");
|
||||||
|
|
||||||
AppSettings["LogFolder"] = "./Data/Logs/Logs";
|
AppSettings["LogFolder"] = "./Data/Logs/Logs";
|
||||||
AppSettings["ErrorFolder"] = "./Data/Logs/Errors";
|
|
||||||
|
|
||||||
Logger = new DBLogger();
|
Logger = new Logger(false, true);
|
||||||
|
|
||||||
ArchiveManager.Initialize();
|
ArchiveManager.Initialize();
|
||||||
|
|
||||||
IsLoaded = true;
|
_isLoaded = true;
|
||||||
|
|
||||||
Logger.Log("Config initialized", LogLevel.INFO);
|
Logger.Log(message: "Config initialized", source: typeof(Config));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PluginManager.Interfaces.Exceptions;
|
|
||||||
|
|
||||||
public interface IException
|
|
||||||
{
|
|
||||||
public List<string> Messages { get; set; }
|
|
||||||
public bool isFatal { get; }
|
|
||||||
public string GenerateFullMessage();
|
|
||||||
public void HandleException();
|
|
||||||
|
|
||||||
public IException AppendError(string message);
|
|
||||||
|
|
||||||
public IException AppendError(List<string> messages);
|
|
||||||
public IException IsFatal(bool isFatal = true);
|
|
||||||
|
|
||||||
}
|
|
||||||
15
PluginManager/Interfaces/Logger/ILog.cs
Normal file
15
PluginManager/Interfaces/Logger/ILog.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using PluginManager.Others;
|
||||||
|
|
||||||
|
namespace PluginManager.Interfaces.Logger;
|
||||||
|
|
||||||
|
internal interface ILog
|
||||||
|
{
|
||||||
|
string Message { get; set; }
|
||||||
|
string OutputFile { get; set; }
|
||||||
|
|
||||||
|
Type? Source { get; set; }
|
||||||
|
|
||||||
|
LogType Type { get; set; }
|
||||||
|
DateTime ThrowTime { get; set; }
|
||||||
|
}
|
||||||
17
PluginManager/Interfaces/Logger/ILogger.cs
Normal file
17
PluginManager/Interfaces/Logger/ILogger.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using PluginManager.Others;
|
||||||
|
using PluginManager.Others.Logger;
|
||||||
|
|
||||||
|
namespace PluginManager.Interfaces.Logger;
|
||||||
|
|
||||||
|
internal interface ILogger
|
||||||
|
{
|
||||||
|
bool IsEnabled { get; init; }
|
||||||
|
bool OutputToFile { get; init; }
|
||||||
|
|
||||||
|
event EventHandler<Log> OnLog;
|
||||||
|
void Log(
|
||||||
|
string message = "", string outputFile = "", Type? source = default, LogType type = LogType.INFO,
|
||||||
|
DateTime throwTime = default);
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ public class ActionsLoader
|
|||||||
|
|
||||||
private readonly string actionExtension = "dll";
|
private readonly string actionExtension = "dll";
|
||||||
|
|
||||||
private readonly string actionFolder = @"./Data/Actions/";
|
private readonly string actionFolder = @"./Data/Plugins/";
|
||||||
|
|
||||||
public ActionsLoader(string path, string extension)
|
public ActionsLoader(string path, string extension)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -53,10 +53,9 @@ internal class Loader
|
|||||||
{
|
{
|
||||||
Assembly.LoadFrom(file);
|
Assembly.LoadFrom(file);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch
|
||||||
{
|
{
|
||||||
Config.Logger.Log("PluginName: " + new FileInfo(file).Name.Split('.')[0] + " not loaded", this,
|
Config.Logger.Log("PluginName: " + new FileInfo(file).Name.Split('.')[0] + " not loaded", source: typeof(Loader), type: LogType.ERROR);
|
||||||
LogLevel.ERROR);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +129,7 @@ internal class Loader
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Config.Logger.Log(ex.Message, this, LogLevel.ERROR);
|
Config.Logger.Log(ex.Message, source: typeof(Loader), type: LogType.ERROR);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,11 +88,10 @@ public class PluginLoader
|
|||||||
Events = new List<DBEvent>();
|
Events = new List<DBEvent>();
|
||||||
SlashCommands = new List<DBSlashCommand>();
|
SlashCommands = new List<DBSlashCommand>();
|
||||||
|
|
||||||
Config.Logger.Log("Starting plugin loader ... Client: " + _client.CurrentUser.Username, this,
|
Config.Logger.Log("Starting plugin loader ... Client: " + _client.CurrentUser.Username, source: typeof(PluginLoader), type: LogType.INFO);
|
||||||
LogLevel.INFO);
|
|
||||||
|
|
||||||
var loader = new Loader("./Data/Plugins", "dll");
|
var loader = new Loader("./Data/Plugins", "dll");
|
||||||
loader.FileLoaded += args => Config.Logger.Log($"{args.PluginName} file Loaded", this, LogLevel.INFO);
|
loader.FileLoaded += args => Config.Logger.Log($"{args.PluginName} file Loaded", source: typeof(PluginLoader), type: LogType.INFO);
|
||||||
loader.PluginLoaded += Loader_PluginLoaded;
|
loader.PluginLoaded += Loader_PluginLoaded;
|
||||||
var res = loader.Load();
|
var res = loader.Load();
|
||||||
Events = res.Item1;
|
Events = res.Item1;
|
||||||
@@ -117,7 +116,7 @@ public class PluginLoader
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Config.Logger.Log(ex.Message, this, LogLevel.ERROR);
|
Config.Logger.Log(ex.Message, source: typeof(PluginLoader), type: LogType.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -151,13 +150,13 @@ public class PluginLoader
|
|||||||
var instance = (DBEvent)Activator.CreateInstance(type);
|
var instance = (DBEvent)Activator.CreateInstance(type);
|
||||||
instance.Start(client);
|
instance.Start(client);
|
||||||
Events.Add(instance);
|
Events.Add(instance);
|
||||||
Config.Logger.Log($"[EVENT] Loaded external {type.FullName}!", LogLevel.INFO);
|
Config.Logger.Log($"[EVENT] Loaded external {type.FullName}!", source: typeof(PluginLoader));
|
||||||
}
|
}
|
||||||
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
|
else if (type.IsClass && typeof(DBCommand).IsAssignableFrom(type))
|
||||||
{
|
{
|
||||||
var instance = (DBCommand)Activator.CreateInstance(type);
|
var instance = (DBCommand)Activator.CreateInstance(type);
|
||||||
Commands.Add(instance);
|
Commands.Add(instance);
|
||||||
Config.Logger.Log($"[CMD] Instance: {type.FullName} loaded !", LogLevel.INFO);
|
Config.Logger.Log($"[CMD] Instance: {type.FullName} loaded !", source: typeof(PluginLoader));
|
||||||
}
|
}
|
||||||
else if (type.IsClass && typeof(DBSlashCommand).IsAssignableFrom(type))
|
else if (type.IsClass && typeof(DBSlashCommand).IsAssignableFrom(type))
|
||||||
{
|
{
|
||||||
@@ -170,13 +169,13 @@ public class PluginLoader
|
|||||||
|
|
||||||
await client.CreateGlobalApplicationCommandAsync(builder.Build());
|
await client.CreateGlobalApplicationCommandAsync(builder.Build());
|
||||||
SlashCommands.Add(instance);
|
SlashCommands.Add(instance);
|
||||||
Config.Logger.Log($"[SLASH] Instance: {type.FullName} loaded !", LogLevel.INFO);
|
Config.Logger.Log($"[SLASH] Instance: {type.FullName} loaded !", source: typeof(PluginLoader));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
//Console.WriteLine(ex.Message);
|
//Console.WriteLine(ex.Message);
|
||||||
Config.Logger.Error(ex);
|
Config.Logger.Log(ex.Message, source: typeof(PluginLoader), type: LogType.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,21 +35,25 @@ internal static class OnlineFunctions
|
|||||||
if (progress == null || !contentLength.HasValue)
|
if (progress == null || !contentLength.HasValue)
|
||||||
{
|
{
|
||||||
await download.CopyToAsync(destination, cancellation);
|
await download.CopyToAsync(destination, cancellation);
|
||||||
|
if(!contentLength.HasValue)
|
||||||
|
progress?.Report(100f);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert absolute progress (bytes downloaded) into relative progress (0% - 100%)
|
// Convert absolute progress (bytes downloaded) into relative progress (0% - 100%)
|
||||||
var relativeProgress = new Progress<long>(totalBytes =>
|
// total ... 100%
|
||||||
{
|
// downloaded ... x%
|
||||||
progress?.Report((float)totalBytes / contentLength.Value *
|
// x = downloaded * 100 / total => x = downloaded / total * 100
|
||||||
100);
|
var relativeProgress = new Progress<long>(totalBytesDownloaded =>
|
||||||
downloadedBytes?.Report(totalBytes);
|
{
|
||||||
}
|
progress?.Report(totalBytesDownloaded / (float)contentLength.Value * 100);
|
||||||
);
|
downloadedBytes?.Report(totalBytesDownloaded);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Use extension method to report progress while downloading
|
// Use extension method to report progress while downloading
|
||||||
await download.CopyToOtherStreamAsync(destination, bufferSize, relativeProgress, cancellation);
|
await download.CopyToOtherStreamAsync(destination, bufferSize, relativeProgress, cancellation);
|
||||||
progress.Report(100);
|
progress.Report(100f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,15 @@ public class PluginsManager
|
|||||||
PluginsLink = plink;
|
PluginsLink = plink;
|
||||||
VersionsLink = vlink;
|
VersionsLink = vlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The default Plugin Manager constructor. It uses the default links.
|
||||||
|
/// </summary>
|
||||||
|
public PluginsManager()
|
||||||
|
{
|
||||||
|
PluginsLink = "https://raw.githubusercontent.com/andreitdr/SethPlugins/releases/PluginsList";
|
||||||
|
VersionsLink = "https://raw.githubusercontent.com/andreitdr/SethPlugins/releases/Versions";
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The URL of the server
|
/// The URL of the server
|
||||||
@@ -33,7 +42,7 @@ public class PluginsManager
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<List<string[]>> GetAvailablePlugins()
|
public async Task<List<string[]>> GetAvailablePlugins()
|
||||||
{
|
{
|
||||||
Config.Logger.Log("Got data from " + VersionsLink, this, LogLevel.INFO);
|
// Config.Logger.Log("Got data from " + VersionsLink, this, LogLevel.INFO);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var list = await ServerCom.ReadTextFromURL(PluginsLink);
|
var list = await ServerCom.ReadTextFromURL(PluginsLink);
|
||||||
@@ -76,15 +85,11 @@ public class PluginsManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data.Add(new[] { "-", "-", "-", "-" });
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
Config.Logger.Log("Failed to execute command: listplugs\nReason: " + exception.Message, this,
|
Config.Logger.Log(message: "Failed to execute command: listplugs\nReason: " + exception.Message, source: typeof(PluginsManager), type: LogType.ERROR );
|
||||||
LogLevel.ERROR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -101,7 +106,7 @@ public class PluginsManager
|
|||||||
var split = item.Split(',');
|
var split = item.Split(',');
|
||||||
if (split[0] == pakName)
|
if (split[0] == pakName)
|
||||||
{
|
{
|
||||||
Config.Logger.Log("Searched for " + pakName + " and found " + split[1] + " as version.", LogLevel.INFO);
|
// Config.Logger.Log("Searched for " + pakName + " and found " + split[1] + " as version.", LogLevel.INFO);
|
||||||
return new VersionString(split[1]);
|
return new VersionString(split[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,8 +141,7 @@ public class PluginsManager
|
|||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
Config.Logger.Log("Failed to execute command: listplugs\nReason: " + exception.Message, this,
|
Config.Logger.Log("Failed to execute command: plugin list\nReason: " + exception.Message, source: typeof(PluginsManager), type: LogType.ERROR);
|
||||||
LogLevel.ERROR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -48,4 +48,5 @@ public static class ServerCom
|
|||||||
{
|
{
|
||||||
await DownloadFileAsync(URl, location, progress, null);
|
await DownloadFileAsync(URl, location, progress, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,29 +18,37 @@ public class InternalActionManager
|
|||||||
|
|
||||||
public async Task Initialize()
|
public async Task Initialize()
|
||||||
{
|
{
|
||||||
loader.ActionLoadedEvent += OnActionLoaded;
|
//loader.ActionLoadedEvent += OnActionLoaded;
|
||||||
var m_actions = await loader.Load();
|
var m_actions = await loader.Load();
|
||||||
if (m_actions == null) return;
|
if (m_actions == null) return;
|
||||||
foreach (var action in m_actions)
|
foreach (var action in m_actions)
|
||||||
Actions.Add(action.ActionName, action);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnActionLoaded(string name, string typeName, bool success, Exception? e)
|
|
||||||
{
|
|
||||||
if (!success)
|
|
||||||
{
|
{
|
||||||
Config.Logger.Error(e);
|
Actions.TryAdd(action.ActionName, action);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Config.Logger.Log($"Action {name} loaded successfully", LogLevel.INFO, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task Refresh()
|
||||||
|
{
|
||||||
|
Actions.Clear();
|
||||||
|
await Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// private void OnActionLoaded(string name, string typeName, bool success, Exception? e)
|
||||||
|
// {
|
||||||
|
// if (!success)
|
||||||
|
// {
|
||||||
|
// Config.Logger.Error(e);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Config.Logger.Log($"Action {name} loaded successfully", LogLevel.INFO, true);
|
||||||
|
// }
|
||||||
|
|
||||||
public async Task<string> Execute(string actionName, params string[]? args)
|
public async Task<string> Execute(string actionName, params string[]? args)
|
||||||
{
|
{
|
||||||
if (!Actions.ContainsKey(actionName))
|
if (!Actions.ContainsKey(actionName))
|
||||||
{
|
{
|
||||||
Config.Logger.Log($"Action {actionName} not found", "InternalActionManager", LogLevel.WARNING, true);
|
Config.Logger.Log($"Action {actionName} not found", type: LogType.ERROR, source: typeof(InternalActionManager));
|
||||||
return "Action not found";
|
return "Action not found";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +59,7 @@ public class InternalActionManager
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Config.Logger.Log(e.Message, "InternalActionManager", LogLevel.ERROR);
|
Config.Logger.Log(e.Message , type: LogType.ERROR, source: typeof(InternalActionManager));
|
||||||
return e.Message;
|
return e.Message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization.Formatters.Binary;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace PluginManager.Others;
|
namespace PluginManager.Others;
|
||||||
@@ -94,7 +93,7 @@ public static class ArchiveManager
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Config.Logger.Log(ex.Message, "Archive Manager", LogLevel.ERROR); // Write the error to a file
|
Config.Logger.Log(message: ex.Message, source: typeof(ArchiveManager), type: LogType.ERROR); // Write the error to a file
|
||||||
await Task.Delay(100);
|
await Task.Delay(100);
|
||||||
return await ReadFromPakAsync(FileName, archFile);
|
return await ReadFromPakAsync(FileName, archFile);
|
||||||
}
|
}
|
||||||
@@ -132,8 +131,7 @@ public static class ArchiveManager
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Config.Logger.Log($"Failed to extract {entry.Name}. Exception: {ex.Message}",
|
Config.Logger.Log(ex.Message, source: typeof(ArchiveManager), type: LogType.ERROR);
|
||||||
"Archive Manager", LogLevel.ERROR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
currentZIPFile++;
|
currentZIPFile++;
|
||||||
@@ -165,8 +163,7 @@ public static class ArchiveManager
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Config.Logger.Log($"Failed to extract {entry.Name}. Exception: {ex.Message}",
|
Config.Logger.Log(ex.Message, source: typeof(ArchiveManager), type: LogType.ERROR);
|
||||||
"Archive Manager", LogLevel.ERROR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(10);
|
await Task.Delay(10);
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
using Discord.Commands;
|
using System.Linq;
|
||||||
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using PluginManager.Bot;
|
||||||
|
|
||||||
namespace PluginManager.Others;
|
namespace PluginManager.Others;
|
||||||
|
|
||||||
@@ -13,6 +16,30 @@ public class DBCommandExecutingArguments
|
|||||||
this.arguments = arguments;
|
this.arguments = arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DBCommandExecutingArguments(SocketUserMessage? message, DiscordSocketClient client)
|
||||||
|
{
|
||||||
|
this.context = new SocketCommandContext(client, message);
|
||||||
|
int pos = 0;
|
||||||
|
if (message.HasMentionPrefix(client.CurrentUser, ref pos))
|
||||||
|
{
|
||||||
|
var mentionPrefix = "<@" + client.CurrentUser.Id + ">";
|
||||||
|
this.cleanContent = message.Content.Substring(mentionPrefix.Length + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.cleanContent = message.Content.Substring(Config.DiscordBot.botPrefix.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
var split = this.cleanContent.Split(' ');
|
||||||
|
|
||||||
|
string[]? argsClean = null;
|
||||||
|
if (split.Length > 1)
|
||||||
|
argsClean = string.Join(' ', split, 1, split.Length - 1).Split(' ');
|
||||||
|
|
||||||
|
this.commandUsed = split[0];
|
||||||
|
this.arguments = argsClean;
|
||||||
|
}
|
||||||
|
|
||||||
public SocketCommandContext context { get; init; }
|
public SocketCommandContext context { get; init; }
|
||||||
public string cleanContent { get; init; }
|
public string cleanContent { get; init; }
|
||||||
public string commandUsed { get; init; }
|
public string commandUsed { get; init; }
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public enum OperatingSystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The output log type
|
/// The output log type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum LogLevel
|
public enum LogType
|
||||||
{
|
{
|
||||||
INFO,
|
INFO,
|
||||||
WARNING,
|
WARNING,
|
||||||
@@ -30,8 +30,8 @@ public enum UnzipProgressType
|
|||||||
|
|
||||||
public enum SaveType
|
public enum SaveType
|
||||||
{
|
{
|
||||||
NORMAL,
|
TXT,
|
||||||
BACKUP
|
JSON
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum InternalActionRunType
|
public enum InternalActionRunType
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using PluginManager.Interfaces.Exceptions;
|
|
||||||
|
|
||||||
namespace PluginManager.Others.Exceptions;
|
|
||||||
|
|
||||||
public class ConfigFailedToLoad : IException
|
|
||||||
{
|
|
||||||
public List<string>? Messages { get; set; }
|
|
||||||
public bool isFatal { get; private set; }
|
|
||||||
public string? File { get; }
|
|
||||||
|
|
||||||
|
|
||||||
public ConfigFailedToLoad(string message, bool isFatal, string file)
|
|
||||||
{
|
|
||||||
this.isFatal = isFatal;
|
|
||||||
Messages = new List<string>() {message};
|
|
||||||
this.File = file;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigFailedToLoad(string message, bool isFatal)
|
|
||||||
{
|
|
||||||
this.isFatal = isFatal;
|
|
||||||
Messages = new List<string>() {message};
|
|
||||||
this.File = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigFailedToLoad(string message)
|
|
||||||
{
|
|
||||||
this.isFatal = false;
|
|
||||||
Messages = new List<string>() {message};
|
|
||||||
this.File = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GenerateFullMessage()
|
|
||||||
{
|
|
||||||
string messages = "";
|
|
||||||
foreach (var message in Messages)
|
|
||||||
{
|
|
||||||
messages += message + "\n";
|
|
||||||
}
|
|
||||||
return $"\nMessage: {messages}\nIsFatal: {isFatal}\nFile: {File ?? "null"}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleException()
|
|
||||||
{
|
|
||||||
if (isFatal)
|
|
||||||
{
|
|
||||||
Config.Logger.Log(GenerateFullMessage(), LogLevel.CRITICAL, true);
|
|
||||||
Environment.Exit((int)ExceptionExitCode.CONFIG_FAILED_TO_LOAD);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Config.Logger.Log(GenerateFullMessage(), LogLevel.WARNING);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IException AppendError(string message)
|
|
||||||
{
|
|
||||||
Messages.Add(message);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IException AppendError(List<string> messages)
|
|
||||||
{
|
|
||||||
Messages.AddRange(messages);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IException IsFatal(bool isFatal = true)
|
|
||||||
{
|
|
||||||
this.isFatal = isFatal;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static ConfigFailedToLoad CreateError(string message, bool isFatal, string? file = null)
|
|
||||||
{
|
|
||||||
if (file is not null)
|
|
||||||
return new ConfigFailedToLoad(message, isFatal, file);
|
|
||||||
return new ConfigFailedToLoad(message, isFatal);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ConfigFailedToLoad CreateError(string message)
|
|
||||||
{
|
|
||||||
return new ConfigFailedToLoad(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using PluginManager.Interfaces.Exceptions;
|
|
||||||
|
|
||||||
namespace PluginManager.Others.Exceptions;
|
|
||||||
|
|
||||||
public class ConfigNoKeyWasPresent: IException
|
|
||||||
{
|
|
||||||
public List<string> Messages { get; set; }
|
|
||||||
public bool isFatal { get; private set; }
|
|
||||||
|
|
||||||
public ConfigNoKeyWasPresent(string message, bool isFatal)
|
|
||||||
{
|
|
||||||
this.Messages = new List<string>() { message };
|
|
||||||
this.isFatal = isFatal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigNoKeyWasPresent(string message)
|
|
||||||
{
|
|
||||||
this.Messages = new List<string>() { message };
|
|
||||||
this.isFatal = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GenerateFullMessage()
|
|
||||||
{
|
|
||||||
string messages = "";
|
|
||||||
foreach (var message in Messages)
|
|
||||||
{
|
|
||||||
messages += message + "\n";
|
|
||||||
}
|
|
||||||
return $"\nMessage: {messages}\nIsFatal: {isFatal}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void HandleException()
|
|
||||||
{
|
|
||||||
if (isFatal)
|
|
||||||
{
|
|
||||||
|
|
||||||
Config.Logger.Log(GenerateFullMessage(), LogLevel.CRITICAL, true);
|
|
||||||
Environment.Exit((int)ExceptionExitCode.CONFIG_KEY_NOT_FOUND);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Config.Logger.Log(GenerateFullMessage(), LogLevel.WARNING);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IException AppendError(string message)
|
|
||||||
{
|
|
||||||
Messages.Add(message);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IException AppendError(List<string> messages)
|
|
||||||
{
|
|
||||||
Messages.AddRange(messages);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IException IsFatal(bool isFatal = true)
|
|
||||||
{
|
|
||||||
this.isFatal = isFatal;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ConfigNoKeyWasPresent CreateError(string message)
|
|
||||||
{
|
|
||||||
return new ConfigNoKeyWasPresent(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ConfigNoKeyWasPresent CreateError(string message, bool isFatal)
|
|
||||||
{
|
|
||||||
return new ConfigNoKeyWasPresent(message, isFatal);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace PluginManager.Others.Logger;
|
|
||||||
|
|
||||||
public class DBLogger
|
|
||||||
{
|
|
||||||
public delegate void LogHandler(string message, LogLevel logType, bool isInternal = false);
|
|
||||||
|
|
||||||
private readonly string _errFolder;
|
|
||||||
|
|
||||||
private readonly string _logFolder;
|
|
||||||
private readonly List<LogMessage> ErrorHistory = new();
|
|
||||||
private readonly List<LogMessage> LogHistory = new();
|
|
||||||
|
|
||||||
public DBLogger()
|
|
||||||
{
|
|
||||||
_logFolder = Config.AppSettings["LogFolder"];
|
|
||||||
_errFolder = Config.AppSettings["ErrorFolder"];
|
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyList<LogMessage> Logs => LogHistory;
|
|
||||||
public IReadOnlyList<LogMessage> Errors => ErrorHistory;
|
|
||||||
|
|
||||||
public event LogHandler? LogEvent;
|
|
||||||
|
|
||||||
public void Log(string message, LogLevel type = LogLevel.INFO)
|
|
||||||
{
|
|
||||||
Log(new LogMessage(message, type));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Log(string message, LogLevel type= LogLevel.INFO, bool isInternal = false)
|
|
||||||
{
|
|
||||||
Log(new LogMessage(message, type,"unknown", isInternal));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Log(string message, string sender = "unknown", LogLevel type = LogLevel.INFO, bool isInternal = false)
|
|
||||||
{
|
|
||||||
Log(new LogMessage(message, type,sender,isInternal));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Log(string message, string sender = "unknown", LogLevel type = LogLevel.INFO)
|
|
||||||
{
|
|
||||||
Log(new LogMessage(message, type, sender));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Error(Exception? e)
|
|
||||||
{
|
|
||||||
Log(e.Message, e.Source, LogLevel.ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Log(LogMessage message)
|
|
||||||
{
|
|
||||||
LogEvent?.Invoke(message.Message, message.Type);
|
|
||||||
|
|
||||||
if (message.Type != LogLevel.ERROR && message.Type != LogLevel.CRITICAL)
|
|
||||||
LogHistory.Add(message);
|
|
||||||
else
|
|
||||||
ErrorHistory.Add(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Log(string message, object sender, LogLevel type = LogLevel.INFO)
|
|
||||||
{
|
|
||||||
Log(message, sender.GetType().Name, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SaveToFile(bool ErrorsOnly = true)
|
|
||||||
{
|
|
||||||
if(!ErrorsOnly)
|
|
||||||
await JsonManager.SaveToJsonFile(_logFolder + "/" + DateTime.Now.ToString("yyyy-MM-dd") + ".json",
|
|
||||||
LogHistory);
|
|
||||||
await JsonManager.SaveToJsonFile(_errFolder + "/" + DateTime.Now.ToString("yyyy-MM-dd") + ".json",
|
|
||||||
ErrorHistory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
78
PluginManager/Others/Logger/Log.cs
Normal file
78
PluginManager/Others/Logger/Log.cs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using PluginManager.Interfaces.Logger;
|
||||||
|
|
||||||
|
namespace PluginManager.Others.Logger;
|
||||||
|
|
||||||
|
public class Log : ILog
|
||||||
|
{
|
||||||
|
public string Message { get; set; }
|
||||||
|
public string OutputFile { get; set; }
|
||||||
|
public Type? Source { get; set; }
|
||||||
|
public LogType Type { get; set; }
|
||||||
|
public DateTime ThrowTime { get; set; }
|
||||||
|
|
||||||
|
public Log(string message, string outputFile, Type? source, LogType type, DateTime throwTime)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
OutputFile = outputFile;
|
||||||
|
Source = source;
|
||||||
|
Type = type;
|
||||||
|
ThrowTime = throwTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log(string message, string outputFile, Type? source, LogType type)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
OutputFile = outputFile;
|
||||||
|
Source = source;
|
||||||
|
Type = type;
|
||||||
|
ThrowTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log(string message, string outputFile, Type? source)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
OutputFile = outputFile;
|
||||||
|
Source = source;
|
||||||
|
Type = LogType.INFO;
|
||||||
|
ThrowTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log(string message, string outputFile)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
OutputFile = outputFile;
|
||||||
|
Source = typeof(Log);
|
||||||
|
Type = LogType.INFO;
|
||||||
|
ThrowTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Log(string message)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
OutputFile = "";
|
||||||
|
Source = typeof(Log);
|
||||||
|
Type = LogType.INFO;
|
||||||
|
ThrowTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator Log(string message) => new (message);
|
||||||
|
|
||||||
|
public static implicit operator string(Log log) => $"[{log.ThrowTime}] {log.Message}";
|
||||||
|
|
||||||
|
public string AsLongString()
|
||||||
|
{
|
||||||
|
return $"[{ThrowTime}] [{Source}] [{Type}] {Message}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string AsShortString()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FormatedLongString()
|
||||||
|
{
|
||||||
|
return $"[{ThrowTime}]\t[{Source}]\t\t\t[{Type}]\t{Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace PluginManager.Others.Logger;
|
|
||||||
|
|
||||||
public class LogMessage
|
|
||||||
{
|
|
||||||
public LogMessage(string message, LogLevel type)
|
|
||||||
{
|
|
||||||
Message = message;
|
|
||||||
Type = type;
|
|
||||||
Time = DateTime.Now.ToString("HH:mm:ss");
|
|
||||||
isInternal = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LogMessage(string message, LogLevel type, string sender, bool isInternal) : this(message, type)
|
|
||||||
{
|
|
||||||
Sender = sender;
|
|
||||||
this.isInternal = isInternal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LogMessage(string message, LogLevel type, string sender) : this (message, type, sender, false)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Message { get; set; }
|
|
||||||
public LogLevel Type { get; set; }
|
|
||||||
public string Time { get; set; }
|
|
||||||
public string Sender { get; set; }
|
|
||||||
public bool isInternal { get; set; }
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"[{Time}] {Message}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static explicit operator LogMessage(string message)
|
|
||||||
{
|
|
||||||
return new LogMessage(message, LogLevel.INFO);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static explicit operator LogMessage((string message, LogLevel type) tuple)
|
|
||||||
{
|
|
||||||
return new LogMessage(tuple.message, tuple.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static explicit operator LogMessage((string message, LogLevel type, string sender) tuple)
|
|
||||||
{
|
|
||||||
return new LogMessage(tuple.message, tuple.type, tuple.sender);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
69
PluginManager/Others/Logger/Logger.cs
Normal file
69
PluginManager/Others/Logger/Logger.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using PluginManager.Interfaces.Logger;
|
||||||
|
|
||||||
|
namespace PluginManager.Others.Logger;
|
||||||
|
|
||||||
|
public sealed class Logger : ILogger
|
||||||
|
{
|
||||||
|
public bool IsEnabled { get; init; }
|
||||||
|
public bool OutputToFile { get; init; }
|
||||||
|
|
||||||
|
public LogType LowestLogLevel { get; set; }
|
||||||
|
private bool UseShortVersion { get; }
|
||||||
|
|
||||||
|
public Logger(bool useShortVersion, bool outputToFile, LogType lowestLogLevel = LogType.INFO)
|
||||||
|
{
|
||||||
|
UseShortVersion = useShortVersion;
|
||||||
|
OutputToFile = outputToFile;
|
||||||
|
IsEnabled = true;
|
||||||
|
LowestLogLevel = lowestLogLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<Log>? OnLog;
|
||||||
|
|
||||||
|
private async Task Log(Log logMessage)
|
||||||
|
{
|
||||||
|
if (!IsEnabled) return;
|
||||||
|
|
||||||
|
OnLog?.Invoke(this, logMessage);
|
||||||
|
|
||||||
|
if (logMessage.Type < LowestLogLevel) return;
|
||||||
|
|
||||||
|
if (OutputToFile)
|
||||||
|
await File.AppendAllTextAsync(
|
||||||
|
logMessage.OutputFile,
|
||||||
|
(UseShortVersion ? logMessage : logMessage.AsLongString()) + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void Log(string message = "", string outputFile = "", Type? source = default, LogType type = LogType.INFO, DateTime throwTime = default)
|
||||||
|
{
|
||||||
|
if (!IsEnabled) return;
|
||||||
|
|
||||||
|
if (type < LowestLogLevel) return;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(message)) return;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(outputFile)) outputFile = Config.AppSettings["LogFolder"] + "/" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";
|
||||||
|
|
||||||
|
if(throwTime == default) throwTime = DateTime.Now;
|
||||||
|
|
||||||
|
if (source == default) source = typeof(Log);
|
||||||
|
|
||||||
|
await Log(new Log(message, outputFile, source, type, throwTime));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void Log(Exception exception, LogType logType = LogType.ERROR, Type? source = null)
|
||||||
|
{
|
||||||
|
if (!IsEnabled) return;
|
||||||
|
|
||||||
|
if (logType < LowestLogLevel) return;
|
||||||
|
|
||||||
|
await Log(new Log(exception.Message,
|
||||||
|
Config.AppSettings["LogFolder"] + "/" + DateTime.Now.ToString("yyyy-MM-dd") + ".log",
|
||||||
|
source, logType, DateTime.Now));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using PluginManager.Others.Exceptions;
|
|
||||||
|
|
||||||
namespace PluginManager.Others;
|
namespace PluginManager.Others;
|
||||||
|
|
||||||
@@ -16,10 +15,8 @@ public class SettingsDictionary<TKey, TValue> : IDictionary<TKey, TValue>
|
|||||||
_file = file;
|
_file = file;
|
||||||
if (!LoadFromFile())
|
if (!LoadFromFile())
|
||||||
{
|
{
|
||||||
ConfigFailedToLoad.CreateError("Failed to load config")
|
_dictionary = new Dictionary<TKey, TValue>();
|
||||||
.AppendError("The file is empty or does not exist")
|
SaveToFile();
|
||||||
.IsFatal()
|
|
||||||
.HandleException();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,10 +47,6 @@ public class SettingsDictionary<TKey, TValue> : IDictionary<TKey, TValue>
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
ConfigFailedToLoad
|
|
||||||
.CreateError("Failed to load config")
|
|
||||||
.IsFatal()
|
|
||||||
.HandleException();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,11 +119,6 @@ public class SettingsDictionary<TKey, TValue> : IDictionary<TKey, TValue>
|
|||||||
if(this._dictionary[key] is string s && !string.IsNullOrEmpty(s) && !string.IsNullOrWhiteSpace(s))
|
if(this._dictionary[key] is string s && !string.IsNullOrEmpty(s) && !string.IsNullOrWhiteSpace(s))
|
||||||
return this._dictionary[key];
|
return this._dictionary[key];
|
||||||
|
|
||||||
ConfigNoKeyWasPresent.CreateError($"Key {(key is string ? key : typeof(TKey).Name)} was not present in {_file ?? "config"}")
|
|
||||||
.AppendError("Deleting the file may fix this issue")
|
|
||||||
.IsFatal()
|
|
||||||
.HandleException();
|
|
||||||
|
|
||||||
return default!;
|
return default!;
|
||||||
}
|
}
|
||||||
set => this._dictionary![key] = value;
|
set => this._dictionary![key] = value;
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -6,13 +6,9 @@ This project is based on:
|
|||||||
- [.NET 6 (C#)](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)
|
- [.NET 6 (C#)](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)
|
||||||
- [Discord.Net](https://github.com/discord-net/Discord.Net)
|
- [Discord.Net](https://github.com/discord-net/Discord.Net)
|
||||||
|
|
||||||
- Some plugins can be found [here](https://github.com/andreitdr/SethPlugins).
|
|
||||||
|
|
||||||
|
|
||||||
## Plugins
|
## Plugins
|
||||||
#### Requirements:
|
- Some plugins can be found in [this repo](https://github.com/andreitdr/SethPlugins).
|
||||||
- [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&channel=Release&version=VS2022&source=VSLandingPage&cid=2030&passive=false)
|
|
||||||
- .NET 6 (downloaded with Visual Studio)
|
|
||||||
|
|
||||||
Plugin Types:
|
Plugin Types:
|
||||||
1. Commands
|
1. Commands
|
||||||
@@ -21,6 +17,10 @@ Plugin Types:
|
|||||||
|
|
||||||
### How to create a plugin
|
### How to create a plugin
|
||||||
|
|
||||||
|
#### Requirements:
|
||||||
|
- [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community&channel=Release&version=VS2022&source=VSLandingPage&cid=2030&passive=false)
|
||||||
|
- .NET 6 (downloaded with Visual Studio)
|
||||||
|
|
||||||
First of all, create a new project (class library) in Visual Studio.
|
First of all, create a new project (class library) in Visual Studio.
|
||||||
Then import the PluginManager as reference to your project.
|
Then import the PluginManager as reference to your project.
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ public class LevelCommand : DBCommand
|
|||||||
|
|
||||||
From here on, start coding. When your plugin is done, build it as any DLL project then add it to the following path
|
From here on, start coding. When your plugin is done, build it as any DLL project then add it to the following path
|
||||||
`{bot_executable}/Data/Plugins/<optional subfolder>/[plugin name].dll`
|
`{bot_executable}/Data/Plugins/<optional subfolder>/[plugin name].dll`
|
||||||
Then, reload bot and execute command `lp` in bot's console. The plugin should be loaded into memory or an error is thrown if not. If an error is thrown, then
|
Then, reload bot and execute command `plugin load` in the console. The plugin should be loaded into memory or an error is thrown if not. If an error is thrown, then
|
||||||
there is something wrong in your command's code.
|
there is something wrong in your command's code.
|
||||||
|
|
||||||
## 2. Events
|
## 2. Events
|
||||||
@@ -192,4 +192,4 @@ namespace SlashCommands
|
|||||||
You can create multiple commands, events and slash commands into one single plugin (class library). The PluginManager will detect the classes and load them individualy. If there are more commands (normal commands, events or slash commands) into a single project (class library) they can use the same resources (a class for example) that is contained within the plugin.
|
You can create multiple commands, events and slash commands into one single plugin (class library). The PluginManager will detect the classes and load them individualy. If there are more commands (normal commands, events or slash commands) into a single project (class library) they can use the same resources (a class for example) that is contained within the plugin.
|
||||||
|
|
||||||
|
|
||||||
> Updated: 5.08.2023
|
> Updated: 25.09.2023
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MusicPlayer", "..\SethPlugi
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LevelingSystem", "..\SethPlugins\LevelingSystem\LevelingSystem.csproj", "{BFE3491C-AC01-4252-B242-6451270FC548}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LevelingSystem", "..\SethPlugins\LevelingSystem\LevelingSystem.csproj", "{BFE3491C-AC01-4252-B242-6451270FC548}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PythonCompatibilityLayer", "..\SethPlugins\PythonCompatibilityLayer\PythonCompatibilityLayer.csproj", "{81ED4953-13E5-4950-96A8-8CEF5FD59559}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -35,6 +37,10 @@ Global
|
|||||||
{BFE3491C-AC01-4252-B242-6451270FC548}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{BFE3491C-AC01-4252-B242-6451270FC548}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{BFE3491C-AC01-4252-B242-6451270FC548}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{BFE3491C-AC01-4252-B242-6451270FC548}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{BFE3491C-AC01-4252-B242-6451270FC548}.Release|Any CPU.Build.0 = Release|Any CPU
|
{BFE3491C-AC01-4252-B242-6451270FC548}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{81ED4953-13E5-4950-96A8-8CEF5FD59559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{81ED4953-13E5-4950-96A8-8CEF5FD59559}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{81ED4953-13E5-4950-96A8-8CEF5FD59559}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{81ED4953-13E5-4950-96A8-8CEF5FD59559}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -42,6 +48,7 @@ Global
|
|||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{1690CBBC-BDC0-4DD8-B701-F8817189D9D5} = {78B6D390-F61A-453F-B38D-E4C054321615}
|
{1690CBBC-BDC0-4DD8-B701-F8817189D9D5} = {78B6D390-F61A-453F-B38D-E4C054321615}
|
||||||
{BFE3491C-AC01-4252-B242-6451270FC548} = {78B6D390-F61A-453F-B38D-E4C054321615}
|
{BFE3491C-AC01-4252-B242-6451270FC548} = {78B6D390-F61A-453F-B38D-E4C054321615}
|
||||||
|
{81ED4953-13E5-4950-96A8-8CEF5FD59559} = {78B6D390-F61A-453F-B38D-E4C054321615}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF}
|
SolutionGuid = {3FB3C5DE-ED21-4D2E-ABDD-3A00EE4A2FFF}
|
||||||
|
|||||||
Reference in New Issue
Block a user