Reworked the Config system
This commit is contained in:
@@ -131,7 +131,9 @@ internal static class PluginMethods
|
|||||||
|
|
||||||
IProgress<float> progress = new Progress<float>(p => { downloadTask.Value = p; });
|
IProgress<float> progress = new Progress<float>(p => { downloadTask.Value = p; });
|
||||||
|
|
||||||
await ServerCom.DownloadFileAsync(pluginLink, $"{Application.CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"]}/{pluginData.Name}.dll", progress);
|
string baseFolder = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("PluginFolder");
|
||||||
|
|
||||||
|
await ServerCom.DownloadFileAsync(pluginLink, $"{baseFolder}/{pluginData.Name}.dll", progress);
|
||||||
|
|
||||||
downloadTask.Increment(100);
|
downloadTask.Increment(100);
|
||||||
|
|
||||||
@@ -177,12 +179,9 @@ internal static class PluginMethods
|
|||||||
task.IsIndeterminate = true;
|
task.IsIndeterminate = true;
|
||||||
downloadTasks.Add(new Tuple<ProgressTask, IProgress<float>, string, string>(task, progress, dependency.DownloadLink, dependency.DownloadLocation));
|
downloadTasks.Add(new Tuple<ProgressTask, IProgress<float>, string, string>(task, progress, dependency.DownloadLink, dependency.DownloadLocation));
|
||||||
}
|
}
|
||||||
|
|
||||||
int maxParallelDownloads = 5;
|
int maxParallelDownloads = Application.CurrentApplication.ApplicationEnvironmentVariables.Get("MaxParallelDownloads", 5);
|
||||||
|
|
||||||
if (Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("MaxParallelDownloads"))
|
|
||||||
maxParallelDownloads = int.Parse(Application.CurrentApplication.ApplicationEnvironmentVariables["MaxParallelDownloads"]);
|
|
||||||
|
|
||||||
var options = new ParallelOptions()
|
var options = new ParallelOptions()
|
||||||
{
|
{
|
||||||
MaxDegreeOfParallelism = maxParallelDownloads,
|
MaxDegreeOfParallelism = maxParallelDownloads,
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ internal static class SettingsConfigExtra
|
|||||||
if (!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey(key))
|
if (!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey(key))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Application.CurrentApplication.ApplicationEnvironmentVariables[key] = string.Join(' ', value);
|
Application.CurrentApplication.ApplicationEnvironmentVariables.Add(key, string.Join(' ', value));
|
||||||
// Config.Application.CurrentApplication.ApplicationEnvironmentVariables.SaveToFile().Wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void RemoveSettings(string key)
|
internal static void RemoveSettings(string key)
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ namespace DiscordBot.Bot.Actions
|
|||||||
|
|
||||||
public string Description => "Access module commands";
|
public string Description => "Access module commands";
|
||||||
|
|
||||||
public string Usage => "module <name>";
|
public string Usage => "module <command>";
|
||||||
|
|
||||||
public IEnumerable<InternalActionOption> ListOfOptions => [];
|
public IEnumerable<InternalActionOption> ListOfOptions => [
|
||||||
|
new InternalActionOption("list", "List all loaded modules")
|
||||||
|
];
|
||||||
|
|
||||||
public InternalActionRunType RunType => InternalActionRunType.OnCall;
|
public InternalActionRunType RunType => InternalActionRunType.OnCall;
|
||||||
|
|
||||||
@@ -24,7 +26,7 @@ namespace DiscordBot.Bot.Actions
|
|||||||
|
|
||||||
public Task Execute(string[] args)
|
public Task Execute(string[] args)
|
||||||
{
|
{
|
||||||
string command = args[0];
|
string command = args?[0];
|
||||||
switch(command)
|
switch(command)
|
||||||
{
|
{
|
||||||
case "list":
|
case "list":
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using DiscordBot.Bot.Actions.Extra;
|
using DiscordBot.Bot.Actions.Extra;
|
||||||
using DiscordBotCore;
|
using DiscordBotCore;
|
||||||
@@ -14,6 +15,7 @@ public class SettingsConfig: ICommandAction
|
|||||||
public string ActionName => "config";
|
public string ActionName => "config";
|
||||||
public string Description => "Change the settings of the bot";
|
public string Description => "Change the settings of the bot";
|
||||||
public string Usage => "config <options!>";
|
public string Usage => "config <options!>";
|
||||||
|
|
||||||
public IEnumerable<InternalActionOption> ListOfOptions => new List<InternalActionOption>
|
public IEnumerable<InternalActionOption> ListOfOptions => new List<InternalActionOption>
|
||||||
{
|
{
|
||||||
new InternalActionOption("help", "Displays this message"),
|
new InternalActionOption("help", "Displays this message"),
|
||||||
@@ -21,16 +23,16 @@ public class SettingsConfig: ICommandAction
|
|||||||
new InternalActionOption("remove", "Remove a setting"),
|
new InternalActionOption("remove", "Remove a setting"),
|
||||||
new InternalActionOption("add", "Add a setting")
|
new InternalActionOption("add", "Add a setting")
|
||||||
};
|
};
|
||||||
|
|
||||||
public InternalActionRunType RunType => InternalActionRunType.OnCall;
|
public InternalActionRunType RunType => InternalActionRunType.OnCall;
|
||||||
|
|
||||||
public bool RequireOtherThread => false;
|
public bool RequireOtherThread => false;
|
||||||
|
|
||||||
public Task Execute(string[] args)
|
public Task Execute(string[] args)
|
||||||
{
|
{
|
||||||
if (args is null)
|
if (args is null)
|
||||||
{
|
{
|
||||||
foreach (var settings in Application.CurrentApplication.ApplicationEnvironmentVariables)
|
PrintAllSettings();
|
||||||
Console.WriteLine(settings.Key + ": " + settings.Value);
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@@ -59,7 +61,7 @@ public class SettingsConfig: ICommandAction
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "-h":
|
case "-h":
|
||||||
case "-help":
|
case "help":
|
||||||
Console.WriteLine("Options:");
|
Console.WriteLine("Options:");
|
||||||
Console.WriteLine("-s <settingName> <newValue>: Set a setting");
|
Console.WriteLine("-s <settingName> <newValue>: Set a setting");
|
||||||
Console.WriteLine("-r <settingName>: Remove a setting");
|
Console.WriteLine("-r <settingName>: Remove a setting");
|
||||||
@@ -76,4 +78,85 @@ public class SettingsConfig: ICommandAction
|
|||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
private void PrintList(IList<object> list, int indentLevel)
|
||||||
|
{
|
||||||
|
bool isListOfDictionaries = list.All(item => item is IDictionary<string, object>);
|
||||||
|
|
||||||
|
if (isListOfDictionaries)
|
||||||
|
{
|
||||||
|
foreach (var item in list)
|
||||||
|
{
|
||||||
|
if (item is IDictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
PrintDictionary(dict, indentLevel + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrintIndent(indentLevel);
|
||||||
|
Console.WriteLine(string.Join(",", list));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrintDictionary(IDictionary<string, object> dictionary, int indentLevel)
|
||||||
|
{
|
||||||
|
foreach (var kvp in dictionary)
|
||||||
|
{
|
||||||
|
PrintIndent(indentLevel);
|
||||||
|
Console.Write(kvp.Key + ": ");
|
||||||
|
|
||||||
|
var value = kvp.Value;
|
||||||
|
if (value is IDictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
PrintDictionary(dict, indentLevel + 1);
|
||||||
|
}
|
||||||
|
else if (value is IList<object> list)
|
||||||
|
{
|
||||||
|
if (list.All(item => item is IDictionary<string, object>))
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
PrintList(list, indentLevel + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrintList(list, indentLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrintIndent(int indentLevel)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < indentLevel; i++)
|
||||||
|
{
|
||||||
|
Console.Write(" "); // Two spaces for each indentation level
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrintAllSettings()
|
||||||
|
{
|
||||||
|
var settings = Application.CurrentApplication.ApplicationEnvironmentVariables;
|
||||||
|
foreach (var setting in settings)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Setting: " + setting.Key);
|
||||||
|
if (setting.Value is IDictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
PrintDictionary(dict, 1);
|
||||||
|
}
|
||||||
|
else if (setting.Value is IList<object> list)
|
||||||
|
{
|
||||||
|
PrintList(list, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine(setting.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,9 @@ internal class Help: DBCommand
|
|||||||
);
|
);
|
||||||
if (cmd == null) return null;
|
if (cmd == null) return null;
|
||||||
|
|
||||||
embedBuilder.AddField("Usage", Application.CurrentApplication.ApplicationEnvironmentVariables["prefix"] + cmd.Usage);
|
string prefix = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("prefix");
|
||||||
|
|
||||||
|
embedBuilder.AddField("Usage", prefix + cmd.Usage);
|
||||||
embedBuilder.AddField("Description", cmd.Description);
|
embedBuilder.AddField("Description", cmd.Description);
|
||||||
if (cmd.Aliases is null)
|
if (cmd.Aliases is null)
|
||||||
return embedBuilder;
|
return embedBuilder;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace DiscordBot;
|
|||||||
|
|
||||||
public static class Installer
|
public static class Installer
|
||||||
{
|
{
|
||||||
private static void AskForConfig(string key, string message)
|
private static string AskForConfig(string key, string message)
|
||||||
{
|
{
|
||||||
var value = AnsiConsole.Ask<string>($"[green]{message}[/]");
|
var value = AnsiConsole.Ask<string>($"[green]{message}[/]");
|
||||||
|
|
||||||
@@ -18,19 +18,29 @@ public static class Installer
|
|||||||
Environment.Exit(-20);
|
Environment.Exit(-20);
|
||||||
}
|
}
|
||||||
|
|
||||||
Application.CurrentApplication.ApplicationEnvironmentVariables.Add(key, value);
|
return value;
|
||||||
|
|
||||||
}
|
}
|
||||||
public static async Task GenerateStartupConfig()
|
public static async Task GenerateStartupConfig()
|
||||||
{
|
{
|
||||||
|
|
||||||
if(!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("token"))
|
if(!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("token"))
|
||||||
AskForConfig("token", "Token:");
|
{
|
||||||
|
string response = AskForConfig("token", "Token:");
|
||||||
|
Application.CurrentApplication.ApplicationEnvironmentVariables.Add("token", response);
|
||||||
|
}
|
||||||
|
|
||||||
if(!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("prefix"))
|
if (!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("prefix"))
|
||||||
AskForConfig("prefix", "Prefix:");
|
{
|
||||||
|
string response = AskForConfig("prefix", "Prefix:");
|
||||||
|
Application.CurrentApplication.ApplicationEnvironmentVariables.Add("prefix", response);
|
||||||
|
}
|
||||||
|
|
||||||
if(!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("ServerID"))
|
if (!Application.CurrentApplication.ApplicationEnvironmentVariables.ContainsKey("ServerID"))
|
||||||
AskForConfig("ServerID", "Server ID:");
|
{
|
||||||
|
string response = AskForConfig("ServerID", "Please enter the server Ids where the bot will be used (separated by ;):");
|
||||||
|
Application.CurrentApplication.ApplicationEnvironmentVariables.Add("ServerID", response);
|
||||||
|
}
|
||||||
|
|
||||||
await Application.CurrentApplication.ApplicationEnvironmentVariables.SaveToFile();
|
await Application.CurrentApplication.ApplicationEnvironmentVariables.SaveToFile();
|
||||||
|
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ public class Program
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var token = Application.CurrentApplication.ApplicationEnvironmentVariables["token"];
|
var token = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("token");
|
||||||
var prefix = Application.CurrentApplication.ApplicationEnvironmentVariables["prefix"];
|
var prefix = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("prefix");
|
||||||
var discordbooter = new App(token, prefix);
|
var discordbooter = new App(token, prefix);
|
||||||
await discordbooter.Awake();
|
await discordbooter.Awake();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using DiscordBotCore.Interfaces.Logger;
|
|||||||
using DiscordBotCore.Modules;
|
using DiscordBotCore.Modules;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using DiscordBotCore.Online.Helpers;
|
using DiscordBotCore.Online.Helpers;
|
||||||
|
using DiscordBotCore.Others.Settings;
|
||||||
|
|
||||||
|
|
||||||
namespace DiscordBotCore
|
namespace DiscordBotCore
|
||||||
@@ -26,21 +27,17 @@ namespace DiscordBotCore
|
|||||||
|
|
||||||
private static readonly string _ConfigFile = "./Data/Resources/config.json";
|
private static readonly string _ConfigFile = "./Data/Resources/config.json";
|
||||||
private static readonly string _PluginsDatabaseFile = "./Data/Resources/plugins.json";
|
private static readonly string _PluginsDatabaseFile = "./Data/Resources/plugins.json";
|
||||||
private static readonly string _ModuleFolder = "./Data/Modules";
|
|
||||||
|
|
||||||
private static readonly string _ResourcesFolder = "./Data/Resources";
|
private static readonly string _ResourcesFolder = "./Data/Resources";
|
||||||
private static readonly string _PluginsFolder = "./Data/Plugins";
|
private static readonly string _PluginsFolder = "./Data/Plugins";
|
||||||
private static readonly string _ArchivesFolder = "./Data/Archives";
|
|
||||||
private static readonly string _LogsFolder = "./Data/Logs";
|
private static readonly string _LogsFolder = "./Data/Logs";
|
||||||
|
|
||||||
private static readonly string _MaxParallelDownloads = "3";
|
public List<ulong> ServerIDs => ApplicationEnvironmentVariables.GetList("ServerID", new List<ulong>());
|
||||||
|
public string PluginDatabase => ApplicationEnvironmentVariables.Get<string>("PluginDatabase", _PluginsDatabaseFile);
|
||||||
public string ServerID => ApplicationEnvironmentVariables["ServerID"];
|
|
||||||
public string PluginDatabase => ApplicationEnvironmentVariables["PluginDatabase"] ?? _PluginsDatabaseFile;
|
|
||||||
|
|
||||||
private ModuleManager _ModuleManager;
|
private ModuleManager _ModuleManager;
|
||||||
|
|
||||||
public SettingsDictionary<string, string> ApplicationEnvironmentVariables { get; private set; }
|
public CustomSettingsDictionary ApplicationEnvironmentVariables { get; private set; }
|
||||||
public InternalActionManager InternalActionManager { get; private set; }
|
public InternalActionManager InternalActionManager { get; private set; }
|
||||||
|
|
||||||
public ILogger Logger
|
public ILogger Logger
|
||||||
@@ -84,27 +81,19 @@ namespace DiscordBotCore
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
CurrentApplication = new Application();
|
CurrentApplication = new Application();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Directory.CreateDirectory(_ResourcesFolder);
|
Directory.CreateDirectory(_ResourcesFolder);
|
||||||
Directory.CreateDirectory(_PluginsFolder);
|
Directory.CreateDirectory(_PluginsFolder);
|
||||||
Directory.CreateDirectory(_ArchivesFolder);
|
|
||||||
Directory.CreateDirectory(_LogsFolder);
|
Directory.CreateDirectory(_LogsFolder);
|
||||||
Directory.CreateDirectory(_ModuleFolder);
|
|
||||||
|
|
||||||
CurrentApplication.ApplicationEnvironmentVariables = new SettingsDictionary<string, string>(_ConfigFile);
|
CurrentApplication.ApplicationEnvironmentVariables = await CustomSettingsDictionary.CreateFromFile(_ConfigFile, true);
|
||||||
bool result = await CurrentApplication.ApplicationEnvironmentVariables.LoadFromFile();
|
|
||||||
if(!result)
|
|
||||||
{
|
|
||||||
PopulateEnvWithDefault();
|
|
||||||
File.Delete(_ConfigFile);
|
|
||||||
await CurrentApplication.ApplicationEnvironmentVariables.SaveToFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentApplication.ApplicationEnvironmentVariables.Add("ModuleFolder", _ModuleFolder);
|
CurrentApplication.ApplicationEnvironmentVariables.Set("PluginFolder", _PluginsFolder);
|
||||||
|
CurrentApplication.ApplicationEnvironmentVariables.Set("ResourceFolder", _ResourcesFolder);
|
||||||
CurrentApplication._ModuleManager = new(_ModuleFolder);
|
CurrentApplication.ApplicationEnvironmentVariables.Set("LogsFolder", _LogsFolder);
|
||||||
|
|
||||||
|
|
||||||
|
CurrentApplication._ModuleManager = new ModuleManager();
|
||||||
await CurrentApplication._ModuleManager.LoadModules();
|
await CurrentApplication._ModuleManager.LoadModules();
|
||||||
|
|
||||||
if (!File.Exists(_PluginsDatabaseFile))
|
if (!File.Exists(_PluginsDatabaseFile))
|
||||||
@@ -130,29 +119,13 @@ namespace DiscordBotCore
|
|||||||
|
|
||||||
public IReadOnlyDictionary<Type, List<object>> GetLoadedCoreModules() => _ModuleManager.LoadedModules.AsReadOnly();
|
public IReadOnlyDictionary<Type, List<object>> GetLoadedCoreModules() => _ModuleManager.LoadedModules.AsReadOnly();
|
||||||
|
|
||||||
private static void PopulateEnvWithDefault()
|
|
||||||
{
|
|
||||||
if (CurrentApplication is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (CurrentApplication.ApplicationEnvironmentVariables is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
CurrentApplication.ApplicationEnvironmentVariables["LogFolder"] = _LogsFolder;
|
|
||||||
CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"] = _PluginsFolder;
|
|
||||||
CurrentApplication.ApplicationEnvironmentVariables["ArchiveFolder"] = _ArchivesFolder;
|
|
||||||
CurrentApplication.ApplicationEnvironmentVariables["PluginDatabase"] = _PluginsDatabaseFile;
|
|
||||||
CurrentApplication.ApplicationEnvironmentVariables["MaxParallelDownloads"] = _MaxParallelDownloads;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetResourceFullPath(string path)
|
public static string GetResourceFullPath(string path)
|
||||||
{
|
{
|
||||||
string result = Path.Combine(_ResourcesFolder, path);
|
string result = Path.Combine(_ResourcesFolder, path);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetResourceFullPath() => _ResourcesFolder;
|
public static string GetResourceFullPath() => CurrentApplication.ApplicationEnvironmentVariables.Get<string>("ResourceFolder", _ResourcesFolder);
|
||||||
|
|
||||||
public static string GetPluginFullPath(string path)
|
public static string GetPluginFullPath(string path)
|
||||||
{
|
{
|
||||||
@@ -160,7 +133,7 @@ namespace DiscordBotCore
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetPluginFullPath() => _PluginsFolder;
|
public static string GetPluginFullPath() => CurrentApplication.ApplicationEnvironmentVariables.Get<string>("PluginFolder", _PluginsFolder);
|
||||||
|
|
||||||
public static async Task<string> GetPluginDependencyPath(string dependencyName, string? pluginName = null)
|
public static async Task<string> GetPluginDependencyPath(string dependencyName, string? pluginName = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,16 +11,17 @@ namespace DiscordBotCore.Loaders
|
|||||||
{
|
{
|
||||||
internal class ModuleLoader
|
internal class ModuleLoader
|
||||||
{
|
{
|
||||||
private string _moduleFolder;
|
private readonly string _ModuleFolder;
|
||||||
|
|
||||||
public ModuleLoader(string moduleFolder)
|
public ModuleLoader(string moduleFolder)
|
||||||
{
|
{
|
||||||
_moduleFolder = moduleFolder;
|
_ModuleFolder = moduleFolder;
|
||||||
|
Directory.CreateDirectory(moduleFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task LoadFileModules()
|
public Task LoadFileModules()
|
||||||
{
|
{
|
||||||
var files = Directory.GetFiles(_moduleFolder, "*.dll");
|
var files = Directory.GetFiles(_ModuleFolder, "*.dll");
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ using System.Collections.Generic;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Discord;
|
using Discord;
|
||||||
|
using Discord.Interactions;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
|
||||||
using DiscordBotCore.Interfaces;
|
using DiscordBotCore.Interfaces;
|
||||||
using DiscordBotCore.Others;
|
using DiscordBotCore.Others;
|
||||||
|
using ContextType = Discord.Commands.ContextType;
|
||||||
|
|
||||||
namespace DiscordBotCore.Loaders;
|
namespace DiscordBotCore.Loaders;
|
||||||
|
|
||||||
@@ -31,60 +33,75 @@ internal static class PluginLoaderExtensions
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task ResetSlashCommands(this PluginLoader pluginLoader)
|
internal static Task ResetSlashCommands(this PluginLoader pluginLoader)
|
||||||
{
|
{
|
||||||
await pluginLoader._Client.Rest.DeleteAllGlobalCommandsAsync();
|
throw new NotImplementedException("This method is not implemented yet.");
|
||||||
|
|
||||||
if(pluginLoader._Client.Guilds.Count == 0) return;
|
// await pluginLoader._Client.Rest.DeleteAllGlobalCommandsAsync();
|
||||||
if (!ulong.TryParse(Application.CurrentApplication.ServerID, out _))
|
//
|
||||||
{
|
// if(pluginLoader._Client.Guilds.Count == 0) return;
|
||||||
Application.CurrentApplication.Logger.Log("Invalid ServerID in config file. Can not reset specific guild commands", typeof(PluginLoader), LogType.Error);
|
// if (!ulong.TryParse(Application.CurrentApplication.ServerID, out _))
|
||||||
return;
|
// {
|
||||||
}
|
// Application.CurrentApplication.Logger.Log("Invalid ServerID in config file. Can not reset specific guild commands", typeof(PluginLoader), LogType.Error);
|
||||||
|
// return;
|
||||||
SocketGuild? guild = pluginLoader._Client.GetGuild(ulong.Parse(Application.CurrentApplication.ServerID));
|
// }
|
||||||
if(guild is null)
|
//
|
||||||
{
|
// SocketGuild? guild = pluginLoader._Client.GetGuild(ulong.Parse(Application.CurrentApplication.ServerID));
|
||||||
Application.CurrentApplication.Logger.Log("Failed to get guild with ID " + Application.CurrentApplication.ServerID, typeof(PluginLoader), LogType.Error);
|
// if(guild is null)
|
||||||
return;
|
// {
|
||||||
}
|
// Application.CurrentApplication.Logger.Log("Failed to get guild with ID " + Application.CurrentApplication.ServerID, typeof(PluginLoader), LogType.Error);
|
||||||
|
// return;
|
||||||
await guild.DeleteApplicationCommandsAsync();
|
// }
|
||||||
|
//
|
||||||
Application.CurrentApplication.Logger.Log($"Cleared all slash commands from guild {guild.Id}", typeof(PluginLoader));
|
// await guild.DeleteApplicationCommandsAsync();
|
||||||
|
//
|
||||||
|
// Application.CurrentApplication.Logger.Log($"Cleared all slash commands from guild {guild.Id}", typeof(PluginLoader));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task<bool> TryStartSlashCommand(this PluginLoader pluginLoader, DBSlashCommand? dbSlashCommand)
|
internal static async Task<bool> TryStartSlashCommand(this PluginLoader pluginLoader, DBSlashCommand? dbSlashCommand)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (dbSlashCommand is null)
|
if (dbSlashCommand is null)
|
||||||
{
|
{
|
||||||
//throw new ArgumentNullException(nameof(dbSlashCommand));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginLoader._Client.Guilds.Count == 0) return false;
|
if (pluginLoader._Client.Guilds.Count == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var builder = new SlashCommandBuilder();
|
var builder = new SlashCommandBuilder();
|
||||||
builder.WithName(dbSlashCommand.Name);
|
builder.WithName(dbSlashCommand.Name);
|
||||||
builder.WithDescription(dbSlashCommand.Description);
|
builder.WithDescription(dbSlashCommand.Description);
|
||||||
builder.WithDMPermission(dbSlashCommand.canUseDM);
|
|
||||||
builder.Options = dbSlashCommand.Options;
|
builder.Options = dbSlashCommand.Options;
|
||||||
|
|
||||||
if (uint.TryParse(Application.CurrentApplication.ServerID, out uint result))
|
if (dbSlashCommand.canUseDM)
|
||||||
{
|
builder.WithContextTypes(InteractionContextType.BotDm, InteractionContextType.Guild);
|
||||||
SocketGuild? guild = pluginLoader._Client.GetGuild(result);
|
else
|
||||||
if (guild is null)
|
builder.WithContextTypes(InteractionContextType.Guild);
|
||||||
{
|
|
||||||
Application.CurrentApplication.Logger.Log("Failed to get guild with ID " + Application.CurrentApplication.ServerID, typeof(PluginLoader), LogType.Error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
await guild.CreateApplicationCommandAsync(builder.Build());
|
// if (uint.TryParse(Application.CurrentApplication.ServerID, out uint result))
|
||||||
}else await pluginLoader._Client.CreateGlobalApplicationCommandAsync(builder.Build());
|
// {
|
||||||
|
// SocketGuild? guild = pluginLoader._Client.GetGuild(result);
|
||||||
|
// if (guild is null)
|
||||||
|
// {
|
||||||
|
// Application.CurrentApplication.Logger.Log("Failed to get guild with ID " + Application.CurrentApplication.ServerID, typeof(PluginLoader), LogType.Error);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// await guild.CreateApplicationCommandAsync(builder.Build());
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
|
||||||
|
foreach(ulong guildId in Application.CurrentApplication.ServerIDs)
|
||||||
|
{
|
||||||
|
await pluginLoader.EnableSlashCommandPerGuild(guildId, builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
await pluginLoader._Client.CreateGlobalApplicationCommandAsync(builder.Build());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -94,4 +111,19 @@ internal static class PluginLoaderExtensions
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task<bool> EnableSlashCommandPerGuild(this PluginLoader pluginLoader, ulong guildId, SlashCommandBuilder builder)
|
||||||
|
{
|
||||||
|
SocketGuild? guild = pluginLoader._Client.GetGuild(guildId);
|
||||||
|
if (guild is null)
|
||||||
|
{
|
||||||
|
Application.CurrentApplication.Logger.Log("Failed to get guild with ID " + guildId, typeof(PluginLoader), LogType.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await guild.CreateApplicationCommandAsync(builder.Build());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,12 +12,20 @@ namespace DiscordBotCore.Modules
|
|||||||
{
|
{
|
||||||
internal class ModuleManager
|
internal class ModuleManager
|
||||||
{
|
{
|
||||||
private string _moduleFolder;
|
private static readonly string _BaseModuleFolder = "./Data/Modules";
|
||||||
internal Dictionary<Type, List<object>> LoadedModules { get; private set; }
|
|
||||||
|
private readonly string _ModuleFolder;
|
||||||
|
internal Dictionary<Type, List<object>> LoadedModules { get; }
|
||||||
|
|
||||||
public ModuleManager(string moduleFolder)
|
public ModuleManager(string moduleFolder)
|
||||||
{
|
{
|
||||||
_moduleFolder = moduleFolder;
|
_ModuleFolder = moduleFolder;
|
||||||
|
LoadedModules = new Dictionary<Type, List<object>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModuleManager()
|
||||||
|
{
|
||||||
|
_ModuleFolder = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("ModuleFolder", _BaseModuleFolder);
|
||||||
LoadedModules = new Dictionary<Type, List<object>>();
|
LoadedModules = new Dictionary<Type, List<object>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,11 +43,10 @@ namespace DiscordBotCore.Modules
|
|||||||
|
|
||||||
public async Task LoadModules()
|
public async Task LoadModules()
|
||||||
{
|
{
|
||||||
ModuleLoader loader = new ModuleLoader(_moduleFolder);
|
ModuleLoader loader = new ModuleLoader(_ModuleFolder);
|
||||||
await loader.LoadFileModules();
|
await loader.LoadFileModules();
|
||||||
|
|
||||||
|
|
||||||
// Load All Loggers
|
|
||||||
var loggers = await loader.LoadModules<ILogger>();
|
var loggers = await loader.LoadModules<ILogger>();
|
||||||
foreach (var logger in loggers)
|
foreach (var logger in loggers)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ public class PluginManager : IPluginManager
|
|||||||
installProgress?.Report(currentProgress + stepProgress * p);
|
installProgress?.Report(currentProgress + stepProgress * p);
|
||||||
});
|
});
|
||||||
|
|
||||||
await ServerCom.DownloadFileAsync(pluginData.DownLoadLink, $"{Application.CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"]}/{pluginData.Name}.dll", progress);
|
await ServerCom.DownloadFileAsync(pluginData.DownLoadLink, $"{Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("PluginFolder")}/{pluginData.Name}.dll", progress);
|
||||||
|
|
||||||
if (pluginData.HasFileDependencies)
|
if (pluginData.HasFileDependencies)
|
||||||
foreach (var dependency in pluginData.Dependencies)
|
foreach (var dependency in pluginData.Dependencies)
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ namespace DiscordBotCore.Others;
|
|||||||
|
|
||||||
public static class ArchiveManager
|
public static class ArchiveManager
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private static readonly string _ArchivesFolder = "./Data/Archives";
|
||||||
|
|
||||||
public static void CreateFromFile(string file, string folder)
|
public static void CreateFromFile(string file, string folder)
|
||||||
{
|
{
|
||||||
@@ -33,7 +35,13 @@ public static class ArchiveManager
|
|||||||
public static async Task<byte[]?> ReadAllBytes(string fileName, string archName)
|
public static async Task<byte[]?> ReadAllBytes(string fileName, string archName)
|
||||||
{
|
{
|
||||||
|
|
||||||
archName = Path.Combine(Application.CurrentApplication.ApplicationEnvironmentVariables["ArchiveFolder"], archName);
|
string? archiveFolderBasePath = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("ArchiveFolder", _ArchivesFolder);
|
||||||
|
if(archiveFolderBasePath is null)
|
||||||
|
throw new Exception("Archive folder not found");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(archiveFolderBasePath);
|
||||||
|
|
||||||
|
archName = Path.Combine(archiveFolderBasePath, archName);
|
||||||
|
|
||||||
if (!File.Exists(archName))
|
if (!File.Exists(archName))
|
||||||
throw new Exception("Failed to load file !");
|
throw new Exception("Failed to load file !");
|
||||||
@@ -64,7 +72,14 @@ public static class ArchiveManager
|
|||||||
/// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns>
|
/// <returns>A string that represents the content of the file or null if the file does not exists or it has no content</returns>
|
||||||
public static async Task<string?> ReadFromPakAsync(string fileName, string archFile)
|
public static async Task<string?> ReadFromPakAsync(string fileName, string archFile)
|
||||||
{
|
{
|
||||||
archFile = Application.CurrentApplication.ApplicationEnvironmentVariables["ArchiveFolder"] + archFile;
|
string? archiveFolderBasePath = Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("ArchiveFolder", _ArchivesFolder);
|
||||||
|
if(archiveFolderBasePath is null)
|
||||||
|
throw new Exception("Archive folder not found");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(archiveFolderBasePath);
|
||||||
|
|
||||||
|
archFile = Path.Combine(archiveFolderBasePath, archFile);
|
||||||
|
|
||||||
if (!File.Exists(archFile))
|
if (!File.Exists(archFile))
|
||||||
throw new Exception("Failed to load file !");
|
throw new Exception("Failed to load file !");
|
||||||
|
|
||||||
|
|||||||
93
DiscordBotCore/Others/Settings/CustomSettingsDictionary.cs
Normal file
93
DiscordBotCore/Others/Settings/CustomSettingsDictionary.cs
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace DiscordBotCore.Others.Settings;
|
||||||
|
|
||||||
|
public class CustomSettingsDictionary : CustomSettingsDictionaryBase<string, object>
|
||||||
|
{
|
||||||
|
private bool _EnableAutoAddOnGetWithDefault;
|
||||||
|
private CustomSettingsDictionary(string diskLocation, bool enableAutoAddOnGetWithDefault): base(diskLocation)
|
||||||
|
{
|
||||||
|
_EnableAutoAddOnGetWithDefault = enableAutoAddOnGetWithDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task SaveToFile()
|
||||||
|
{
|
||||||
|
var json = JsonConvert.SerializeObject(_InternalDictionary, Formatting.Indented);
|
||||||
|
await File.WriteAllTextAsync(_DiskLocation, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override T Get<T>(string key, T defaultValue)
|
||||||
|
{
|
||||||
|
T value = base.Get(key, defaultValue);
|
||||||
|
|
||||||
|
if (_EnableAutoAddOnGetWithDefault && value.Equals(defaultValue))
|
||||||
|
{
|
||||||
|
Add(key, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<T> GetList<T>(string key, List<T> defaultValue)
|
||||||
|
{
|
||||||
|
List<T> result = base.GetList(key, defaultValue);
|
||||||
|
|
||||||
|
if (_EnableAutoAddOnGetWithDefault && defaultValue.All(result.Contains))
|
||||||
|
{
|
||||||
|
Add(key,defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task LoadFromFile()
|
||||||
|
{
|
||||||
|
string jsonContent = await File.ReadAllTextAsync(_DiskLocation);
|
||||||
|
var jObject = JsonConvert.DeserializeObject<JObject>(jsonContent);
|
||||||
|
_InternalDictionary.Clear();
|
||||||
|
|
||||||
|
foreach (var kvp in jObject)
|
||||||
|
{
|
||||||
|
AddPairToDictionary(kvp, _InternalDictionary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddPairToDictionary(KeyValuePair<string, JToken> kvp, IDictionary<string, object> dict)
|
||||||
|
{
|
||||||
|
if (kvp.Value is JObject nestedJObject)
|
||||||
|
{
|
||||||
|
dict[kvp.Key] = nestedJObject.ToObject<Dictionary<string, object>>();
|
||||||
|
|
||||||
|
foreach (var nestedKvp in nestedJObject)
|
||||||
|
{
|
||||||
|
AddPairToDictionary(nestedKvp, dict[kvp.Key] as Dictionary<string, object>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (kvp.Value is JArray nestedJArray)
|
||||||
|
{
|
||||||
|
dict[kvp.Key] = nestedJArray.ToObject<List<object>>();
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dict[kvp.Key] = kvp.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new Settings Dictionary from a file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="baseFile">The file location</param>
|
||||||
|
/// <param name="enableAutoAddOnGetWithDefault">Set this to true if you want to update the dictionary with default values on get</param>
|
||||||
|
internal static async Task<CustomSettingsDictionary> CreateFromFile(string baseFile, bool enableAutoAddOnGetWithDefault)
|
||||||
|
{
|
||||||
|
var settings = new CustomSettingsDictionary(baseFile, enableAutoAddOnGetWithDefault);
|
||||||
|
await settings.LoadFromFile();
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
160
DiscordBotCore/Others/Settings/CustomSettingsDictionaryBase.cs
Normal file
160
DiscordBotCore/Others/Settings/CustomSettingsDictionaryBase.cs
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DiscordBotCore.Others.Settings;
|
||||||
|
|
||||||
|
public abstract class CustomSettingsDictionaryBase<TKey,TValue> : ICustomSettingsDictionary<TKey,TValue>
|
||||||
|
{
|
||||||
|
protected readonly IDictionary<TKey,TValue> _InternalDictionary = new Dictionary<TKey, TValue>();
|
||||||
|
protected readonly string _DiskLocation;
|
||||||
|
|
||||||
|
protected CustomSettingsDictionaryBase(string diskLocation)
|
||||||
|
{
|
||||||
|
this._DiskLocation = diskLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Add(TKey key, TValue value)
|
||||||
|
{
|
||||||
|
if (_InternalDictionary.ContainsKey(key))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (value is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_InternalDictionary.Add(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Set(TKey key, TValue value)
|
||||||
|
{
|
||||||
|
_InternalDictionary[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual TValue Get(TKey key)
|
||||||
|
{
|
||||||
|
return _InternalDictionary[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual T Get<T>(TKey key, T defaultValue)
|
||||||
|
{
|
||||||
|
if (_InternalDictionary.TryGetValue(key, out var value))
|
||||||
|
{
|
||||||
|
return (T)Convert.ChangeType(value, typeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual T? Get<T>(TKey key)
|
||||||
|
{
|
||||||
|
if (_InternalDictionary.TryGetValue(key, out var value))
|
||||||
|
{
|
||||||
|
return (T)Convert.ChangeType(value, typeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual List<T> GetList<T>(TKey key, List<T> defaultValue)
|
||||||
|
{
|
||||||
|
if(_InternalDictionary.TryGetValue(key, out var value))
|
||||||
|
{
|
||||||
|
if (value is not IList)
|
||||||
|
{
|
||||||
|
throw new Exception("The value is not a list");
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = new List<T>();
|
||||||
|
foreach (var item in (IList)value)
|
||||||
|
{
|
||||||
|
list.Add(ConvertValue<T>(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Remove(TKey key)
|
||||||
|
{
|
||||||
|
_InternalDictionary.Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
||||||
|
{
|
||||||
|
return _InternalDictionary.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Clear()
|
||||||
|
{
|
||||||
|
_InternalDictionary.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool ContainsKey(TKey key)
|
||||||
|
{
|
||||||
|
return _InternalDictionary.ContainsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<KeyValuePair<TKey, TValue>> Where(Func<KeyValuePair<TKey, TValue>, bool> predicate)
|
||||||
|
{
|
||||||
|
return _InternalDictionary.Where(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<KeyValuePair<TKey, TValue>> Where(Func<KeyValuePair<TKey, TValue>, int, bool> predicate)
|
||||||
|
{
|
||||||
|
return _InternalDictionary.Where(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<TResult> Where<TResult>(Func<KeyValuePair<TKey, TValue>, TResult> selector)
|
||||||
|
{
|
||||||
|
return _InternalDictionary.Select(selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual IEnumerable<TResult> Where<TResult>(Func<KeyValuePair<TKey, TValue>, int, TResult> selector)
|
||||||
|
{
|
||||||
|
return _InternalDictionary.Select(selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual KeyValuePair<TKey, TValue> FirstOrDefault(Func<KeyValuePair<TKey, TValue>, bool> predicate)
|
||||||
|
{
|
||||||
|
return _InternalDictionary.FirstOrDefault(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual KeyValuePair<TKey, TValue> FirstOrDefault()
|
||||||
|
{
|
||||||
|
return _InternalDictionary.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool ContainsAllKeys(params TKey[] keys)
|
||||||
|
{
|
||||||
|
return keys.All(ContainsKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool TryGetValue(TKey key, out TValue? value)
|
||||||
|
{
|
||||||
|
return _InternalDictionary.TryGetValue(key, out value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Task SaveToFile();
|
||||||
|
|
||||||
|
public abstract Task LoadFromFile();
|
||||||
|
|
||||||
|
protected virtual T? ConvertValue<T>(object value)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (typeof(T) == typeof(ulong) && value is long longValue)
|
||||||
|
{
|
||||||
|
return (T)(object)Convert.ToUInt64(longValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof(T).IsEnum && value is string stringValue)
|
||||||
|
{
|
||||||
|
return (T)Enum.Parse(typeof(T), stringValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (T)Convert.ChangeType(value, typeof(T));
|
||||||
|
}
|
||||||
|
}
|
||||||
136
DiscordBotCore/Others/Settings/ICustomSettingsDictionary.cs
Normal file
136
DiscordBotCore/Others/Settings/ICustomSettingsDictionary.cs
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DiscordBotCore.Others.Settings;
|
||||||
|
|
||||||
|
internal interface ICustomSettingsDictionary<TKey,TValue>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an element to the custom settings dictionary
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key</param>
|
||||||
|
/// <param name="value">The value</param>
|
||||||
|
void Add(TKey key, TValue value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the value of a key in the custom settings dictionary
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key</param>
|
||||||
|
/// <param name="value">The value</param>
|
||||||
|
void Set(TKey key, TValue value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of a key in the custom settings dictionary. If the T type is different then the TValue type, it will try to convert it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key</param>
|
||||||
|
/// <param name="defaultValue">The default value to be returned if the searched value is not found</param>
|
||||||
|
/// <typeparam name="T">The type of the returned value</typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
T Get<T>(TKey key, T defaultValue);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of a key in the custom settings dictionary. If the T type is different then the TValue type, it will try to convert it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key</param>
|
||||||
|
/// <typeparam name="T">The type of the returned value</typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
T? Get<T>(TKey key);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a list of values from the custom settings dictionary
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key</param>
|
||||||
|
/// <param name="defaultValue">The default list to be returned if nothing is found</param>
|
||||||
|
/// <typeparam name="T">The type of the returned value</typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<T> GetList<T>(TKey key, List<T> defaultValue);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove a key from the custom settings dictionary
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key</param>
|
||||||
|
void Remove(TKey key);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the enumerator of the custom settings dictionary
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clear the custom settings dictionary
|
||||||
|
/// </summary>
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if the custom settings dictionary contains a key
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool ContainsKey(TKey key);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Filter the custom settings dictionary based on a predicate
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="predicate">The predicate</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
IEnumerable<KeyValuePair<TKey, TValue>> Where(Func<KeyValuePair<TKey, TValue>, bool> predicate);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Filter the custom settings dictionary based on a predicate
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="predicate">The predicate</param>
|
||||||
|
IEnumerable<KeyValuePair<TKey, TValue>> Where(Func<KeyValuePair<TKey, TValue>, int, bool> predicate);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Filter the custom settings dictionary based on a predicate
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="selector">The predicate</param>
|
||||||
|
IEnumerable<TResult> Where<TResult>(Func<KeyValuePair<TKey, TValue>, TResult> selector);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Filter the custom settings dictionary based on a predicate
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="selector">The predicate</param>
|
||||||
|
IEnumerable<TResult> Where<TResult>(Func<KeyValuePair<TKey, TValue>, int, TResult> selector);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the first element of the custom settings dictionary based on a predicate
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="predicate">The predicate</param>
|
||||||
|
KeyValuePair<TKey, TValue> FirstOrDefault(Func<KeyValuePair<TKey, TValue>, bool> predicate);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the first element of the custom settings dictionary
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
KeyValuePair<TKey, TValue> FirstOrDefault();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the custom settings dictionary contains all the keys
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="keys">A list of keys</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool ContainsAllKeys(params TKey[] keys);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to get the value of a key in the custom settings dictionary
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key</param>
|
||||||
|
/// <param name="value">The value</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool TryGetValue(TKey key, out TValue? value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Save the custom settings dictionary to a file
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task SaveToFile();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load the custom settings dictionary from a file
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task LoadFromFile();
|
||||||
|
}
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace DiscordBotCore.Others;
|
|
||||||
|
|
||||||
public class SettingsDictionary<TKey, TValue>
|
|
||||||
{
|
|
||||||
private string _File { get; }
|
|
||||||
protected IDictionary<TKey, TValue> _Dictionary;
|
|
||||||
|
|
||||||
public SettingsDictionary(string file)
|
|
||||||
{
|
|
||||||
this._File = file;
|
|
||||||
_Dictionary = null!;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SaveToFile()
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(_File))
|
|
||||||
await JsonManager.SaveToJsonFile(_File, _Dictionary);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
|
|
||||||
{
|
|
||||||
return _Dictionary.GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> LoadFromFile()
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(_File))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(!File.Exists(_File))
|
|
||||||
{
|
|
||||||
_Dictionary = new Dictionary<TKey, TValue>();
|
|
||||||
await SaveToFile();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
string fileAsText = await File.ReadAllTextAsync(_File);
|
|
||||||
if(string.IsNullOrEmpty(fileAsText) || string.IsNullOrWhiteSpace(fileAsText))
|
|
||||||
{
|
|
||||||
_Dictionary = new Dictionary<TKey, TValue>();
|
|
||||||
await SaveToFile();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_Dictionary = await JsonManager.ConvertFromJson<IDictionary<TKey,TValue>>(fileAsText);
|
|
||||||
|
|
||||||
if (_Dictionary.Keys.Count == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(TKey key, TValue value)
|
|
||||||
{
|
|
||||||
if (_Dictionary.ContainsKey(key))
|
|
||||||
return;
|
|
||||||
|
|
||||||
_Dictionary.Add(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ContainsAllKeys(params TKey[] keys)
|
|
||||||
{
|
|
||||||
return keys.All(key => _Dictionary.ContainsKey(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ContainsKey(TKey key)
|
|
||||||
{
|
|
||||||
return _Dictionary.ContainsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Remove(TKey key)
|
|
||||||
{
|
|
||||||
return _Dictionary.Remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TValue this[TKey key]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if(!_Dictionary.ContainsKey(key))
|
|
||||||
throw new System.Exception($"The key {key} ({typeof(TKey)}) (file: {this._File}) was not present in the dictionary");
|
|
||||||
|
|
||||||
if(_Dictionary[key] is not TValue)
|
|
||||||
throw new System.Exception("The dictionary is corrupted. This error is critical !");
|
|
||||||
|
|
||||||
return _Dictionary[key];
|
|
||||||
}
|
|
||||||
set => _Dictionary[key] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// First
|
|
||||||
public KeyValuePair<TKey, TValue> FirstOrDefault(Func<KeyValuePair<TKey, TValue>, bool> predicate)
|
|
||||||
{
|
|
||||||
return _Dictionary.FirstOrDefault(predicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Where
|
|
||||||
public IEnumerable<KeyValuePair<TKey, TValue>> Where(Func<KeyValuePair<TKey, TValue>, bool> predicate)
|
|
||||||
{
|
|
||||||
return _Dictionary.Where(predicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
_Dictionary.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<TKey> Keys => _Dictionary.Keys;
|
|
||||||
public IEnumerable<TValue> Values => _Dictionary.Values;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -22,20 +22,20 @@ public class PluginInfo
|
|||||||
PluginVersion = pluginVersion;
|
PluginVersion = pluginVersion;
|
||||||
ListOfExecutableDependencies = listOfExecutableDependencies;
|
ListOfExecutableDependencies = listOfExecutableDependencies;
|
||||||
IsMarkedToUninstall = isMarkedToUninstall;
|
IsMarkedToUninstall = isMarkedToUninstall;
|
||||||
FilePath = $"{Application.CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"]}/{pluginName}.dll";
|
FilePath = $"{Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("PluginFolder")}/{pluginName}.dll";
|
||||||
IsOfflineAdded = isOfflineAdded;
|
IsOfflineAdded = isOfflineAdded;
|
||||||
IsEnabled = isEnabled;
|
IsEnabled = isEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginInfo(string pluginName, PluginVersion pluginVersion, Dictionary<string, string> listOfExecutableDependencies)
|
public PluginInfo(string pluginName, PluginVersion pluginVersion, Dictionary<string, string> listOfExecutableDependencies)
|
||||||
{
|
{
|
||||||
PluginName = pluginName;
|
PluginName = pluginName;
|
||||||
PluginVersion = pluginVersion;
|
PluginVersion = pluginVersion;
|
||||||
ListOfExecutableDependencies = listOfExecutableDependencies;
|
ListOfExecutableDependencies = listOfExecutableDependencies;
|
||||||
IsMarkedToUninstall = false;
|
IsMarkedToUninstall = false;
|
||||||
FilePath = $"{Application.CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"]}/{pluginName}.dll";
|
FilePath = $"{Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("PluginFolder")}/{pluginName}.dll";
|
||||||
IsOfflineAdded = false;
|
IsOfflineAdded = false;
|
||||||
IsEnabled = true;
|
IsEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PluginInfo FromOnlineInfo(PluginOnlineInfo onlineInfo)
|
public static PluginInfo FromOnlineInfo(PluginOnlineInfo onlineInfo)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class PluginUpdater
|
|||||||
public async Task UpdatePlugin(string pluginName, IProgress<float>? progressMeter = null)
|
public async Task UpdatePlugin(string pluginName, IProgress<float>? progressMeter = null)
|
||||||
{
|
{
|
||||||
PluginOnlineInfo pluginInfo = await GetPluginInfo(pluginName);
|
PluginOnlineInfo pluginInfo = await GetPluginInfo(pluginName);
|
||||||
await ServerCom.DownloadFileAsync(pluginInfo.DownLoadLink, $"{DiscordBotCore.Application.CurrentApplication.ApplicationEnvironmentVariables["PluginFolder"]}/{pluginName}.dll", progressMeter);
|
await ServerCom.DownloadFileAsync(pluginInfo.DownLoadLink, $"{DiscordBotCore.Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("PluginFolder")}/{pluginName}.dll", progressMeter);
|
||||||
|
|
||||||
foreach(OnlineDependencyInfo dependency in pluginInfo.Dependencies)
|
foreach(OnlineDependencyInfo dependency in pluginInfo.Dependencies)
|
||||||
await ServerCom.DownloadFileAsync(dependency.DownloadLink, dependency.DownloadLocation, progressMeter);
|
await ServerCom.DownloadFileAsync(dependency.DownloadLink, dependency.DownloadLocation, progressMeter);
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ namespace CppWrapper.Objects
|
|||||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||||||
public struct ApplicationStruct
|
public struct ApplicationStruct
|
||||||
{
|
{
|
||||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 19)]
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
|
||||||
public string ServerId;
|
public ulong[] ServerIds;
|
||||||
|
|
||||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
|
||||||
public string Prefix;
|
public string Prefix;
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ namespace CppWrapper.Objects
|
|||||||
{
|
{
|
||||||
return new ApplicationStruct
|
return new ApplicationStruct
|
||||||
{
|
{
|
||||||
Token = application.ApplicationEnvironmentVariables["token"],
|
Token = application.ApplicationEnvironmentVariables.Get<string>("token") ?? throw new Exception("Token not found"),
|
||||||
Prefix = application.ApplicationEnvironmentVariables["prefix"],
|
Prefix = application.ApplicationEnvironmentVariables.Get<string>("prefix") ?? throw new Exception("Prefix not found"),
|
||||||
ServerId = application.ServerID
|
ServerIds = application.ServerIDs.ToArray()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ internal class LevelEvent : DBEvent
|
|||||||
|
|
||||||
private async Task ClientOnMessageReceived(SocketMessage arg)
|
private async Task ClientOnMessageReceived(SocketMessage arg)
|
||||||
{
|
{
|
||||||
if (arg.Author.IsBot || arg.IsTTS || arg.Content.StartsWith(Application.CurrentApplication.ApplicationEnvironmentVariables["prefix"]))
|
if (arg.Author.IsBot || arg.IsTTS || arg.Content.StartsWith(Application.CurrentApplication.ApplicationEnvironmentVariables.Get<string>("prefix")))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (WaitingList.ContainsKey(arg.Author.Id) && WaitingList[arg.Author.Id] > DateTime.Now.AddSeconds(-GlobalSettings.SecondsToWaitBetweenMessages))
|
if (WaitingList.ContainsKey(arg.Author.Id) && WaitingList[arg.Author.Id] > DateTime.Now.AddSeconds(-GlobalSettings.SecondsToWaitBetweenMessages))
|
||||||
|
|||||||
@@ -78,8 +78,7 @@ public class AddMelody: DBCommand
|
|||||||
await msg.ModifyAsync(a => a.Content = "Done");
|
await msg.ModifyAsync(a => a.Content = "Done");
|
||||||
|
|
||||||
|
|
||||||
var info =
|
var info = MusicInfoExtensions.CreateMusicInfo(title, location, description ?? "Unknown", aliases.ToList(), bsize);
|
||||||
MusicInfoExtensions.CreateMusicInfo(title, location, description ?? "Unknown", aliases.ToList(), bsize);
|
|
||||||
|
|
||||||
Variables._MusicDatabase?.Add(title, info);
|
Variables._MusicDatabase?.Add(title, info);
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,13 @@ public class AddMelodyYoutube: DBCommand
|
|||||||
|
|
||||||
public async void ExecuteServer(DbCommandExecutingArguments args)
|
public async void ExecuteServer(DbCommandExecutingArguments args)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if(Variables._MusicDatabase is null)
|
||||||
|
{
|
||||||
|
await args.Context.Channel.SendMessageAsync("Music Database is not loaded !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (args.Arguments is null)
|
if (args.Arguments is null)
|
||||||
{
|
{
|
||||||
await args.Context.Channel.SendMessageAsync("Invalid arguments given. Please use the following format:\nadd_melody_youtube [URL]");
|
await args.Context.Channel.SendMessageAsync("Invalid arguments given. Please use the following format:\nadd_melody_youtube [URL]");
|
||||||
@@ -28,9 +35,9 @@ public class AddMelodyYoutube: DBCommand
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var URL = args.Arguments[0];
|
var url = args.Arguments[0];
|
||||||
|
|
||||||
if (!URL.StartsWith("https://www.youtube.com/watch?v=") && !URL.StartsWith("https://youtu.be/"))
|
if (!url.StartsWith("https://www.youtube.com/watch?v=") && !url.StartsWith("https://youtu.be/"))
|
||||||
{
|
{
|
||||||
await args.Context.Channel.SendMessageAsync("Invalid URL given. Please use the following format:\nadd_melody_youtube [URL]");
|
await args.Context.Channel.SendMessageAsync("Invalid URL given. Please use the following format:\nadd_melody_youtube [URL]");
|
||||||
return;
|
return;
|
||||||
@@ -44,7 +51,7 @@ public class AddMelodyYoutube: DBCommand
|
|||||||
|
|
||||||
var msg = await args.Context.Channel.SendMessageAsync("Saving melody ...");
|
var msg = await args.Context.Channel.SendMessageAsync("Saving melody ...");
|
||||||
|
|
||||||
var title = await YoutubeDLP.DownloadMelody(URL);
|
var title = await YoutubeDLP.DownloadMelody(url);
|
||||||
|
|
||||||
if (title == null)
|
if (title == null)
|
||||||
{
|
{
|
||||||
@@ -56,8 +63,11 @@ public class AddMelodyYoutube: DBCommand
|
|||||||
List<string> aliases = joinedAliases.Split('|').ToList();
|
List<string> aliases = joinedAliases.Split('|').ToList();
|
||||||
|
|
||||||
|
|
||||||
if (Variables._MusicDatabase.ContainsMelodyWithNameOrAlias(title))
|
if (Variables._MusicDatabase.GetMusicInfoWithTitleOrAlias(title).Any())
|
||||||
Variables._MusicDatabase.Remove(title);
|
{
|
||||||
|
await msg.ModifyAsync(x => x.Content = "Melody already exists !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Variables._MusicDatabase.Add(title, new MusicInfo()
|
Variables._MusicDatabase.Add(title, new MusicInfo()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,6 +15,19 @@ public class SearchMelody: DBCommand
|
|||||||
|
|
||||||
public void ExecuteServer(DbCommandExecutingArguments args)
|
public void ExecuteServer(DbCommandExecutingArguments args)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if(Variables._MusicDatabase is null)
|
||||||
|
{
|
||||||
|
args.Context.Channel.SendMessageAsync("Music Database is not loaded !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.Arguments is null || args.Arguments.Length == 0)
|
||||||
|
{
|
||||||
|
args.Context.Channel.SendMessageAsync("You need to specify a melody name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var title = string.Join(" ", args.Arguments);
|
var title = string.Join(" ", args.Arguments);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(title))
|
if (string.IsNullOrWhiteSpace(title))
|
||||||
@@ -23,16 +36,13 @@ public class SearchMelody: DBCommand
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MusicInfo>? info = Variables._MusicDatabase.GetMusicInfoList(title);
|
List<MusicInfo> info = Variables._MusicDatabase.GetMusicInfoWithTitleOrAlias(title);
|
||||||
if (info == null || info.Count == 0)
|
if (!info.Any())
|
||||||
{
|
{
|
||||||
args.Context.Channel.SendMessageAsync("No melody with that name or alias was found");
|
args.Context.Channel.SendMessageAsync("No melody with that name or alias was found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.Count > 1)
|
args.Context.Channel.SendMessageAsync(embed: info.Count > 1 ? info.ToEmbed(Color.DarkOrange) : info[0].ToEmbed(Color.DarkOrange));
|
||||||
args.Context.Channel.SendMessageAsync(embed: info.ToEmbed(Color.DarkOrange));
|
|
||||||
else
|
|
||||||
args.Context.Channel.SendMessageAsync(embed: info[0].ToEmbed(Color.DarkOrange));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,64 +1,67 @@
|
|||||||
using DiscordBotCore.Others;
|
using DiscordBotCore.Others;
|
||||||
|
using DiscordBotCore.Others.Settings;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace MusicPlayer;
|
namespace MusicPlayer;
|
||||||
|
|
||||||
public class MusicDatabase: SettingsDictionary<string, MusicInfo>
|
public class MusicDatabase: CustomSettingsDictionaryBase<string, MusicInfo>
|
||||||
{
|
{
|
||||||
public MusicDatabase(string file): base(file)
|
public MusicDatabase(string diskLocation): base(diskLocation)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public List<MusicInfo> GetMusicInfoWithTitleOrAlias(string searchQuery)
|
||||||
/// Checks if the database contains a melody with the specified name or alias
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="melodyName">The name (alias) of the melody</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public bool ContainsMelodyWithNameOrAlias(string melodyName)
|
|
||||||
{
|
{
|
||||||
return ContainsKey(melodyName) || Values.Any(elem => elem.Aliases.Contains(melodyName, StringComparer.CurrentCultureIgnoreCase));
|
List<MusicInfo> musicInfos = new List<MusicInfo>();
|
||||||
}
|
foreach (var (title, musicInfo) in _InternalDictionary)
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to get the music info of a melody with the specified name or alias. Returns the first match or null if no match was found.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="searchQuery">The music name or one of its aliases.</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public MusicInfo? GetMusicInfo(string searchQuery)
|
|
||||||
{
|
|
||||||
return FirstOrDefault(kvp => kvp.Key.Contains(searchQuery, StringComparison.InvariantCultureIgnoreCase) ||
|
|
||||||
kvp.Value.Aliases.Any(alias => alias.Contains(searchQuery, StringComparison.InvariantCultureIgnoreCase))
|
|
||||||
).Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get a list of music info that match the search query. Returns null if an error occurred, or empty list if no match was found.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="searchQuery">The search query</param>
|
|
||||||
/// <returns>null if an error occured, otherwise a list with songs that match the search query. If no song match the list is empty</returns>
|
|
||||||
public List<MusicInfo>? GetMusicInfoList(string searchQuery)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
return this.Where(kvp =>
|
|
||||||
kvp.Key.Contains(searchQuery, StringComparison.InvariantCultureIgnoreCase) ||
|
if(title.StartsWith(searchQuery))
|
||||||
kvp.Value.Aliases.Any(alias => alias.Contains(searchQuery, StringComparison.InvariantCultureIgnoreCase))
|
{
|
||||||
)
|
musicInfos.Add(musicInfo);
|
||||||
.Select(item => item.Value).ToList();
|
}
|
||||||
|
|
||||||
|
if (musicInfo.Aliases is null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (musicInfo.Aliases.Contains(searchQuery) || musicInfo.Aliases.Any(x => x.StartsWith(searchQuery)))
|
||||||
|
{
|
||||||
|
musicInfos.Add(musicInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception ex)
|
return musicInfos;
|
||||||
{
|
|
||||||
Console.WriteLine(ex.ToString());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public override async Task SaveToFile()
|
||||||
/// Adds a new entry to the database based on the music info. It uses the title as the key.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="musicInfo">The music to add to</param>
|
|
||||||
public void AddNewEntryBasedOnMusicInfo(MusicInfo musicInfo)
|
|
||||||
{
|
{
|
||||||
Add(musicInfo.Title, musicInfo);
|
var json = JsonConvert.SerializeObject(_InternalDictionary, Formatting.Indented);
|
||||||
|
await File.WriteAllTextAsync(_DiskLocation, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task LoadFromFile()
|
||||||
|
{
|
||||||
|
string jsonContent = await File.ReadAllTextAsync(_DiskLocation);
|
||||||
|
var jObject = JsonConvert.DeserializeObject<JObject>(jsonContent);
|
||||||
|
_InternalDictionary.Clear();
|
||||||
|
|
||||||
|
foreach (var (key,value) in jObject)
|
||||||
|
{
|
||||||
|
if (value is null || value.Type == JTokenType.Null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MusicInfo? info = value.ToObject<MusicInfo>();
|
||||||
|
if (info is null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_InternalDictionary[key] = info;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,10 +137,13 @@ public class MusicPlayer
|
|||||||
|
|
||||||
public bool Enqueue(string musicName)
|
public bool Enqueue(string musicName)
|
||||||
{
|
{
|
||||||
var minfo = Variables._MusicDatabase.GetMusicInfo(musicName);
|
var musicInfo = Variables._MusicDatabase?.Get(musicName);
|
||||||
if (minfo is null) return false;
|
if (musicInfo is null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
MusicQueue.Enqueue(minfo);
|
MusicQueue.Enqueue(musicInfo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,11 +152,6 @@ public class MusicPlayer
|
|||||||
isPlaying = false;
|
isPlaying = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetVolume(float volume)
|
|
||||||
{
|
|
||||||
// set volume
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Process? CreateStream(string? fileName, string path)
|
private static Process? CreateStream(string? fileName, string path)
|
||||||
{
|
{
|
||||||
return Process.Start(new ProcessStartInfo
|
return Process.Start(new ProcessStartInfo
|
||||||
|
|||||||
@@ -29,6 +29,13 @@ public class Play: DBSlashCommand
|
|||||||
|
|
||||||
public async void ExecuteServer(SocketSlashCommand context)
|
public async void ExecuteServer(SocketSlashCommand context)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if(Variables._MusicDatabase is null)
|
||||||
|
{
|
||||||
|
await context.RespondAsync("Music Database is not loaded !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var melodyName = context.Data.Options.First().Value as string;
|
var melodyName = context.Data.Options.First().Value as string;
|
||||||
|
|
||||||
if (melodyName is null)
|
if (melodyName is null)
|
||||||
@@ -37,8 +44,8 @@ public class Play: DBSlashCommand
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var melody = Variables._MusicDatabase.GetMusicInfo(melodyName);
|
var melody = Variables._MusicDatabase.GetMusicInfoWithTitleOrAlias(melodyName);
|
||||||
if (melody is null)
|
if (!melody.Any())
|
||||||
{
|
{
|
||||||
await context.RespondAsync("The searched melody does not exists in the database. Sorry :(");
|
await context.RespondAsync("The searched melody does not exists in the database. Sorry :(");
|
||||||
return;
|
return;
|
||||||
@@ -71,6 +78,7 @@ public class Play: DBSlashCommand
|
|||||||
await context.RespondAsync("Failed to enqueue your request. Something went wrong !");
|
await context.RespondAsync("Failed to enqueue your request. Something went wrong !");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.RespondAsync("Enqueued your request");
|
await context.RespondAsync("Enqueued your request");
|
||||||
|
|
||||||
await Variables._MusicPlayer.PlayQueue(); //start queue
|
await Variables._MusicPlayer.PlayQueue(); //start queue
|
||||||
|
|||||||
Reference in New Issue
Block a user