1
Fork 0
mirror of https://github.com/wlinator/luminara.git synced 2024-10-02 18:23:12 +00:00

Working error handler and xkcd commands

This commit is contained in:
wlinator 2024-08-28 08:59:54 -04:00
parent 47e7d7ad71
commit 24b84c11f2
5 changed files with 177 additions and 7 deletions

140
handlers/error.py Normal file
View file

@ -0,0 +1,140 @@
import sys
import traceback
from discord.ext import commands
from discord.ext.commands import Cog
from loguru import logger
from lib.const import CONST
from ui.embeds import builder
from lib import exceptions as LumiExceptions
async def handle_error(
ctx: commands.Context[commands.Bot],
error: commands.CommandError | commands.CheckFailure,
) -> None:
if isinstance(error, (commands.CommandNotFound, LumiExceptions.Blacklisted)):
return
author_text = None
description = None
footer_text = None
ephemeral = False
if isinstance(error, commands.MissingRequiredArgument):
author_text = CONST.STRINGS["error_bad_argument_author"]
description = CONST.STRINGS["error_bad_argument_description"].format(str(error))
elif isinstance(error, commands.BadArgument):
author_text = CONST.STRINGS["error_bad_argument_author"]
description = CONST.STRINGS["error_bad_argument_description"].format(str(error))
elif isinstance(error, commands.BotMissingPermissions):
author_text = CONST.STRINGS["error_bot_missing_permissions_author"]
description = CONST.STRINGS["error_bot_missing_permissions_description"]
elif isinstance(error, commands.CommandOnCooldown):
author_text = CONST.STRINGS["error_command_cooldown_author"]
description = CONST.STRINGS["error_command_cooldown_description"].format(
int(error.retry_after // 60),
int(error.retry_after % 60),
)
ephemeral = True
elif isinstance(error, commands.MissingPermissions):
author_text = CONST.STRINGS["error_missing_permissions_author"]
description = CONST.STRINGS["error_missing_permissions_description"]
elif isinstance(error, commands.NoPrivateMessage):
author_text = CONST.STRINGS["error_no_private_message_author"]
description = CONST.STRINGS["error_no_private_message_description"]
elif isinstance(error, commands.NotOwner):
author_text = CONST.STRINGS["error_not_owner_author"]
description = CONST.STRINGS["error_not_owner_description"]
elif isinstance(error, commands.PrivateMessageOnly):
author_text = CONST.STRINGS["error_private_message_only_author"]
description = CONST.STRINGS["error_private_message_only_description"]
elif isinstance(error, LumiExceptions.BirthdaysDisabled):
author_text = CONST.STRINGS["error_birthdays_disabled_author"]
description = CONST.STRINGS["error_birthdays_disabled_description"]
footer_text = CONST.STRINGS["error_birthdays_disabled_footer"]
elif isinstance(error, LumiExceptions.LumiException):
author_text = CONST.STRINGS["error_lumi_exception_author"]
description = CONST.STRINGS["error_lumi_exception_description"].format(
str(error),
)
else:
author_text = CONST.STRINGS["error_unknown_error_author"]
description = CONST.STRINGS["error_unknown_error_description"]
await ctx.send(
embed=builder.create_error_embed(
ctx,
author_text=author_text,
description=description,
footer_text=footer_text,
),
ephemeral=ephemeral,
)
async def on_error(event: str, *args, **kwargs) -> None:
logger.exception(
f"on_error INFO: errors.event.{event} | '*args': {args} | '**kwargs': {kwargs}",
)
logger.exception(f"on_error EXCEPTION: {sys.exc_info()}")
traceback.print_exc()
class ErrorHandler(Cog):
def __init__(self, bot: commands.Bot) -> None:
self.bot = bot
@staticmethod
async def log_command_error(ctx, error, command_type):
log_msg = (
f"{ctx.author.name} executed {command_type}{ctx.command.qualified_name}"
)
log_msg += " in DMs" if ctx.guild is None else f" | guild: {ctx.guild.name} "
logger.exception(f"{log_msg} | FAILED: {error}")
@Cog.listener()
async def on_command_error(
self,
ctx: commands.Context[commands.Bot],
error: commands.CommandError | commands.CheckFailure,
) -> None:
try:
await handle_error(ctx, error)
await self.log_command_error(ctx, error, ".")
except Exception as e:
logger.exception(f"Error in on_command_error: {e}")
traceback.print_exc()
@Cog.listener()
async def on_app_command_error(
self,
ctx: commands.Context[commands.Bot],
error: commands.CommandError | commands.CheckFailure,
) -> None:
try:
await handle_error(ctx, error)
await self.log_command_error(ctx, error, "/")
except Exception as e:
logger.exception(f"Error in on_app_command_error: {e}")
traceback.print_exc()
@Cog.listener()
async def on_error(self, event: str, *args, **kwargs) -> None:
await on_error(event, *args, **kwargs)
async def setup(bot: commands.Bot) -> None:
await bot.add_cog(ErrorHandler(bot))

31
lib/exceptions.py Normal file
View file

@ -0,0 +1,31 @@
from discord.ext import commands
from lib.const import CONST
class BirthdaysDisabled(commands.CheckFailure):
"""
Raised when the birthdays module is disabled in ctx.guild.
"""
pass
class LumiException(commands.CommandError):
"""
A generic exception to raise for quick error handling.
"""
def __init__(self, message=CONST.STRINGS["lumi_exception_generic"]):
self.message = message
super().__init__(message)
class Blacklisted(commands.CommandError):
"""
Raised when a user is blacklisted.
"""
def __init__(self, message=CONST.STRINGS["lumi_exception_blacklisted"]):
self.message = message
super().__init__(message)

View file

@ -52,4 +52,5 @@ class CogLoader(commands.Cog):
async def setup(cls, bot: commands.Bot) -> None:
cog_loader = cls(bot)
await cog_loader.load_cog_from_dir(dir_name="modules")
await cog_loader.load_cog_from_dir(dir_name="handlers")
await bot.add_cog(cog_loader)

View file

@ -22,7 +22,7 @@ async def print_comic(
else:
comic = _xkcd.get_random_comic(raw_comic_image=True)
await interaction.followup.send(
await interaction.response.send_message(
embed=builder.create_success_embed(
interaction,
author_text=CONST.STRINGS["xkcd_title"].format(comic.id, comic.title),
@ -37,7 +37,7 @@ async def print_comic(
)
except HttpError:
await interaction.followup.send(
await interaction.response.send_message(
embed=builder.create_error_embed(
interaction,
author_text=CONST.STRINGS["xkcd_not_found_author"],
@ -51,10 +51,7 @@ class Xkcd(commands.Cog):
def __init__(self, bot: commands.Bot):
self.bot = bot
xkcd: app_commands.Group = app_commands.Group(
name="xkcd",
description="Xkcd commands",
)
xkcd = app_commands.Group(name="xkcd", description="Get the latest xkcd comic")
@xkcd.command(name="latest", description="Get the latest xkcd comic")
async def xkcd_latest(self, interaction: discord.Interaction) -> None:

View file

@ -1,5 +1,6 @@
import datetime
from discord.ext import commands
import discord
from lib.const import CONST
@ -8,7 +9,7 @@ from lib.const import CONST
class builder:
@staticmethod
def create_embed(
ctx,
ctx: commands.Context[commands.Bot],
title=None,
author_text=None,
author_icon_url=None,