Skip to content

Commit 76f0d95

Browse files
authored
Improve error handling (#130)
1 parent 87aa62a commit 76f0d95

File tree

9 files changed

+85
-79
lines changed

9 files changed

+85
-79
lines changed

bot/cogs/config.py

+21-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from libs.tickets.utils import get_cached_thread
2020
from libs.utils import GuildContext
2121
from libs.utils.checks import bot_check_permissions, check_permissions
22-
from libs.utils.embeds import Embed
22+
from libs.utils.embeds import CooldownEmbed, Embed
2323
from libs.utils.pages import SimplePages
2424
from libs.utils.prefix import get_prefix
2525

@@ -242,6 +242,14 @@ async def get_block_ticket(
242242

243243
return BlocklistTicket(cog=tickets_cog, thread=cached_ticket.thread)
244244

245+
### Misc Utilities
246+
async def _handle_error(
247+
self, ctx: GuildContext, error: commands.CommandError
248+
) -> None:
249+
if isinstance(error, commands.CommandOnCooldown):
250+
embed = CooldownEmbed(error.retry_after)
251+
await ctx.send(embed=embed)
252+
245253
@check_permissions(manage_guild=True)
246254
@bot_check_permissions(manage_channels=True, manage_webhooks=True)
247255
@commands.guild_only()
@@ -463,6 +471,18 @@ async def delete(self, ctx: GuildContext) -> None:
463471
else:
464472
await ctx.send("Cancelling.")
465473

474+
@setup.error
475+
async def on_setup_error(
476+
self, ctx: GuildContext, error: commands.CommandError
477+
) -> None:
478+
await self._handle_error(ctx, error)
479+
480+
@delete.error
481+
async def on_delete_error(
482+
self, ctx: GuildContext, error: commands.CommandError
483+
) -> None:
484+
await self._handle_error(ctx, error)
485+
466486
@check_permissions(manage_guild=True)
467487
@commands.guild_only()
468488
@config.group(name="prefix", fallback="info")

bot/cogs/tickets.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
safe_content,
1515
)
1616
from libs.utils.checks import bot_check_permissions
17-
from libs.utils.embeds import Embed, LoggingEmbed
17+
from libs.utils.embeds import CooldownEmbed, Embed, LoggingEmbed
1818

1919
from .config import GuildWebhookDispatcher
2020

@@ -526,6 +526,14 @@ async def on_ticket_close(
526526
embed.add_field(name="Link", value=ticket.mention)
527527
await webhook.send(embed=embed)
528528

529+
@reply.error
530+
async def on_reply_error(
531+
self, ctx: GuildContext, error: commands.CommandError
532+
) -> None:
533+
if isinstance(error, commands.CommandOnCooldown):
534+
embed = CooldownEmbed(error.retry_after)
535+
await ctx.send(embed=embed)
536+
529537

530538
async def setup(bot: Rodhaj) -> None:
531539
await bot.add_cog(Tickets(bot))

bot/libs/utils/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
ErrorEmbed as ErrorEmbed,
1212
LoggingEmbed as LoggingEmbed,
1313
)
14-
from .errors import send_error_embed as send_error_embed
1514
from .handler import KeyboardInterruptHandler as KeyboardInterruptHandler
1615
from .help import RodhajHelp as RodhajHelp
1716
from .logger import RodhajLogger as RodhajLogger

bot/libs/utils/embeds.py

+30
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import traceback
2+
13
import discord
24

35

@@ -23,3 +25,31 @@ def __init__(self, **kwargs):
2325
"Uh oh! It seems like the command ran into an issue! For support, ask the dev team",
2426
)
2527
super().__init__(**kwargs)
28+
29+
30+
class FullErrorEmbed(ErrorEmbed):
31+
def __init__(self, error: Exception, **kwargs):
32+
kwargs.setdefault("description", self._format_description(error))
33+
super().__init__(**kwargs)
34+
35+
def _format_description(self, error: Exception) -> str:
36+
error_traceback = "\n".join(traceback.format_exception_only(type(error), error))
37+
desc = f"""
38+
Uh oh! It seems like there was an issue. Ask the devs for help.
39+
40+
**Error**:
41+
```{error_traceback}```
42+
"""
43+
return desc
44+
45+
46+
class CooldownEmbed(discord.Embed):
47+
def __init__(self, retry_after: float, **kwargs):
48+
kwargs.setdefault("color", discord.Color.from_rgb(214, 6, 6))
49+
kwargs.setdefault("timestamp", discord.utils.utcnow())
50+
kwargs.setdefault("title", "Command On Cooldown")
51+
kwargs.setdefault(
52+
"description",
53+
f"This command is on cooldown. Try again in {retry_after:.2f}s",
54+
)
55+
super().__init__(**kwargs)

bot/libs/utils/errors.py

-61
This file was deleted.

bot/libs/utils/modals.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import discord
44

55
from .context import RoboContext
6-
from .errors import produce_error_embed
6+
from .embeds import FullErrorEmbed
77

88
NO_CONTROL_MSG = "This modal cannot be controlled by you, sorry!"
99

@@ -28,6 +28,6 @@ async def on_error(
2828
self, interaction: discord.Interaction, error: Exception, /
2929
) -> None:
3030
await interaction.response.send_message(
31-
embed=produce_error_embed(error), ephemeral=True
31+
embed=FullErrorEmbed(error), ephemeral=True
3232
)
3333
self.stop()

bot/libs/utils/tree.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import discord
66
from discord import app_commands
77

8-
from .errors import produce_error_embed
8+
from .embeds import FullErrorEmbed
99

1010
if TYPE_CHECKING:
1111
from rodhaj import Rodhaj
@@ -25,4 +25,4 @@ async def interaction_check(self, interaction: discord.Interaction, /) -> bool:
2525
async def on_error(
2626
self, interaction: discord.Interaction, error: app_commands.AppCommandError
2727
) -> None:
28-
await interaction.response.send_message(embed=produce_error_embed(error))
28+
await interaction.response.send_message(embed=FullErrorEmbed(error))

bot/libs/utils/views.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
import discord
66

7-
from .embeds import ErrorEmbed
8-
from .errors import produce_error_embed
7+
from .embeds import ErrorEmbed, FullErrorEmbed
98

109
if TYPE_CHECKING:
1110
from .context import RoboContext
@@ -38,7 +37,7 @@ async def on_error(
3837
/,
3938
) -> None:
4039
await interaction.response.send_message(
41-
embed=produce_error_embed(error), ephemeral=True
40+
embed=FullErrorEmbed(error), ephemeral=True
4241
)
4342
self.stop()
4443

bot/rodhaj.py

+19-8
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,14 @@
1414
from libs.tickets.structs import PartialConfig, ReservedTags, StatusChecklist
1515
from libs.tickets.utils import get_cached_thread, get_partial_ticket
1616
from libs.tickets.views import TicketConfirmView
17-
from libs.utils import (
18-
RoboContext,
19-
RodhajCommandTree,
20-
RodhajHelp,
21-
send_error_embed,
22-
)
17+
from libs.utils import RoboContext, RodhajCommandTree, RodhajHelp
2318
from libs.utils.config import RodhajConfig
2419
from libs.utils.prefix import get_prefix
2520
from libs.utils.reloader import Reloader
2621

2722
if TYPE_CHECKING:
2823
from cogs.tickets import Tickets
24+
from libs.utils.context import RoboContext
2925

3026

3127
class Rodhaj(commands.Bot):
@@ -89,9 +85,24 @@ async def get_context(
8985
return await super().get_context(origin, cls=cls)
9086

9187
async def on_command_error(
92-
self, ctx: commands.Context, error: commands.CommandError
88+
self, ctx: RoboContext, error: commands.CommandError
9389
) -> None:
94-
await send_error_embed(ctx, error)
90+
if self._dev_mode:
91+
self.logger.exception("Ignoring exception:", exc_info=error)
92+
return
93+
94+
if isinstance(error, commands.NoPrivateMessage):
95+
await ctx.author.send("This command cannot be used in private messages")
96+
elif isinstance(error, commands.MissingRequiredArgument):
97+
await ctx.send(
98+
f"You are missing the following argument(s): {error.param.name}"
99+
)
100+
elif isinstance(error, commands.CommandInvokeError):
101+
original = error.original
102+
if not isinstance(original, discord.HTTPException):
103+
self.logger.exception("In %s:", ctx.command.qualified_name, exc_info=original) # type: ignore
104+
elif isinstance(error, commands.BadArgument):
105+
await ctx.send(str(error))
95106

96107
### Ticket processing and handling
97108

0 commit comments

Comments
 (0)