From 64b6f39033478dcd20eb70bf58f7481ca24db32d Mon Sep 17 00:00:00 2001 From: Sean Stoves Date: Tue, 2 Jun 2020 21:35:21 -0400 Subject: [PATCH] Adding CommandHandler --- .idea/.idea.ChaosBot/.idea/contentModel.xml | 3 + ChaosBot/Discord/DiscordConnect.cs | 64 +++++++++--- ChaosBot/Discord/Modules/ExampleCommand.cs | 109 ++++++++++++++++++++ ChaosBot/Program.cs | 13 +-- ChaosBot/appsettings.json | 3 +- 5 files changed, 166 insertions(+), 26 deletions(-) create mode 100644 ChaosBot/Discord/Modules/ExampleCommand.cs diff --git a/.idea/.idea.ChaosBot/.idea/contentModel.xml b/.idea/.idea.ChaosBot/.idea/contentModel.xml index d678b00..192f79c 100644 --- a/.idea/.idea.ChaosBot/.idea/contentModel.xml +++ b/.idea/.idea.ChaosBot/.idea/contentModel.xml @@ -10,6 +10,9 @@ + + + diff --git a/ChaosBot/Discord/DiscordConnect.cs b/ChaosBot/Discord/DiscordConnect.cs index 06d1de6..301a003 100644 --- a/ChaosBot/Discord/DiscordConnect.cs +++ b/ChaosBot/Discord/DiscordConnect.cs @@ -1,11 +1,14 @@ using NLog; using System; -using System.Reflection; using Discord; +using Discord.Net; +using Discord.Commands; +using System.Reflection; using Discord.WebSocket; using System.Threading.Tasks; -using Discord.Commands; +using ChaosBot.Discord.Services; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; namespace ChaosBot.Discord @@ -15,31 +18,58 @@ namespace ChaosBot.Discord private static DiscordSocketClient _client; private static Logger _logger = Program._logger; - public static async Task Connect() + public static async Task StartUp() { try { - /* - * Perform Connection - */ - _client = new DiscordSocketClient(); - _client.Log += Log; - - await _client.LoginAsync(TokenType.Bot, Program.Cfg.GetValue("Discord:Token")); - await _client.StartAsync(); - - /* - * Let's keep the Task open and happy. - */ - await Task.Delay(-1); + using (var services = ConfigureServices()) + { + // get the client and assign to client + // you get the services via GetRequiredService + var client = services.GetRequiredService(); + _client = client; + // setup logging and the ready event + client.Log += Log; + client.Ready += ReadyAsync; + services.GetRequiredService().Log += Log; + + // this is where we get the Token value from the configuration file, and start the bot + await client.LoginAsync(TokenType.Bot, Program.Cfg.GetValue("Discord:Token")); + await client.StartAsync(); + + // we get the CommandHandler class here and call the InitializeAsync method to start things up for the CommandHandler service + await services.GetRequiredService().InitializeAsync(); + + await Task.Delay(-1); + } } catch (Exception ex) { - _logger.Error($"dBot.Connect: Exception [{ex}] thrown, <[{ex.Message}]>."); + _logger.Error($"DiscordConnect.StartUp: Exception [{ex}] thrown, <[{ex.Message}]>."); } } + private static Task ReadyAsync() + { + _logger.Info($"Connected as -> [{_client.CurrentUser}] :)"); + return Task.CompletedTask; + } + + private static ServiceProvider ConfigureServices() + { + // this returns a ServiceProvider that is used later to call for those services + // we can add types we have access to here, hence adding the new using statement: + // using csharpi.Services; + // the config we build is also added, which comes in handy for setting the command prefix! + return new ServiceCollection() + .AddSingleton(Program.Cfg) + .AddSingleton() + .AddSingleton() + .AddSingleton() + .BuildServiceProvider(); + } + private static Task Log(LogMessage msg) { switch (msg.Severity) diff --git a/ChaosBot/Discord/Modules/ExampleCommand.cs b/ChaosBot/Discord/Modules/ExampleCommand.cs new file mode 100644 index 0000000..af835f2 --- /dev/null +++ b/ChaosBot/Discord/Modules/ExampleCommand.cs @@ -0,0 +1,109 @@ +using System; +using Discord; +using System.Text; +using Discord.Commands; +using System.Threading.Tasks; +using System.Collections.Generic; + + +namespace ChaosBot.Discord.Modules +{ + // for commands to be available, and have the Context passed to them, we must inherit ModuleBase + public class ExampleCommands : ModuleBase + { + [Command("hello")] + public async Task HelloCommand() + { + // initialize empty string builder for reply + var sb = new StringBuilder(); + + // get user info from the Context + var user = Context.User; + + // build out the reply + sb.AppendLine($"You are -> [{user.Username}]"); + sb.AppendLine("I must now say, World!"); + + // send simple string reply + await ReplyAsync(sb.ToString()); + } + + [Command("8ball")] + [Alias("ask")] + [RequireUserPermission(GuildPermission.KickMembers)] + public async Task AskEightBall([Remainder]string args = null) + { + // I like using StringBuilder to build out the reply + var sb = new StringBuilder(); + // let's use an embed for this one! + var embed = new EmbedBuilder(); + + // now to create a list of possible replies + var replies = new List(); + + // add our possible replies + replies.Add("yes"); + replies.Add("no"); + replies.Add("maybe"); + replies.Add("hazzzzy...."); + + // time to add some options to the embed (like color and title) + embed.WithColor(new Color(0, 255,0)); + embed.Title = "Welcome to the 8-ball!"; + + // we can get lots of information from the Context that is passed into the commands + // here I'm setting up the preface with the user's name and a comma + sb.AppendLine($"{Context.User.Username},"); + sb.AppendLine(); + + // let's make sure the supplied question isn't null + if (args == null) + { + // if no question is asked (args are null), reply with the below text + sb.AppendLine("Sorry, can't answer a question you didn't ask!"); + } + else + { + // if we have a question, let's give an answer! + // get a random number to index our list with (arrays start at zero so we subtract 1 from the count) + var answer = replies[new Random().Next(replies.Count - 1)]; + + // build out our reply with the handy StringBuilder + sb.AppendLine($"You asked: [**{args}**]..."); + sb.AppendLine(); + sb.AppendLine($"...your answer is [**{answer}**]"); + + // bonus - let's switch out the reply and change the color based on it + switch (answer) + { + case "yes": + { + embed.WithColor(new Color(0, 255, 0)); + break; + } + case "no": + { + embed.WithColor(new Color(255, 0, 0)); + break; + } + case "maybe": + { + embed.WithColor(new Color(255,255,0)); + break; + } + case "hazzzzy....": + { + embed.WithColor(new Color(255,0,255)); + break; + } + } + } + + // now we can assign the description of the embed to the contents of the StringBuilder we created + embed.Description = sb.ToString(); + + // this will reply with the embed + await ReplyAsync(null, false, embed.Build()); + } + } +} \ No newline at end of file diff --git a/ChaosBot/Program.cs b/ChaosBot/Program.cs index f5f6a61..6c86185 100644 --- a/ChaosBot/Program.cs +++ b/ChaosBot/Program.cs @@ -1,9 +1,7 @@ using NLog; using System; -using Discord; -using Discord.WebSocket; -using System.Threading.Tasks; using ChaosBot.Discord; +using System.Threading.Tasks; using Microsoft.Extensions.Configuration; @@ -13,8 +11,8 @@ namespace ChaosBot { public static IConfiguration Cfg { get; set; } public static Logger _logger; - - public static void Main(string[] args) + + private static void Main(string[] args) { new Program().MainFunction().GetAwaiter().GetResult(); } @@ -40,9 +38,8 @@ namespace ChaosBot */ _logger.Info($"Starting Up {Cfg.GetValue("Bot:Name")} v{Cfg.GetValue("Bot:Version")}"); - - var DiscordBot = DiscordConnect.Connect(); - await DiscordBot; + var discordBot = DiscordConnect.StartUp(); + await discordBot; } catch (Exception ex) { diff --git a/ChaosBot/appsettings.json b/ChaosBot/appsettings.json index b9f31ee..d74e236 100644 --- a/ChaosBot/appsettings.json +++ b/ChaosBot/appsettings.json @@ -6,7 +6,8 @@ "Discord": { "Secret": "TPtJeNzPXPM0vptm3igbh8_G3KEfbPdA", "ClientID": "717523478890414090", - "Token": "NzE3NTIzNDc4ODkwNDE0MDkw.XtbkDw.RpsISqttv27m2Pknq3c5nEVvXWg" + "Token": "NzE3NTIzNDc4ODkwNDE0MDkw.XtbkDw.RpsISqttv27m2Pknq3c5nEVvXWg", + "Prefix": "!" }, "NLog": { "internalLogLevel": "Info",