Skip to content

Commit

Permalink
fix some error handling, add /debug throw
Browse files Browse the repository at this point in the history
  • Loading branch information
FloatingMilkshake committed Dec 9, 2023
1 parent 255b28d commit 4e65350
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 21 deletions.
29 changes: 29 additions & 0 deletions Commands/Owner/DebugCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,34 @@ public static async Task Usage(InteractionContext ctx)

await ctx.FollowUpAsync(new DiscordFollowupMessageBuilder().WithContent(output.Trim()));
}

[SlashCommand("throw", "[Authorized users only] Intentionally throw an exception for debugging.")]
public static async Task Error(InteractionContext ctx,
[Option("exception", "The type of exception to throw.")]
[Choice("NullReferenceException", "nullref")]
[Choice("InvalidOperationException", "invalidop")]
[Choice("SlashExecutionChecksFailedException", "slashchecksfailed")]
string exceptionType)
{
string exceptionFullName = exceptionType switch
{
"nullref" => "NullReferenceException",
"invalidop" => "InvalidOperationException",
"slashchecksfailed" => "SlashExecutionChecksFailedException",
_ => throw new NotImplementedException()
};
await ctx.CreateResponseAsync(new DiscordInteractionResponseBuilder().WithContent(
$"Throwing {exceptionFullName}..."));

switch (exceptionType)
{
case "nullref":
throw new NullReferenceException("This is a test exception");
case "invalidop":
throw new InvalidOperationException("This is a test exception");
case "slashchecksfailed":
throw new SlashExecutionChecksFailedException();
}
}
}
}
71 changes: 50 additions & 21 deletions Events/ErrorEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,51 @@ public static async Task SlashCommandErrored(SlashCommandsExtension scmds, Slash
switch (e.Exception)
{
case SlashExecutionChecksFailedException execChecksFailedEx
when execChecksFailedEx.FailedChecks.OfType<SlashRequireGuildAttribute>().Any():
await e.Context.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource,
new DiscordInteractionResponseBuilder()
.WithContent(
when execChecksFailedEx.FailedChecks is not null && execChecksFailedEx.FailedChecks.OfType<SlashRequireGuildAttribute>().Any():
try
{
await e.Context.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource,
new DiscordInteractionResponseBuilder().WithContent(
$"This command cannot be used in DMs. Please use it in a server. Contact the bot owner if you need help or think I messed up (if you don't know who that is, see {SlashCmdMentionHelpers.GetSlashCmdMention("about")}!).")
.AsEphemeral());
}
catch
{
await e.Context.FollowUpAsync(new DiscordFollowupMessageBuilder().WithContent(
$"This command cannot be used in DMs. Please use it in a server. Contact the bot owner if you need help or think I messed up (if you don't know who that is, see {SlashCmdMentionHelpers.GetSlashCmdMention("about")}!).")
.AsEphemeral());
}

return;
case SlashExecutionChecksFailedException:
await e.Context.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource,
new DiscordInteractionResponseBuilder().WithContent(
try
{
await e.Context.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource,
new DiscordInteractionResponseBuilder().WithContent(
$"Hmm, it looks like one of the checks for this command failed. Make sure you and I both have the permissions required to use it, and that you're using it properly. Contact the bot owner if you need help or think I messed up (if you don't know who that is, see {SlashCmdMentionHelpers.GetSlashCmdMention("about")}!).")
.AsEphemeral());
}
catch
{
await e.Context.FollowUpAsync(new DiscordFollowupMessageBuilder().WithContent(
$"Hmm, it looks like one of the checks for this command failed. Make sure you and I both have the permissions required to use it, and that you're using it properly. Contact the bot owner if you need help or think I messed up (if you don't know who that is, see {SlashCmdMentionHelpers.GetSlashCmdMention("about")}!).")
.AsEphemeral());
}

return;
case InvalidOperationException when
e.Exception.Message == "Slash commands failed to register properly on startup.":
case NullReferenceException:
default:
{
var exception = e.Exception;

var ownerMention =
Program.Discord.CurrentApplication.Owners.Aggregate("",
(current, owner) => current + owner.Mention + "\n");

DiscordEmbedBuilder embed = new()
{
Title = "Slash commands failed to register",
Title = "An exception was thrown when executing a slash command",
Description =
$"Slash commands failed to register on bot startup and {e.Context.User.Mention}'s usage of `/{e.Context.CommandName}` failed. Please restart the bot. Details are below.",
$"An exception was thrown when {e.Context.User.Mention} used `/{e.Context.CommandName}`. Details are below.",
Color = DiscordColor.Red
};
embed.AddField("Exception Details",
$"{exception.GetType()}: {exception.Message}\n```\n{exception.StackTrace}\n```");
$"```{exception.GetType()}: {exception.Message}:\n{exception.StackTrace}\n```");

try
{
Expand All @@ -49,18 +62,33 @@ await e.Context.CreateResponseAsync(new DiscordInteractionResponseBuilder()
.WithContent(
"It looks like slash commands are having issues! Sorry for the inconvenience. Bot owners have been alerted.")
.AsEphemeral());
await Program.HomeChannel.SendMessageAsync(ownerMention, embed);
await Program.HomeChannel.SendMessageAsync(embed);
return;
}
}
catch
{
// /proc/self/cgroup could not be found, which means the bot is not running in Docker.
await e.Context.CreateResponseAsync(new DiscordInteractionResponseBuilder()

// Try to respond to the interaction
try
{
await e.Context.CreateResponseAsync(new DiscordInteractionResponseBuilder()
.WithContent(
"It looks like slash commands are having issues! Sorry for the inconvenience. Bot owners have been alerted.")
.AsEphemeral());
await Program.HomeChannel.SendMessageAsync(ownerMention, embed);
}
catch (BadRequestException)
{
// If the interaction was deferred, CreateResponseAsync() won't work
// Try using FollowUpAsync() instead
await e.Context.FollowUpAsync(new DiscordFollowupMessageBuilder()
.WithContent(
"It looks like slash commands are having issues! Sorry for the inconvenience. Bot owners have been alerted.")
.AsEphemeral());
}

await Program.HomeChannel.SendMessageAsync(embed);
return;
}

Expand All @@ -71,8 +99,9 @@ await e.Context.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSo
.AsEphemeral());

embed.Description =
$"Slash commands failed to register on bot startup and {e.Context.User.Mention}'s usage of `/{e.Context.CommandName}` failed. **The bot is attempting to restart automatically.** Details are below.";
await Program.HomeChannel.SendMessageAsync(ownerMention, embed);
$"An exception was thrown when {e.Context.User.Mention} used `/{e.Context.CommandName}`."
+ " Details are below. The bot is restarting to attempt to fix this in case it was caused by a failure to register commands.";
await Program.HomeChannel.SendMessageAsync(embed);

Environment.Exit(1);
break;
Expand Down

0 comments on commit 4e65350

Please sign in to comment.