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="Discord" t="Include">
|
||||||
<e p="DiscordConnect.cs" t="Include" />
|
<e p="DiscordConnect.cs" t="Include" />
|
||||||
<e p="Modules" t="Include">
|
<e p="Modules" t="Include">
|
||||||
<e p="ExampleCommand.cs" t="Include" />
|
<e p="InfoCommands.cs" t="Include" />
|
||||||
</e>
|
</e>
|
||||||
<e p="Services" t="Include">
|
<e p="Services" t="Include">
|
||||||
<e p="CommandHandler.cs" t="Include" />
|
<e p="CommandHandler.cs" t="Include" />
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Net;
|
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using System.Reflection;
|
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using ChaosBot.Discord.Services;
|
using ChaosBot.Discord.Services;
|
||||||
@ -58,19 +56,28 @@ namespace ChaosBot.Discord
|
|||||||
|
|
||||||
private static ServiceProvider ConfigureServices()
|
private static ServiceProvider ConfigureServices()
|
||||||
{
|
{
|
||||||
// this returns a ServiceProvider that is used later to call for those services
|
ServiceProvider csInfo = null;
|
||||||
// we can add types we have access to here, hence adding the new using statement:
|
|
||||||
// using csharpi.Services;
|
try
|
||||||
// the config we build is also added, which comes in handy for setting the command prefix!
|
{
|
||||||
return new ServiceCollection()
|
csInfo = new ServiceCollection()
|
||||||
.AddSingleton(Program.Cfg)
|
.AddSingleton(Program.Cfg)
|
||||||
.AddSingleton<DiscordSocketClient>()
|
.AddSingleton<DiscordSocketClient>()
|
||||||
.AddSingleton<CommandService>()
|
.AddSingleton<CommandService>()
|
||||||
.AddSingleton<CommandHandler>()
|
.AddSingleton<CommandHandler>()
|
||||||
.BuildServiceProvider();
|
.BuildServiceProvider();
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error($"DiscordConnect.ConfigureServices: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return csInfo;
|
||||||
|
}
|
||||||
|
|
||||||
private static Task Log(LogMessage msg)
|
private static Task Log(LogMessage msg)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
switch (msg.Severity)
|
switch (msg.Severity)
|
||||||
{
|
{
|
||||||
@ -96,6 +103,11 @@ namespace ChaosBot.Discord
|
|||||||
_logger.Trace(msg.Message);
|
_logger.Trace(msg.Message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error($"DiscordConnect.Log: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||||
|
}
|
||||||
|
|
||||||
return Task.CompletedTask;
|
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.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using NLog;
|
||||||
|
|
||||||
namespace ChaosBot.Discord.Services
|
namespace ChaosBot.Discord.Services
|
||||||
{
|
{
|
||||||
public class CommandHandler
|
public class CommandHandler
|
||||||
{
|
{
|
||||||
// setup fields to be set later in the constructor
|
|
||||||
private readonly IConfiguration _config;
|
private readonly IConfiguration _config;
|
||||||
private readonly CommandService _commands;
|
private readonly CommandService _commands;
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly IServiceProvider _services;
|
private readonly IServiceProvider _services;
|
||||||
|
private readonly Logger _logger = Program._logger;
|
||||||
|
|
||||||
public CommandHandler(IServiceProvider services)
|
public CommandHandler(IServiceProvider services)
|
||||||
{
|
{
|
||||||
// juice up the fields with these services
|
try
|
||||||
// since we passed the services in, we can use GetRequiredService to pass them into the fields set earlier
|
{
|
||||||
_config = services.GetRequiredService<IConfiguration>();
|
_config = services.GetRequiredService<IConfiguration>();
|
||||||
_commands = services.GetRequiredService<CommandService>();
|
_commands = services.GetRequiredService<CommandService>();
|
||||||
_client = services.GetRequiredService<DiscordSocketClient>();
|
_client = services.GetRequiredService<DiscordSocketClient>();
|
||||||
_services = services;
|
_services = services;
|
||||||
|
|
||||||
// take action when we execute a command
|
|
||||||
_commands.CommandExecuted += CommandExecutedAsync;
|
_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;
|
_client.MessageReceived += MessageReceivedAsync;
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error($"CommandHandler.CommandHandler: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task InitializeAsync()
|
public async Task InitializeAsync()
|
||||||
{
|
{
|
||||||
// register modules that are public and inherit ModuleBase<T>.
|
|
||||||
await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);
|
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)
|
public async Task MessageReceivedAsync(SocketMessage rawMessage)
|
||||||
{
|
{
|
||||||
// ensures we don't process system/other bot messages
|
try
|
||||||
if (!(rawMessage is SocketUserMessage message))
|
|
||||||
{
|
{
|
||||||
|
if (!(rawMessage is SocketUserMessage message))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (message.Source != MessageSource.User)
|
if (message.Source != MessageSource.User)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// sets the argument position away from the prefix we set
|
|
||||||
var argPos = 0;
|
var argPos = 0;
|
||||||
|
|
||||||
// get prefix from the configuration file
|
char prefix = Char.Parse(_config["Discord:Prefix"]);
|
||||||
char prefix = Char.Parse(_config["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)))
|
if (!(message.HasMentionPrefix(_client.CurrentUser, ref argPos) || message.HasCharPrefix(prefix, ref argPos)))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
var context = new SocketCommandContext(_client, message);
|
var context = new SocketCommandContext(_client, message);
|
||||||
|
|
||||||
// execute command if one is found that matches
|
|
||||||
await _commands.ExecuteAsync(context, argPos, _services);
|
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)
|
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)
|
if (!command.IsSpecified)
|
||||||
{
|
{
|
||||||
System.Console.WriteLine($"Command failed to execute for [{context.User.Username}] <-> [{result.ErrorReason}]!");
|
System.Console.WriteLine($"Command failed to execute for [{context.User.Username}] <-> [{result.ErrorReason}]!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// log success to the console and exit this method
|
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
{
|
{
|
||||||
System.Console.WriteLine($"Command [{command.Value.Name}] executed for -> [{context.User.Username}]");
|
System.Console.WriteLine($"Command [{command.Value.Name}] executed for -> [{context.User.Username}]");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// failure scenario, let's let the user know
|
|
||||||
await context.Channel.SendMessageAsync($"Sorry, {context.User.Username}... something went wrong -> [{result}]!");
|
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();
|
return LogManager.GetCurrentClassLogger();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine(e);
|
Console.WriteLine($"Logging.Logger: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,7 +43,7 @@ namespace ChaosBot
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
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