From 81fb4afbf4b65210ec6e59445dc81ad880fc06e6 Mon Sep 17 00:00:00 2001 From: CloudTheWolf Date: Sat, 22 Oct 2022 19:23:01 +0100 Subject: [PATCH] Now supports Sharding! --- ...harpPlus.Scaffolding.Example.Module.csproj | 7 +- .../Example.cs | 9 +- .../Bot.cs | 3 +- ...eWolf.DSharpPlus.Scaffolding.Worker.csproj | 2 +- .../Options.cs | 5 + .../Services/PluginLoader.cs | 68 +++++++++- .../ShardBot.cs | 120 ++++++++++++++++++ .../Worker.cs | 16 ++- 8 files changed, 215 insertions(+), 15 deletions(-) create mode 100644 CloudTheWolf.DSharpPlus.Scaffolding.Worker/ShardBot.cs diff --git a/CloudTheWolf.DSharpPlus.Scaffolding.Example.Module/CloudTheWolf.DSharpPlus.Scaffolding.Example.Module.csproj b/CloudTheWolf.DSharpPlus.Scaffolding.Example.Module/CloudTheWolf.DSharpPlus.Scaffolding.Example.Module.csproj index 9030e7c..b4bf412 100644 --- a/CloudTheWolf.DSharpPlus.Scaffolding.Example.Module/CloudTheWolf.DSharpPlus.Scaffolding.Example.Module.csproj +++ b/CloudTheWolf.DSharpPlus.Scaffolding.Example.Module/CloudTheWolf.DSharpPlus.Scaffolding.Example.Module.csproj @@ -7,8 +7,13 @@ bin\ + + C:\Users\MichaelHoward\Documents\GitHub\CloudTheWolf.DSharpPlus.Scaffolding\CloudTheWolf.DSharpPlus.Scaffolding.Worker\bin\Debug\Plugins + AnyCPU + + - + diff --git a/CloudTheWolf.DSharpPlus.Scaffolding.Example.Module/Example.cs b/CloudTheWolf.DSharpPlus.Scaffolding.Example.Module/Example.cs index 762ff4a..a7a53d5 100644 --- a/CloudTheWolf.DSharpPlus.Scaffolding.Example.Module/Example.cs +++ b/CloudTheWolf.DSharpPlus.Scaffolding.Example.Module/Example.cs @@ -6,10 +6,12 @@ using Microsoft.Extensions.Logging; using System; using CloudTheWolf.DSharpPlus.Scaffolding.Example.Module.ApplicationCommands; +using DSharpPlus.CommandsNext; +using DSharpPlus.SlashCommands; namespace CloudTheWolf.DSharpPlus.Scaffolding.Example.Module { - public class Example : IPlugin + public class Example : IShardPlugin { public string Name => "Example Plugin"; @@ -19,7 +21,7 @@ public class Example : IPlugin public static ILogger Logger; - public void InitPlugin(IBot bot, ILogger logger, DiscordConfiguration discordConfiguration, IConfigurationRoot applicationConfig) + public void InitPlugin(IShardBot bot, ILogger logger, DiscordConfiguration discordConfiguration, IConfigurationRoot applicationConfig) { Logger = logger; LoadConfig(applicationConfig); @@ -28,12 +30,11 @@ public void InitPlugin(IBot bot, ILogger logger, DiscordConfiguration di } - private void RegisterCommands(IBot bot) + private void RegisterCommands(IShardBot bot) { bot.SlashCommandsExt.RegisterCommands(); bot.Commands.RegisterCommands(); Logger.LogInformation($"{Name}: Registered {nameof(ExampleCommands)}!"); - } private void LoadConfig(IConfigurationRoot applicationConfig) diff --git a/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Bot.cs b/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Bot.cs index 8545436..5578a7d 100644 --- a/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Bot.cs +++ b/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Bot.cs @@ -15,12 +15,11 @@ using System.Threading; using System.Threading.Tasks; using DSharpPlus.SlashCommands; -using Emzi0767.Utilities; using Microsoft.Extensions.Configuration; namespace CloudTheWolf.DSharpPlus.Scaffolding.Worker { - class Bot : IBot + internal class Bot : IBot { public DiscordClient Client { get; set; } public VoiceNextExtension Voice { get; set; } diff --git a/CloudTheWolf.DSharpPlus.Scaffolding.Worker/CloudTheWolf.DSharpPlus.Scaffolding.Worker.csproj b/CloudTheWolf.DSharpPlus.Scaffolding.Worker/CloudTheWolf.DSharpPlus.Scaffolding.Worker.csproj index 5b46650..03286ae 100644 --- a/CloudTheWolf.DSharpPlus.Scaffolding.Worker/CloudTheWolf.DSharpPlus.Scaffolding.Worker.csproj +++ b/CloudTheWolf.DSharpPlus.Scaffolding.Worker/CloudTheWolf.DSharpPlus.Scaffolding.Worker.csproj @@ -20,7 +20,7 @@ - + diff --git a/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Options.cs b/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Options.cs index 8c8760a..ed925c7 100644 --- a/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Options.cs +++ b/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Options.cs @@ -9,6 +9,11 @@ namespace CloudTheWolf.DSharpPlus.Scaffolding.Worker { public class Options { + /// + /// Set if the bot uses Sharding + /// + public static bool ShardMode { get; set; } + /// /// Prefix for commands /// diff --git a/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Services/PluginLoader.cs b/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Services/PluginLoader.cs index c64dd98..7513a15 100644 --- a/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Services/PluginLoader.cs +++ b/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Services/PluginLoader.cs @@ -10,6 +10,7 @@ namespace CloudTheWolf.DSharpPlus.Scaffolding.Worker.Services public class PluginLoader { public List Plugins { get; set; } + public List ShardPlugins { get; set; } public void LoadPlugins() { @@ -20,11 +21,15 @@ public void LoadPlugins() //Load the DLLs from the Plugins directory if (Directory.Exists(Constants.PluginsFolder)) { - var files = Directory.GetFiles(Constants.PluginsFolder); - foreach (var file in files) + var dirs = Directory.GetDirectories(Constants.PluginsFolder); + foreach (var dir in dirs) { - if (file.EndsWith("dll")) - Assembly.LoadFrom(Path.GetFullPath(file)); + var files = Directory.GetFiles(dir); + foreach (var file in files) + { + if (file.EndsWith("dll")) + Assembly.LoadFrom(Path.GetFullPath(file)); + } } } @@ -66,5 +71,60 @@ public void LoadPlugins() } } + public void LoadShardPlugins() + { + try + { + ShardPlugins = new List(); + + //Load the DLLs from the Plugins directory + if (Directory.Exists(Constants.PluginsFolder)) + { + var files = Directory.GetFiles(Constants.PluginsFolder); + foreach (var file in files) + { + if (file.EndsWith("dll")) + Assembly.LoadFrom(Path.GetFullPath(file)); + } + } + + var interfaceType = typeof(IShardPlugin); + //Fetch all types that implement the interface IPlugin and are a class + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + var ts = new List(); + var tsLikePlugin = new List(); + + foreach (var assembly in assemblies) + { + var item = assembly.GetTypes(); + ts.Add(item.FirstOrDefault()); + } + + foreach (var type in ts) + { + if (interfaceType.IsAssignableFrom(type)) + { + if (type.IsClass) + { + tsLikePlugin.Add(type); + } + } + } + + var types = tsLikePlugin.ToArray(); + + //Create a new instance of all found types + foreach (var type in types) + { + ShardPlugins.Add((IShardPlugin)Activator.CreateInstance(type)); + } + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + } + } } diff --git a/CloudTheWolf.DSharpPlus.Scaffolding.Worker/ShardBot.cs b/CloudTheWolf.DSharpPlus.Scaffolding.Worker/ShardBot.cs new file mode 100644 index 0000000..6e69814 --- /dev/null +++ b/CloudTheWolf.DSharpPlus.Scaffolding.Worker/ShardBot.cs @@ -0,0 +1,120 @@ +using CloudTheWolf.DSharpPlus.Scaffolding.Logging; +using CloudTheWolf.DSharpPlus.Scaffolding.Shared.Interfaces; +using CloudTheWolf.DSharpPlus.Scaffolding.Worker.Services; +using DSharpPlus; +using DSharpPlus.CommandsNext; +using DSharpPlus.EventArgs; +using DSharpPlus.Interactivity; +using DSharpPlus.Interactivity.Extensions; +using DSharpPlus.Lavalink; +using DSharpPlus.VoiceNext; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using DSharpPlus.SlashCommands; +using Emzi0767.Utilities; +using Microsoft.Extensions.Configuration; + +namespace CloudTheWolf.DSharpPlus.Scaffolding.Worker +{ + internal class ShardBot : IShardBot + { + public DiscordShardedClient Client { get; set; } + public IReadOnlyDictionary Voice { get; set; } + public DiscordRestClient Rest { get; set; } + public IReadOnlyDictionary Commands { get; set; } + public IReadOnlyDictionary Interactivity { get; set; } + public IReadOnlyDictionary LavalinkConfig { get; set; } + public IReadOnlyDictionary SlashCommandsExt { get; set; } + + + private static DiscordConfiguration _config; + private static dynamic _myConfig; + private static readonly PluginLoader PluginLoader = new PluginLoader(); + + public static ILogger Logger; + + public async Task RunAsync(CancellationToken stoppingToken, ILogger logger) + { + Logger = logger; + Logger.LogInformation("Bot Starting!"); + LoadConfig(); + SetDiscordConfig(); + CreateDiscordClient(); + CreateClientCommandConfiguration(); + InitPlugins(); + await Client.StartAsync(); + await Task.Delay(-1, stoppingToken); + } + + private void InitPlugins() + { + PluginLoader.LoadShardPlugins(); + + foreach (var plugin in PluginLoader.ShardPlugins) + { + plugin.InitPlugin(this, Logger, _config, Program.configuration); + } + } + + private static void LoadConfig() + { + Options.Token = Program.configuration.GetValue("Discord:token"); + Options.Prefix = new string[] { Program.configuration.GetValue("Discord:prefix") }; + Options.EnableDms = Program.configuration.GetValue("Discord:enableDms"); + Options.EnableMentionPrefix = Program.configuration.GetValue("Discord:enableMentionPrefix"); + Options.DmHelp = Program.configuration.GetValue("Discord:dmHelp"); + Options.DefaultHelp = Program.configuration.GetValue("Discord:enableDefaultHelp"); + + } + + + private void CreateClientCommandConfiguration() + { + var commandsConfig = new CommandsNextConfiguration + { + StringPrefixes = Options.Prefix, + EnableDms = Options.EnableDms, + EnableMentionPrefix = Options.EnableMentionPrefix, + DmHelp = Options.DmHelp, + EnableDefaultHelp = Options.DefaultHelp + }; + + + Commands = Client.UseCommandsNextAsync(commandsConfig).Result; + } + + private void CreateDiscordClient() + { + Client = new DiscordShardedClient(_config); + Interactivity = Client.GetInteractivityAsync().Result; + Client.Ready += OnClientReady; + SlashCommandsExt = Client.UseSlashCommandsAsync().Result; + + } + + private static void SetDiscordConfig() + { + _config = new DiscordConfiguration + { + Token = Options.Token, + TokenType = TokenType.Bot, + AutoReconnect = true, + Intents = DiscordIntents.All, + LoggerFactory = Logging.Logger.LoggerFactory, + + }; + } + + private static Task OnClientReady(DiscordClient sender, ReadyEventArgs readyEventArgs) + { + Logger.LogInformation($"Bot Ready!"); + + return Task.CompletedTask; + } + } +} diff --git a/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Worker.cs b/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Worker.cs index 6116206..b762b88 100644 --- a/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Worker.cs +++ b/CloudTheWolf.DSharpPlus.Scaffolding.Worker/Worker.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using System; +using Microsoft.Extensions.Configuration; namespace CloudTheWolf.DSharpPlus.Scaffolding.Worker { @@ -21,9 +22,18 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) while (!stoppingToken.IsCancellationRequested) { _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); - var bot = new Bot(); - await bot.RunAsync(stoppingToken, _logger); - await Task.Delay(-1, stoppingToken); + if(Program.configuration.GetValue("ShardMode")) + { + var bot = new ShardBot(); + await bot.RunAsync(stoppingToken, _logger); + await Task.Delay(-1, stoppingToken); + } + else + { + var bot = new Bot(); + await bot.RunAsync(stoppingToken, _logger); + await Task.Delay(-1, stoppingToken); + } } } }