discordbot/cogs/eval_cog.py

63 lines
1.8 KiB
Python

import discord
from discord.ext import commands
import io
import textwrap
import traceback
import contextlib
class EvalCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
def cleanup_code(self, content):
"""Automatically removes code blocks from the code."""
# remove ```py\n```
if content.startswith('```') and content.endswith('```'):
return '\n'.join(content.split('\n')[1:-1])
return content.strip('` \n')
@commands.command(name='evalpy', hidden=True)
@commands.is_owner()
async def _eval(self, ctx, *, body: str):
"""Evaluates a code snippet."""
env = {
'bot': self.bot,
'ctx': ctx,
'channel': ctx.channel,
'author': ctx.author,
'guild': ctx.guild,
'message': ctx.message,
'discord': discord,
'commands': commands
}
env.update(globals())
body = self.cleanup_code(body)
stdout = io.StringIO()
to_compile = f'async def func():\n{textwrap.indent(body, " ")}'
try:
exec(to_compile, env)
except Exception as e:
return await ctx.send(f'```py\n{e.__class__.__name__}: {e}\n```')
func = env['func']
try:
with contextlib.redirect_stdout(stdout):
ret = await func()
ret = await func()
except Exception as e:
value = stdout.getvalue()
await ctx.send(f'```py\n{value}{traceback.format_exc()}\n```')
else:
value = stdout.getvalue()
if ret is None:
if value:
await ctx.send(f'```py\n{value}\n```')
else:
await ctx.send(f'```py\n{value}{ret}\n```')
async def setup(bot: commands.Bot):
await bot.add_cog(EvalCog(bot))