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.