mirror of https://github.com/stijndcl/didier
62 lines
2.0 KiB
Python
62 lines
2.0 KiB
Python
import traceback
|
|
from typing import Optional
|
|
|
|
import discord
|
|
from discord.ext import commands
|
|
|
|
from didier.utils.discord.constants import Limits
|
|
from didier.utils.types.string import abbreviate
|
|
|
|
__all__ = ["create_error_embed"]
|
|
|
|
|
|
def _get_traceback(exception: Exception) -> str:
|
|
"""Get a proper representation of the exception"""
|
|
tb = traceback.format_exception(type(exception), exception, exception.__traceback__)
|
|
error_string = ""
|
|
for line in tb:
|
|
# Don't add endless tracebacks
|
|
if line.strip().startswith("The above exception was the direct cause of"):
|
|
break
|
|
|
|
# Escape Discord Markdown formatting
|
|
error_string += line
|
|
if line.strip():
|
|
error_string += "\n"
|
|
|
|
return abbreviate(error_string, Limits.EMBED_FIELD_VALUE_LENGTH - 8)
|
|
|
|
|
|
def create_error_embed(ctx: Optional[commands.Context], exception: Exception) -> discord.Embed:
|
|
"""Create an embed for the traceback of an exception"""
|
|
message = str(exception)
|
|
|
|
# Wrap the traceback in a codeblock for readability
|
|
description = _get_traceback(exception).strip()
|
|
description = f"```\n{description}\n```"
|
|
|
|
embed = discord.Embed(title="Error", colour=discord.Colour.red())
|
|
|
|
if ctx is not None:
|
|
if ctx.guild is None or isinstance(ctx.channel, discord.DMChannel):
|
|
origin = "DM"
|
|
else:
|
|
origin = f"<#{ctx.channel.id}> ({ctx.guild.name})"
|
|
|
|
invocation = f"{ctx.author.display_name} in {origin}"
|
|
|
|
if ctx.interaction is not None and ctx.interaction.command is not None:
|
|
command = ctx.interaction.command.name
|
|
else:
|
|
command = ctx.message.content or "N/A"
|
|
|
|
embed.add_field(name="Command", value=command, inline=True)
|
|
embed.add_field(name="Context", value=invocation, inline=True)
|
|
|
|
if message:
|
|
embed.add_field(name="Exception", value=message, inline=False)
|
|
|
|
embed.add_field(name="Traceback", value=description, inline=False)
|
|
|
|
return embed
|