Removing Scratch, Adding Exception Handling to all processes.
This commit is contained in:
parent
64b6f39033
commit
ba1c3861f4
@ -11,7 +11,7 @@
|
||||
<e p="Discord" t="Include">
|
||||
<e p="DiscordConnect.cs" t="Include" />
|
||||
<e p="Modules" t="Include">
|
||||
<e p="ExampleCommand.cs" t="Include" />
|
||||
<e p="InfoCommands.cs" t="Include" />
|
||||
</e>
|
||||
<e p="Services" t="Include">
|
||||
<e p="CommandHandler.cs" t="Include" />
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
using NLog;
|
||||
using System;
|
||||
using Discord;
|
||||
using Discord.Net;
|
||||
using Discord.Commands;
|
||||
using System.Reflection;
|
||||
using Discord.WebSocket;
|
||||
using System.Threading.Tasks;
|
||||
using ChaosBot.Discord.Services;
|
||||
@ -58,19 +56,28 @@ namespace ChaosBot.Discord
|
||||
|
||||
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()
|
||||
ServiceProvider csInfo = null;
|
||||
|
||||
try
|
||||
{
|
||||
csInfo = new ServiceCollection()
|
||||
.AddSingleton(Program.Cfg)
|
||||
.AddSingleton<DiscordSocketClient>()
|
||||
.AddSingleton<CommandService>()
|
||||
.AddSingleton<CommandHandler>()
|
||||
.BuildServiceProvider();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"DiscordConnect.ConfigureServices: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||
}
|
||||
|
||||
return csInfo;
|
||||
}
|
||||
|
||||
private static Task Log(LogMessage msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (msg.Severity)
|
||||
{
|
||||
@ -96,6 +103,11 @@ namespace ChaosBot.Discord
|
||||
_logger.Trace(msg.Message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"DiscordConnect.Log: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@ -1,109 +0,0 @@
|
||||
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<string>();
|
||||
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
50
ChaosBot/Discord/Modules/InfoCommands.cs
Normal file
50
ChaosBot/Discord/Modules/InfoCommands.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using Discord;
|
||||
using System.Text;
|
||||
using Discord.Commands;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using NLog;
|
||||
|
||||
|
||||
namespace ChaosBot.Discord.Modules
|
||||
{
|
||||
public class InfoCommands : ModuleBase
|
||||
{
|
||||
private static readonly Logger _logger = Program._logger;
|
||||
|
||||
|
||||
[Command("info")]
|
||||
[Alias("version")]
|
||||
public async Task InfoCommand()
|
||||
{
|
||||
try
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var embed = new EmbedBuilder();
|
||||
|
||||
embed.WithColor(new Color(255, 255,0));
|
||||
embed.Title = $"General Information";
|
||||
sb.AppendLine($"{Context.User.Mention} has requested information from {Program.Cfg.GetValue<string>("Bot:Name")}.");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"Bot Version: {Program.Cfg.GetValue<string>("Bot:Version")}");
|
||||
sb.AppendLine($"Bot Prefix: {Program.Cfg.GetValue<string>("Discord:Prefix")}");
|
||||
|
||||
/*
|
||||
* Add the string to the Embed
|
||||
*/
|
||||
embed.Description = sb.ToString();
|
||||
|
||||
/*
|
||||
* Reply with the Embed created above
|
||||
*/
|
||||
await ReplyAsync(null, false, embed.Build());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"InfoCommands.InfoCommand: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,91 +6,91 @@ using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using NLog;
|
||||
|
||||
namespace ChaosBot.Discord.Services
|
||||
{
|
||||
public class CommandHandler
|
||||
{
|
||||
// setup fields to be set later in the constructor
|
||||
private readonly IConfiguration _config;
|
||||
private readonly CommandService _commands;
|
||||
private readonly DiscordSocketClient _client;
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly Logger _logger = Program._logger;
|
||||
|
||||
public CommandHandler(IServiceProvider services)
|
||||
{
|
||||
// juice up the fields with these services
|
||||
// since we passed the services in, we can use GetRequiredService to pass them into the fields set earlier
|
||||
try
|
||||
{
|
||||
_config = services.GetRequiredService<IConfiguration>();
|
||||
_commands = services.GetRequiredService<CommandService>();
|
||||
_client = services.GetRequiredService<DiscordSocketClient>();
|
||||
_services = services;
|
||||
|
||||
// take action when we execute a command
|
||||
_commands.CommandExecuted += CommandExecutedAsync;
|
||||
|
||||
// take action when we receive a message (so we can process it, and see if it is a valid command)
|
||||
_client.MessageReceived += MessageReceivedAsync;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"CommandHandler.CommandHandler: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
// register modules that are public and inherit ModuleBase<T>.
|
||||
await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
|
||||
}
|
||||
|
||||
// this class is where the magic starts, and takes actions upon receiving messages
|
||||
public async Task MessageReceivedAsync(SocketMessage rawMessage)
|
||||
{
|
||||
// ensures we don't process system/other bot messages
|
||||
if (!(rawMessage is SocketUserMessage message))
|
||||
try
|
||||
{
|
||||
if (!(rawMessage is SocketUserMessage message))
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.Source != MessageSource.User)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// sets the argument position away from the prefix we set
|
||||
var argPos = 0;
|
||||
|
||||
// get prefix from the configuration file
|
||||
char prefix = Char.Parse(_config["Prefix"]);
|
||||
char prefix = Char.Parse(_config["Discord:Prefix"]);
|
||||
|
||||
// determine if the message has a valid prefix, and adjust argPos based on prefix
|
||||
if (!(message.HasMentionPrefix(_client.CurrentUser, ref argPos) || message.HasCharPrefix(prefix, ref argPos)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var context = new SocketCommandContext(_client, message);
|
||||
|
||||
// execute command if one is found that matches
|
||||
await _commands.ExecuteAsync(context, argPos, _services);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"CommandHandler.MessageReceivedAsync: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CommandExecutedAsync(Optional<CommandInfo> command, ICommandContext context, IResult result)
|
||||
{
|
||||
// if a command isn't found, log that info to console and exit this method
|
||||
try
|
||||
{
|
||||
if (!command.IsSpecified)
|
||||
{
|
||||
System.Console.WriteLine($"Command failed to execute for [{context.User.Username}] <-> [{result.ErrorReason}]!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// log success to the console and exit this method
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
System.Console.WriteLine($"Command [{command.Value.Name}] executed for -> [{context.User.Username}]");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// failure scenario, let's let the user know
|
||||
await context.Channel.SendMessageAsync($"Sorry, {context.User.Username}... something went wrong -> [{result}]!");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"CommandHandler.CommandExecutedAsync: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -14,9 +14,9 @@ namespace ChaosBot
|
||||
|
||||
return LogManager.GetCurrentClassLogger();
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
Console.WriteLine($"Logging.Logger: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ namespace ChaosBot
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, $"Stopped program because of exception");
|
||||
_logger.Error(ex, $"Program.MainFunction: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user