1

I'm working on a Discord bot using the Pycord framework, and I have an eval command that I can use to evaluate Python statements:

class DevCog(discord.Cog):
    def __init__(self, bot: discord.Bot):
        self.bot = bot

    root = discord.SlashCommandGroup(
        name="dev",
        checks=[is_owner],
    )

    @root.command(description="Execute an arbitrary script.")
    async def execute(self, ctx: discord.ApplicationContext, script: str):
        """Executes an arbitrary Python script in the bot context. Used to debug and retrieve information not accessible by other commands.
        
        Args:
            script (str): The Python script to execute.
        """
        await ctx.defer(ephemeral=True)
        output = eval(script)
        if isawaitable(output):
            output = await output
        output = str(output)
        # Do returning-output stuff (Spit it out in an embed if it's under 4k characters, upload it to Hastebin and return the link to it otherwise, yada yada)

There's two big problems, arising from one: multi-line statements. I may need to do some things in the script I pass in before I arrive at the info I'm after, such as:

def answer():
    return 42
answer()

The first problem with this: Discord doesn't let you put newlines into string arguments in slash commands. (IIRC they did previously. Why they got rid of that is faaaar beyond me) I have thought of a solution: Using an attachment-type arg instead of a string-type to allow multiple lines.

The second lies with Python itself. This is what I get back from the Python REPL if I try to eval that script above:

>>> eval("""
... def answer():
...     return 42
... answer()
... """)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
SyntaxError: invalid syntax

This is where I'm stuck. I'm trying to run the script in the bot context (so I can access the bot and other objects and do things with them) and not in its own process. How can I set it up so I can do something like this?

Edit to clarify: I need to get some sort of output from the script returned so that I can pass it back in the response to the command.

M1N3R
  • 33
  • 4
  • `eval` evaluates an expression, to execute statements, use `exec`. Does that answer your question? – mkrieger1 Jul 18 '23 at 10:00
  • @mkrieger1 Nope. Just put a statement in it, nothing happened. Tried printing, returned None, but printed stuff in the logs, didn't return the output a la `eval`. Returning outside of a function doesn't work either. Functions/lambdas don't do anything either. – M1N3R Jul 18 '23 at 11:05

0 Answers0