Skip to content

tux.cogs.admin.eval

Classes:

Name Description
Eval

Functions:

Name Description
insert_returns

Inserts return statements into the body of the function definition.

Classes

Eval(bot: Tux)

Bases: Cog

Methods:

Name Description
eval

Evaluate a Python expression. (Owner only)

Source code in tux/cogs/admin/eval.py
Python
def __init__(self, bot: Tux) -> None:
    self.bot = bot
    self.eval.usage = generate_usage(self.eval)

Functions

eval(ctx: commands.Context[Tux], *, expression: str) -> None async

Evaluate a Python expression. (Owner only)

Parameters:

Name Type Description Default
ctx Context[Tux]

The context in which the command is being invoked.

required
expression str

The Python expression to evaluate.

required
Source code in tux/cogs/admin/eval.py
Python
@commands.command(
    name="eval",
    aliases=["e"],
)
@commands.guild_only()
@checks.has_pl(8)  # sysadmin or higher
async def eval(self, ctx: commands.Context[Tux], *, expression: str) -> None:
    """
    Evaluate a Python expression. (Owner only)

    Parameters
    ----------
    ctx : commands.Context[Tux]
        The context in which the command is being invoked.
    expression : str
        The Python expression to evaluate.
    """
    cmd = expression

    # Check if the user is in the discord.py owner_ids list in the bot instance
    if self.bot.owner_ids is None:
        logger.warning("Bot owner IDs are not set.")
        await ctx.send("Bot owner IDs are not set. Better luck next time!", ephemeral=True, delete_after=30)
        return

    if ctx.author.id not in self.bot.owner_ids:
        logger.warning(
            f"{ctx.author} tried to run eval but is not the bot owner. (User ID: {ctx.author.id})",
        )
        await ctx.send("You are not the bot owner. Better luck next time!", ephemeral=True, delete_after=30)
        return

    try:
        # Evaluate the expression
        fn_name = "_eval_expr"
        cmd = cmd.strip("` ")

        # Add a layer of indentation
        cmd = "\n".join(f"    {i}" for i in cmd.splitlines())

        # Wrap in async def body
        body = f"async def {fn_name}():\n{cmd}"

        # Parse the body
        parsed = ast.parse(body)

        # Ensure the first statement is a function definition
        if isinstance(parsed.body[0], ast.FunctionDef | ast.AsyncFunctionDef):
            # Access the body of the function definition
            body = parsed.body[0].body
            insert_returns(body)

        env = {
            "bot": ctx.bot,
            "discord": discord,
            "commands": commands,
            "ctx": ctx,
            "__import__": __import__,
        }

        # Execute the code
        exec(compile(parsed, filename="<ast>", mode="exec"), env)

        # Evaluate the function
        evaluated = await eval(f"{fn_name}()", env)

        embed = EmbedCreator.create_embed(
            EmbedCreator.SUCCESS,
            bot=self.bot,
            user_name=ctx.author.name,
            user_display_avatar=ctx.author.display_avatar.url,
            description=f"```py\n{evaluated}```",
        )
        await ctx.reply(embed=embed, ephemeral=True, delete_after=30)
        logger.info(f"{ctx.author} ran an expression: {cmd}")

    except Exception as error:
        embed = EmbedCreator.create_embed(
            EmbedCreator.ERROR,
            bot=self.bot,
            user_name=ctx.author.name,
            user_display_avatar=ctx.author.display_avatar.url,
            description=f"```py\n{error}```",
        )
        await ctx.reply(embed=embed, ephemeral=True, delete_after=30)
        logger.error(f"An error occurred while running an expression: {error}")

Functions

insert_returns(body: list[ast.stmt]) -> None

Inserts return statements into the body of the function definition.

Parameters:

Name Type Description Default
body list[stmt]

The body of the function definition.

required

Returns:

Type Description
None
Source code in tux/cogs/admin/eval.py
Python
def insert_returns(body: list[ast.stmt]) -> None:
    """
    Inserts return statements into the body of the function definition.

    Parameters
    ----------
    body : list[ast.stmt]
        The body of the function definition.

    Returns
    -------
    None
    """

    # Insert return statement if the last expression is a expression statement
    if isinstance(body[-1], ast.Expr):
        body[-1] = ast.Return(body[-1].value)
        ast.fix_missing_locations(body[-1])

    # For if statements, we insert returns into the body and the orelse
    if isinstance(body[-1], ast.If):
        insert_returns(body[-1].body)
        insert_returns(body[-1].orelse)

    # For with blocks, again we insert returns into the body
    if isinstance(body[-1], ast.With):
        insert_returns(body[-1].body)