diff --git a/.archive/notes.py b/.archive/notes.py index d929e12..44fb0f6 100644 --- a/.archive/notes.py +++ b/.archive/notes.py @@ -14,7 +14,7 @@ class Notes(ModerationCogBase): @commands.hybrid_group( name="notes", aliases=["n"], - usage="$notes ", + usage="notes ", ) @commands.guild_only() async def notes(self, ctx: commands.Context[commands.Bot]) -> None: @@ -32,7 +32,7 @@ class Notes(ModerationCogBase): @notes.command( name="create", aliases=["c", "add", "a"], - usage="$notes create [target] [content]", + usage="notes create [target] [content]", ) @commands.guild_only() async def create_note(self, ctx: commands.Context[commands.Bot], target: discord.Member, content: str) -> None: @@ -67,7 +67,7 @@ class Notes(ModerationCogBase): @notes.command( name="delete", aliases=["d"], - usage="$notes delete [note_id]", + usage="notes delete [note_id]", ) @commands.guild_only() async def delete_note(self, ctx: commands.Context[commands.Bot], note_id: int) -> None: @@ -108,7 +108,7 @@ class Notes(ModerationCogBase): @notes.command( name="update", aliases=["u", "edit", "e", "modify", "m"], - usage="$notes update [note_id] [content]", + usage="notes update [note_id] [content]", ) @commands.guild_only() async def update_note(self, ctx: commands.Context[commands.Bot], note_id: int, content: str) -> None: @@ -152,7 +152,7 @@ class Notes(ModerationCogBase): @notes.command( name="view", aliases=["v", "get", "g"], - usage="$notes view [note_id]", + usage="notes view [note_id]", ) @commands.guild_only() async def view_note( diff --git a/tux/cogs/admin/dev.py b/tux/cogs/admin/dev.py index a420de7..cfdad53 100644 --- a/tux/cogs/admin/dev.py +++ b/tux/cogs/admin/dev.py @@ -12,7 +12,7 @@ class Dev(commands.Cog): @commands.hybrid_group( name="dev", aliases=["d"], - usage="$dev ", + usage="dev ", ) @commands.guild_only() @checks.has_pl(8) @@ -38,7 +38,7 @@ class Dev(commands.Cog): @dev.command( name="sync_tree", aliases=["st", "sync", "s"], - usage="$dev sync_tree [guild]", + usage="dev sync_tree [guild]", ) @commands.guild_only() @checks.has_pl(8) @@ -69,21 +69,10 @@ class Dev(commands.Cog): await self.bot.tree.sync(guild=ctx.guild) await ctx.send("Application command tree synced.") - @sync_tree.error - async def sync_error(self, ctx: commands.Context[commands.Bot], error: Exception) -> None: - if isinstance(error, commands.MissingRequiredArgument): - await ctx.send( - f"Please specify a guild to sync application commands to. {error}", - ephemeral=True, - delete_after=30, - ) - else: - logger.error(f"Error syncing application commands: {error}") - @dev.command( name="clear_tree", aliases=["ct", "clear", "c"], - usage="$dev clear_tree", + usage="dev clear_tree", ) @commands.guild_only() @checks.has_pl(8) @@ -118,7 +107,7 @@ class Dev(commands.Cog): @dev.command( name="load_cog", aliases=["lc", "load", "l"], - usage="$dev load_cog [cog]", + usage="dev load_cog [cog]", ) @commands.guild_only() @checks.has_pl(8) @@ -156,30 +145,10 @@ class Dev(commands.Cog): await ctx.send(f"Cog {cog} loaded.") logger.info(f"Cog {cog} loaded.") - @load_cog.error - async def load_error(self, ctx: commands.Context[commands.Bot], error: Exception) -> None: - if isinstance(error, commands.MissingRequiredArgument): - await ctx.send(f"Please specify an cog to load. {error}", ephemeral=True, delete_after=30) - elif isinstance(error, commands.ExtensionAlreadyLoaded): - await ctx.send(f"The specified cog is already loaded. {error}", ephemeral=True, delete_after=30) - elif isinstance(error, commands.ExtensionNotFound): - await ctx.send(f"The specified cog is not found. {error}", ephemeral=True, delete_after=30) - elif isinstance(error, commands.ExtensionFailed): - await ctx.send(f"Failed to load cog: {error}", ephemeral=True, delete_after=30) - elif isinstance(error, commands.NoEntryPointError): - await ctx.send( - f"The specified cog does not have a setup function. {error}", - ephemeral=True, - delete_after=30, - ) - else: - await ctx.send(f"Failed to load cog: {error}", ephemeral=True, delete_after=30) - logger.error(f"Failed to load cog: {error}") - @dev.command( name="unload_cog", aliases=["uc", "unload", "u"], - usage="$dev unload_cog [cog]", + usage="dev unload_cog [cog]", ) @commands.guild_only() @checks.has_pl(8) @@ -211,19 +180,10 @@ class Dev(commands.Cog): logger.info(f"Cog {cog} unloaded.") await ctx.send(f"Cog {cog} unloaded.", ephemeral=True, delete_after=30) - @unload_cog.error - async def unload_error(self, ctx: commands.Context[commands.Bot], error: Exception) -> None: - if isinstance(error, commands.MissingRequiredArgument): - await ctx.send(f"Please specify an extension to unload. {error}", ephemeral=True, delete_after=30) - elif isinstance(error, commands.ExtensionNotLoaded): - await ctx.send(f"That cog is not loaded. {error}", ephemeral=True, delete_after=30) - else: - logger.error(f"Error unloading cog: {error}") - @dev.command( name="reload_cog", aliases=["rc", "reload", "r"], - usage="$dev reload_cog [cog]", + usage="dev reload_cog [cog]", ) @commands.guild_only() @checks.has_pl(8) @@ -256,16 +216,6 @@ class Dev(commands.Cog): await ctx.send(f"Cog {cog} reloaded.", ephemeral=True, delete_after=30) logger.info(f"Cog {cog} reloaded.") - @reload_cog.error - async def reload_error(self, ctx: commands.Context[commands.Bot], error: Exception) -> None: - if isinstance(error, commands.MissingRequiredArgument): - await ctx.send(f"Please specify a cog to reload. {error}", ephemeral=True, delete_after=30) - elif isinstance(error, commands.ExtensionNotLoaded): - await ctx.send(f"That cog is not loaded. {error}", ephemeral=True, delete_after=30) - else: - await ctx.send(f"Error reloading cog: {error}", ephemeral=True, delete_after=30) - logger.error(f"Error reloading cog: {error}") - async def setup(bot: commands.Bot) -> None: await bot.add_cog(Dev(bot)) diff --git a/tux/cogs/admin/eval.py b/tux/cogs/admin/eval.py index e86c130..d2b4ea3 100644 --- a/tux/cogs/admin/eval.py +++ b/tux/cogs/admin/eval.py @@ -45,7 +45,7 @@ class Eval(commands.Cog): @commands.command( name="eval", aliases=["e"], - usage="$eval [expression]", + usage="eval [expression]", ) @commands.guild_only() @checks.has_pl(9) diff --git a/tux/cogs/admin/git.py b/tux/cogs/admin/git.py index ed31057..7bab6be 100644 --- a/tux/cogs/admin/git.py +++ b/tux/cogs/admin/git.py @@ -403,7 +403,7 @@ class Git(commands.Cog): @commands.hybrid_group( name="git", aliases=["g"], - usage="$git ", + usage="git ", ) @commands.guild_only() @checks.has_pl(8) @@ -423,7 +423,7 @@ class Git(commands.Cog): @git.command( name="get_repo", aliases=["r"], - usage="$git get_repo", + usage="git get_repo", ) @commands.guild_only() @checks.has_pl(8) @@ -461,7 +461,7 @@ class Git(commands.Cog): @git.command( name="create_issue", aliases=["ci"], - usage="$git create_issue [title] [body]", + usage="git create_issue [title] [body]", ) @commands.guild_only() # @checks.has_pl(8) @@ -503,7 +503,7 @@ class Git(commands.Cog): @git.command( name="get_issue", aliases=["gi", "issue", "i"], - usage="$git get_issue [issue_number]", + usage="git get_issue [issue_number]", ) @commands.guild_only() @checks.has_pl(8) diff --git a/tux/cogs/fun/random.py b/tux/cogs/fun/random.py index 398946f..9a2f60b 100644 --- a/tux/cogs/fun/random.py +++ b/tux/cogs/fun/random.py @@ -12,7 +12,7 @@ class Random(commands.Cog): @commands.hybrid_group( name="random", aliases=["rand"], - usage="$random ", + usage="random ", ) @commands.guild_only() async def random(self, ctx: commands.Context[commands.Bot]) -> None: @@ -30,7 +30,7 @@ class Random(commands.Cog): @random.command( name="coinflip", aliases=["cf"], - usage="$random coinflip", + usage="random coinflip", ) @commands.guild_only() async def coinflip(self, ctx: commands.Context[commands.Bot]) -> None: @@ -50,7 +50,7 @@ class Random(commands.Cog): @random.command( name="8ball", aliases=["eightball", "8b"], - usage="$random 8ball [question]", + usage="random 8ball [question]", ) @commands.guild_only() async def eight_ball(self, ctx: commands.Context[commands.Bot], *, question: str, cow: bool = False) -> None: @@ -140,7 +140,7 @@ class Random(commands.Cog): @random.command( name="dice", aliases=["d"], - usage="$random dice ", + usage="random dice ", ) @commands.guild_only() async def dice(self, ctx: commands.Context[commands.Bot], sides: int = 6) -> None: @@ -170,7 +170,7 @@ class Random(commands.Cog): @random.command( name="number", aliases=["n"], - usage="$random number ", + usage="random number ", ) @commands.guild_only() async def random_number( diff --git a/tux/cogs/fun/xkcd.py b/tux/cogs/fun/xkcd.py index 62da094..d2fad43 100644 --- a/tux/cogs/fun/xkcd.py +++ b/tux/cogs/fun/xkcd.py @@ -15,7 +15,7 @@ class Xkcd(commands.Cog): @commands.hybrid_group( name="xkcd", aliases=["xk"], - usage="$xkcd ", + usage="xkcd ", ) @commands.guild_only() async def xkcd(self, ctx: commands.Context[commands.Bot], comic_id: int | None = None) -> None: @@ -38,7 +38,7 @@ class Xkcd(commands.Cog): @xkcd.command( name="latest", aliases=["l", "new", "n"], - usage="$xkcd latest", + usage="xkcd latest", ) @commands.guild_only() async def latest(self, ctx: commands.Context[commands.Bot]) -> None: @@ -61,7 +61,7 @@ class Xkcd(commands.Cog): @xkcd.command( name="random", aliases=["rand", "r"], - usage="$xkcd random", + usage="xkcd random", ) @commands.guild_only() async def random(self, ctx: commands.Context[commands.Bot]) -> None: @@ -84,7 +84,7 @@ class Xkcd(commands.Cog): @xkcd.command( name="specific", aliases=["s", "id", "num"], - usage="$xkcd specific [comic_id]", + usage="xkcd specific [comic_id]", ) @commands.guild_only() async def specific(self, ctx: commands.Context[commands.Bot], comic_id: int) -> None: diff --git a/tux/cogs/info/avatar.py b/tux/cogs/info/avatar.py index 46e6f46..0c4cdb8 100644 --- a/tux/cogs/info/avatar.py +++ b/tux/cogs/info/avatar.py @@ -36,7 +36,7 @@ class Avatar(commands.Cog): @commands.command( name="avatar", aliases=["av"], - usage="$avatar ", + usage="avatar ", ) @commands.guild_only() async def prefix_avatar( diff --git a/tux/cogs/misc/run.py b/tux/cogs/misc/run.py index 7ea1627..ac3b225 100644 --- a/tux/cogs/misc/run.py +++ b/tux/cogs/misc/run.py @@ -232,7 +232,7 @@ class Run(commands.Cog): @commands.command( name="run", aliases=["compile", "exec"], - usage="$run [code]", + usage="run [code]", ) async def run( self, @@ -302,7 +302,7 @@ class Run(commands.Cog): @commands.command( name="languages", aliases=["langs"], - usage="$languages", + usage="languages", ) async def languages(self, ctx: commands.Context[commands.Bot]) -> None: """ diff --git a/tux/cogs/moderation/ban.py b/tux/cogs/moderation/ban.py index af905b5..8ceb161 100644 --- a/tux/cogs/moderation/ban.py +++ b/tux/cogs/moderation/ban.py @@ -18,7 +18,7 @@ class Ban(ModerationCogBase): @commands.hybrid_command( name="ban", aliases=["b"], - usage="$ban [target] ", + usage="ban [target] ", ) @commands.guild_only() @checks.has_pl(3) diff --git a/tux/cogs/moderation/cases.py b/tux/cogs/moderation/cases.py index 42f5c7e..3b831b1 100644 --- a/tux/cogs/moderation/cases.py +++ b/tux/cogs/moderation/cases.py @@ -33,7 +33,7 @@ class Cases(ModerationCogBase): @commands.hybrid_group( name="cases", aliases=["c"], - usage="$cases ", + usage="cases ", ) @commands.guild_only() @checks.has_pl(2) @@ -47,7 +47,7 @@ class Cases(ModerationCogBase): @cases.command( name="view", aliases=["v", "ls", "list"], - usage="$cases view ", + usage="cases view ", ) @commands.guild_only() @checks.has_pl(2) @@ -83,7 +83,7 @@ class Cases(ModerationCogBase): @cases.command( name="modify", aliases=["m", "edit"], - usage="$cases modify [case_number] ", + usage="cases modify [case_number] ", ) @commands.guild_only() @checks.has_pl(2) diff --git a/tux/cogs/moderation/jail.py b/tux/cogs/moderation/jail.py index f8b00ed..6a4222a 100644 --- a/tux/cogs/moderation/jail.py +++ b/tux/cogs/moderation/jail.py @@ -87,7 +87,7 @@ class Jail(ModerationCogBase): @commands.hybrid_command( name="jail", aliases=["j"], - usage="$jail [target] [reason] ", + usage="jail [target] [reason] ", ) @commands.guild_only() @checks.has_pl(2) diff --git a/tux/cogs/moderation/kick.py b/tux/cogs/moderation/kick.py index 8351b64..697a51f 100644 --- a/tux/cogs/moderation/kick.py +++ b/tux/cogs/moderation/kick.py @@ -18,7 +18,7 @@ class Kick(ModerationCogBase): @commands.hybrid_command( name="kick", aliases=["k"], - usage="$kick [target] [reason] ", + usage="kick [target] [reason] ", ) @commands.guild_only() @checks.has_pl(2) diff --git a/tux/cogs/moderation/purge.py b/tux/cogs/moderation/purge.py index 1a4d416..66b181d 100644 --- a/tux/cogs/moderation/purge.py +++ b/tux/cogs/moderation/purge.py @@ -73,7 +73,7 @@ class Purge(commands.Cog): @commands.command( name="purge", aliases=["p"], - usage="$purge [limit] ", + usage="purge [limit] ", ) @commands.guild_only() @checks.has_pl(2) diff --git a/tux/cogs/moderation/slowmode.py b/tux/cogs/moderation/slowmode.py index acbd7a3..b695096 100644 --- a/tux/cogs/moderation/slowmode.py +++ b/tux/cogs/moderation/slowmode.py @@ -12,7 +12,7 @@ class Slowmode(commands.Cog): @commands.hybrid_command( name="slowmode", aliases=["sm"], - usage="$slowmode [delay] ", + usage="slowmode [delay] ", ) @commands.guild_only() @checks.has_pl(2) diff --git a/tux/cogs/moderation/timeout.py b/tux/cogs/moderation/timeout.py index 9db2ccb..3fb05c9 100644 --- a/tux/cogs/moderation/timeout.py +++ b/tux/cogs/moderation/timeout.py @@ -61,7 +61,7 @@ class Timeout(ModerationCogBase): @commands.hybrid_command( name="timeout", aliases=["t", "to", "mute"], - usage="$timeout [target] [duration] [reason]", + usage="timeout [target] [duration] [reason]", ) @commands.guild_only() @checks.has_pl(2) diff --git a/tux/cogs/moderation/unban.py b/tux/cogs/moderation/unban.py index d1d53c7..27b6025 100644 --- a/tux/cogs/moderation/unban.py +++ b/tux/cogs/moderation/unban.py @@ -18,7 +18,7 @@ class Unban(ModerationCogBase): @commands.hybrid_command( name="unban", aliases=["ub"], - usage="$unban [target] [reason]", + usage="unban [target] [reason]", ) @commands.guild_only() @checks.has_pl(3) diff --git a/tux/cogs/moderation/unjail.py b/tux/cogs/moderation/unjail.py index a4c468b..de41a80 100644 --- a/tux/cogs/moderation/unjail.py +++ b/tux/cogs/moderation/unjail.py @@ -18,7 +18,7 @@ class Unjail(ModerationCogBase): @commands.hybrid_command( name="unjail", aliases=["uj"], - usage="$unjail [target] [reason] ", + usage="unjail [target] [reason] ", ) @commands.guild_only() @checks.has_pl(2) diff --git a/tux/cogs/moderation/untimeout.py b/tux/cogs/moderation/untimeout.py index 7d4ec1a..634b957 100644 --- a/tux/cogs/moderation/untimeout.py +++ b/tux/cogs/moderation/untimeout.py @@ -18,7 +18,7 @@ class Untimeout(ModerationCogBase): @commands.hybrid_command( name="untimeout", aliases=["ut", "uto", "unmute"], - usage="$untimeout [target] [reason]", + usage="untimeout [target] [reason]", ) @commands.guild_only() @checks.has_pl(2) diff --git a/tux/cogs/moderation/warn.py b/tux/cogs/moderation/warn.py index 778f180..d83c35e 100644 --- a/tux/cogs/moderation/warn.py +++ b/tux/cogs/moderation/warn.py @@ -18,7 +18,7 @@ class Warn(ModerationCogBase): @commands.hybrid_command( name="warn", aliases=["w"], - usage="$warn [target] ", + usage="warn [target] ", ) @commands.guild_only() @checks.has_pl(2) diff --git a/tux/cogs/utility/ping.py b/tux/cogs/utility/ping.py index 8218415..1b1b953 100644 --- a/tux/cogs/utility/ping.py +++ b/tux/cogs/utility/ping.py @@ -10,7 +10,7 @@ class Ping(commands.Cog): @commands.hybrid_command( name="ping", - usage="$ping", + usage="ping", ) async def ping(self, ctx: commands.Context[commands.Bot]) -> None: """ diff --git a/tux/cogs/utility/query.py b/tux/cogs/utility/query.py index 1761903..9417b16 100644 --- a/tux/cogs/utility/query.py +++ b/tux/cogs/utility/query.py @@ -14,7 +14,7 @@ class Query(commands.Cog): @commands.hybrid_command( name="query", aliases=["q"], - usage="$query [search_term]", + usage="query [search_term]", ) async def query(self, ctx: commands.Context[commands.Bot], *, search_term: str) -> None: """ diff --git a/tux/cogs/utility/snippets.py b/tux/cogs/utility/snippets.py index 26540e4..7675aad 100644 --- a/tux/cogs/utility/snippets.py +++ b/tux/cogs/utility/snippets.py @@ -23,7 +23,7 @@ class Snippets(commands.Cog): @commands.command( name="snippets", aliases=["ls"], - usage="$snippets", + usage="snippets", ) @commands.guild_only() async def list_snippets(self, ctx: commands.Context[commands.Bot]) -> None: @@ -104,7 +104,7 @@ class Snippets(commands.Cog): @commands.command( name="deletesnippet", aliases=["ds"], - usage="$deletesnippet [name]", + usage="deletesnippet [name]", ) @commands.guild_only() async def delete_snippet(self, ctx: commands.Context[commands.Bot], name: str) -> None: @@ -154,7 +154,7 @@ class Snippets(commands.Cog): @commands.command( name="forcedeletesnippet", aliases=["fds"], - usage="$forcedeletesnippet [name]", + usage="forcedeletesnippet [name]", ) @commands.guild_only() @checks.has_pl(2) @@ -193,7 +193,7 @@ class Snippets(commands.Cog): @commands.command( name="snippet", aliases=["s"], - usage="$snippet [name]", + usage="snippet [name]", ) @commands.guild_only() async def get_snippet(self, ctx: commands.Context[commands.Bot], name: str) -> None: @@ -230,7 +230,7 @@ class Snippets(commands.Cog): @commands.command( name="snippetinfo", aliases=["si"], - usage="$snippetinfo [name]", + usage="snippetinfo [name]", ) @commands.guild_only() async def get_snippet_info(self, ctx: commands.Context[commands.Bot], name: str) -> None: @@ -287,7 +287,7 @@ class Snippets(commands.Cog): @commands.command( name="createsnippet", aliases=["cs"], - usage="$createsnippet [name] [content]", + usage="createsnippet [name] [content]", ) @commands.guild_only() async def create_snippet(self, ctx: commands.Context[commands.Bot], *, arg: str) -> None: diff --git a/tux/cogs/utility/tldr.py b/tux/cogs/utility/tldr.py index a779f3d..af1ad6e 100644 --- a/tux/cogs/utility/tldr.py +++ b/tux/cogs/utility/tldr.py @@ -70,7 +70,7 @@ class Tldr(commands.Cog): @commands.command( name="tldr", aliases=["man"], - usage="$tldr [command]", + usage="tldr [command]", ) @commands.guild_only() async def prefix_tldr(self, ctx: commands.Context[commands.Bot], command: str) -> None: diff --git a/tux/cogs/utility/wiki.py b/tux/cogs/utility/wiki.py index 73cd284..ac3a1b4 100644 --- a/tux/cogs/utility/wiki.py +++ b/tux/cogs/utility/wiki.py @@ -83,7 +83,7 @@ class Wiki(commands.Cog): @commands.hybrid_group( name="wiki", - usage="$wiki [arch|atl]", + usage="wiki [arch|atl]", aliases=["wk"], ) async def wiki(self, ctx: commands.Context[commands.Bot]) -> None: @@ -101,7 +101,7 @@ class Wiki(commands.Cog): @wiki.command( name="arch", - usage="$wiki arch [query]", + usage="wiki arch [query]", ) async def arch_wiki(self, ctx: commands.Context[commands.Bot], query: str) -> None: """ @@ -131,7 +131,7 @@ class Wiki(commands.Cog): @wiki.command( name="atl", - usage="$wiki atl [query]", + usage="wiki atl [query]", ) async def atl_wiki(self, ctx: commands.Context[commands.Bot], query: str) -> None: """ diff --git a/tux/handlers/error.py b/tux/handlers/error.py index 50e827a..e37a3f5 100644 --- a/tux/handlers/error.py +++ b/tux/handlers/error.py @@ -7,6 +7,7 @@ from discord.ext import commands from loguru import logger import tux.handlers.error as error +from tux.utils.embeds import create_error_embed class PermissionLevelError(commands.CheckFailure): @@ -44,14 +45,14 @@ error_map: dict[type[Exception], str] = { commands.CheckFailure: "User not in sudoers file. This incident will be reported. (Permission Check Failed)", commands.CommandNotFound: "This command was not found.", commands.CommandOnCooldown: "This command is on cooldown. Try again in {error.retry_after:.2f} seconds.", - commands.BadArgument: "Invalid argument passed. Correct usage: `{ctx.command.usage}`", - commands.MissingRequiredArgument: "Missing required argument. Correct usage: `{ctx.command.usage}`", + commands.BadArgument: "Invalid argument passed. Correct usage: `{ctx.prefix}{ctx.command.usage}`", + commands.MissingRequiredArgument: "Missing required arg. Correct usage: `{ctx.prefix}{ctx.command.usage}`", commands.MissingRequiredAttachment: "Missing required attachment.", commands.NotOwner: "User not in sudoers file. This incident will be reported. (Not Owner)", commands.BotMissingPermissions: "User not in sudoers file. This incident will be reported. (Bot Missing Permissions)", # Custom errors - error.PermissionLevelError: "User not in sudoers file. This incident will be reported. (You do not have the required permission: {error.permission})", - error.AppCommandPermissionLevelError: "User not in sudoers file. This incident will be reported. (You do not have the required permission: {error.permission})", + error.PermissionLevelError: "User not in sudoers file. This incident will be reported. (Missing required permission: {error.permission})", + error.AppCommandPermissionLevelError: "User not in sudoers file. This incident will be reported. (Missing required permission: {error.permission})", } @@ -84,10 +85,12 @@ class ErrorHandler(commands.Cog): error_message = error_map.get(type(error), self.error_message).format(error=error) + embed = create_error_embed(error_message) + if interaction.response.is_done(): - await interaction.followup.send(error_message, ephemeral=True) + await interaction.followup.send(embed=embed, ephemeral=True) else: - await interaction.response.send_message(error_message, ephemeral=True, delete_after=30) + await interaction.response.send_message(embed=embed, ephemeral=True, delete_after=30) if type(error) in error_map: sentry_sdk.capture_exception(error) @@ -112,18 +115,20 @@ class ErrorHandler(commands.Cog): """ # # If the command has its own error handler, return - if hasattr(ctx.command, "on_error"): - logger.debug(f"Command {ctx.command} has its own error handler.") - return + # if hasattr(ctx.command, "on_error"): + # logger.debug(f"Command {ctx.command} has its own error handler.") + # return # # If the cog has its own error handler, return - if ctx.cog and ctx.cog._get_overridden_method(ctx.cog.cog_command_error) is not None: - logger.debug(f"Cog {ctx.cog} has its own error handler.") - return + # if ctx.cog and ctx.cog._get_overridden_method(ctx.cog.cog_command_error) is not None: + # logger.debug(f"Cog {ctx.cog} has its own error handler.") + # return if isinstance(error, commands.CheckFailure): message = error_map.get(type(error), self.error_message).format(error=error, ctx=ctx) - await ctx.send(content=message, ephemeral=True, delete_after=30) + # await ctx.send(content=message, ephemeral=True, delete_after=30) + embed = create_error_embed(message) + await ctx.send(embed=embed, ephemeral=True, delete_after=30) sentry_sdk.capture_exception(error) return @@ -140,7 +145,10 @@ class ErrorHandler(commands.Cog): # Get the error message and send it to the user message: str = self.get_error_message(error, ctx) - await ctx.send(content=message, ephemeral=True, delete_after=30) + # await ctx.send(content=message, ephemeral=True, delete_after=30) + + embed = create_error_embed(message) + await ctx.send(embed=embed, ephemeral=True, delete_after=30) # Log the error traceback if it's not in the error map if type(error) not in error_map: diff --git a/tux/help.py b/tux/help.py index 655e875..d133b0c 100644 --- a/tux/help.py +++ b/tux/help.py @@ -18,7 +18,6 @@ from tux.utils.embeds import EmbedCreator class TuxHelp(commands.HelpCommand): def __init__(self): """Initializes the TuxHelp command with necessary attributes.""" - self.prefix = CONST.PREFIX super().__init__( command_attrs={ "help": "Lists all commands and sub-commands.", @@ -27,6 +26,17 @@ class TuxHelp(commands.HelpCommand): }, ) + async def _get_prefix(self): + """ + Dynamically fetches the prefix from the context. + + Returns + ------- + str + The prefix used to invoke the bot. + """ + return (await self.context.bot.get_prefix(self.context.message))[0] or CONST.PREFIX + def _embed_base(self, title: str, description: str | None = None) -> discord.Embed: """ Creates a base embed with uniform styling. @@ -62,8 +72,10 @@ class TuxHelp(commands.HelpCommand): prefix : str The prefix used to invoke the command. """ + command_aliases = ", ".join(command.aliases) if command.aliases else "No aliases." + embed.add_field( - name=f"{prefix}{command.qualified_name} ({', '.join(command.aliases) if command.aliases else 'No aliases.'})", + name=f"{prefix}{command.qualified_name} ({command_aliases})", value=f"> {command.short_doc or 'No documentation summary.'}", inline=False, ) @@ -172,14 +184,14 @@ class TuxHelp(commands.HelpCommand): "Tux is an all-in-one bot for the All Things Linux Discord server. The bot is written in Python 3.12 using discord.py, and we are actively seeking contributors!", ) - self._add_bot_help_fields(embed) + await self._add_bot_help_fields(embed) menu.add_page(embed) - self._add_cog_pages(menu, mapping) + await self._add_cog_pages(menu, mapping) await menu.start() - def _add_bot_help_fields(self, embed: discord.Embed) -> None: + async def _add_bot_help_fields(self, embed: discord.Embed) -> None: """ Adds additional help information about the bot. @@ -188,19 +200,21 @@ class TuxHelp(commands.HelpCommand): embed : discord.Embed The embed to which the help information will be added. """ + prefix = await self._get_prefix() + embed.add_field( name="How to Use", - value=f"Most commands are hybrid meaning they can be used via prefix `{self.prefix}` OR slash `/`. Commands strictly available via `/` are not listed in the help menu.", + value=f"Most commands are hybrid meaning they can be used via prefix `{prefix}` OR slash `/`. Commands strictly available via `/` are not listed in the help menu.", inline=False, ) embed.add_field( name="Command Help", - value=f"Use `{self.prefix}help ` or `{self.prefix}help ` to learn about a specific command.\n> e.g. `{self.prefix}help ban` or `{self.prefix}h dev load_cog`", + value=f"Use `{prefix}help ` or `{prefix}help ` to learn about a specific command.\n> e.g. `{prefix}help ban` or `{prefix}h dev load_cog`", inline=False, ) embed.add_field( name="Flag Help", - value=f"Flags in `[]` are required and `<>` are optional. Most flags have aliases that can be used.\n> e.g. `{self.prefix}ban @user --reason spamming` or `{self.prefix}b @user -r spamming`", + value=f"Flags in `[]` are required and `<>` are optional. Most flags have aliases that can be used.\n> e.g. `{prefix}ban @user --reason spamming` or `{prefix}b @user -r spamming`", inline=False, ) embed.add_field( @@ -214,7 +228,7 @@ class TuxHelp(commands.HelpCommand): inline=True, ) - def _add_cog_pages( + async def _add_cog_pages( self, menu: ViewMenu, mapping: Mapping[commands.Cog | None, list[commands.Command[Any, Any, Any]]], @@ -229,12 +243,12 @@ class TuxHelp(commands.HelpCommand): mapping : Mapping[commands.Cog | None, list[commands.Command[Any, Any, Any]]] The mapping of cogs to commands. """ - command_categories = self._get_command_categories(mapping) + command_categories = await self._get_command_categories(mapping) cog_groups = self._get_cog_groups() - select_options = self._create_select_options(command_categories, cog_groups, menu) + select_options = await self._create_select_options(command_categories, cog_groups, menu) self._add_navigation_and_selection(menu, select_options) - def _get_command_categories( + async def _get_command_categories( self, mapping: Mapping[commands.Cog | None, list[commands.Command[Any, Any, Any]]], ) -> dict[str, dict[str, str]]: @@ -257,8 +271,11 @@ class TuxHelp(commands.HelpCommand): if cog and len(mapping_commands) > 0: cog_group = self._extract_cog_group(cog) or "extra" command_categories.setdefault(cog_group, {}) - cmd = cog.qualified_name - command_categories[cog_group][cmd] = " ".join(f"`{command.name}`" for command in mapping_commands) + for command in mapping_commands: + cmd_name_and_aliases = f"`{command.name}`" + if command.aliases: + cmd_name_and_aliases += f" ({', '.join(f'`{alias}`' for alias in command.aliases)})" + command_categories[cog_group][command.name] = cmd_name_and_aliases return command_categories @@ -273,7 +290,7 @@ class TuxHelp(commands.HelpCommand): """ return [d for d in os.listdir("./tux/cogs") if Path(f"./tux/cogs/{d}").is_dir() and d != "__pycache__"] - def _create_select_options( + async def _create_select_options( self, command_categories: dict[str, dict[str, str]], cog_groups: list[str], @@ -301,7 +318,9 @@ class TuxHelp(commands.HelpCommand): for index, cog_group in enumerate(cog_groups, start=1): if cog_group in command_categories and any(command_categories[cog_group].values()): embed = self._embed_base(f"{cog_group.capitalize()} Commands", "\n") - embed.set_footer(text=f"Use {self.prefix}help or to learn about it.") + embed.set_footer( + text=f"Use {await self._get_prefix()}help or to learn about it.", + ) for cmd, command_list in command_categories[cog_group].items(): embed.add_field(name=cmd, value=command_list, inline=False) @@ -358,14 +377,15 @@ class TuxHelp(commands.HelpCommand): cog : commands.Cog The cog for which the help message is to be sent. """ + prefix = await self._get_prefix() embed = self._embed_base(f"{cog.qualified_name} Commands") for command in cog.get_commands(): - self._add_command_field(embed, command, self.prefix) + self._add_command_field(embed, command, prefix) if isinstance(command, commands.Group): for subcommand in command.commands: - self._add_command_field(embed, subcommand, self.prefix) + self._add_command_field(embed, subcommand, prefix) await self.get_destination().send(embed=embed) @@ -378,19 +398,21 @@ class TuxHelp(commands.HelpCommand): command : commands.Command[Any, Any, Any] The command for which the help message is to be sent. """ + prefix = await self._get_prefix() + embed = self._embed_base( - title=f"{self.prefix}{command.qualified_name}", + title=f"{prefix}{command.qualified_name}", description=f"> {command.help or 'No documentation available.'}", ) - self._add_command_help_fields(embed, command) + await self._add_command_help_fields(embed, command) if flag_details := self._format_flag_details(command): embed.add_field(name="Flags", value=f"```\n{flag_details}\n```", inline=False) await self.get_destination().send(embed=embed) - def _add_command_help_fields(self, embed: discord.Embed, command: commands.Command[Any, Any, Any]) -> None: + async def _add_command_help_fields(self, embed: discord.Embed, command: commands.Command[Any, Any, Any]) -> None: """ Adds fields with usage and alias information for a command to an embed. @@ -401,9 +423,11 @@ class TuxHelp(commands.HelpCommand): command : commands.Command[Any, Any, Any] The command whose details are to be added. """ + prefix = await self._get_prefix() + embed.add_field( name="Usage", - value=f"`{command.signature or 'No usage.'}`", + value=f"`{prefix}{command.usage or 'No usage.'}`", inline=False, ) embed.add_field( @@ -421,12 +445,14 @@ class TuxHelp(commands.HelpCommand): group : commands.Group[Any, Any, Any] The group for which the help message is to be sent. """ + prefix = await self._get_prefix() + embed = self._embed_base(f"{group.name}", f"> {group.help or 'No documentation available.'}") - self._add_command_help_fields(embed, group) + await self._add_command_help_fields(embed, group) for command in group.commands: - self._add_command_field(embed, command, self.prefix) + self._add_command_field(embed, command, prefix) await self.get_destination().send(embed=embed) diff --git a/tux/utils/embeds.py b/tux/utils/embeds.py index fa70eca..648fefd 100644 --- a/tux/utils/embeds.py +++ b/tux/utils/embeds.py @@ -30,6 +30,14 @@ def create_embed_footer( return (fallback_text, fallback_icon_url) +@staticmethod +def create_error_embed(error: str) -> discord.Embed: + embed = discord.Embed() + embed.color = CONST.EMBED_COLORS["ERROR"] + embed.description = f"<:tux_error:1273494919897681930> {error}" + return embed + + class EmbedCreator: @staticmethod def get_timestamp(