Skip to content

Instantly share code, notes, and snippets.

@simmsb
Last active January 30, 2024 05:39
Show Gist options
  • Save simmsb/2c3c265813121492655bc95aa54da6b9 to your computer and use it in GitHub Desktop.
Save simmsb/2c3c265813121492655bc95aa54da6b9 to your computer and use it in GitHub Desktop.
A good eval for discord.py
import ast
import discord
from discord.ext import commands
def insert_returns(body):
# insert return stmt 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)
@commands.command()
async def eval_fn(ctx, *, cmd):
"""Evaluates input.
Input is interpreted as newline seperated statements.
If the last statement is an expression, that is the return value.
Usable globals:
- `bot`: the bot instance
- `discord`: the discord module
- `commands`: the discord.ext.commands module
- `ctx`: the invokation context
- `__import__`: the builtin `__import__` function
Such that `>eval 1 + 1` gives `2` as the result.
The following invokation will cause the bot to send the text '9'
to the channel of invokation and return '3' as the result of evaluating
>eval ```
a = 1 + 2
b = a * 2
await ctx.send(a + b)
a
```
"""
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}"
parsed = ast.parse(body)
body = parsed.body[0].body
insert_returns(body)
env = {
'bot': ctx.bot,
'discord': discord,
'commands': commands,
'ctx': ctx,
'__import__': __import__
}
exec(compile(parsed, filename="<ast>", mode="exec"), env)
result = (await eval(f"{fn_name}()", env))
await ctx.send(result)
Copy link

ghost commented Jun 30, 2018

lel

@crrapi
Copy link

crrapi commented Jul 1, 2018

Works great

@SmartCord
Copy link

big gay

@StreamlinYT
Copy link

OOOooo

@pTinosq
Copy link

pTinosq commented Jun 9, 2019

Fantastic stuff, saved me so much time!!

Copy link

ghost commented Jan 31, 2020

How to use?

@tyilo
Copy link

tyilo commented Mar 30, 2020

Here is my modified version with some improvements: https://github.com/beeracademy/discord-bot/blob/master/eval_stmts.py

@ides-dev
Copy link

tysm <3

@Master903
Copy link

Error in install libriary "ast" :^(

@tyilo
Copy link

tyilo commented Aug 26, 2020

Error in install libriary "ast" :^(

It's builtin.

@pTinosq
Copy link

pTinosq commented Nov 16, 2020

Please do not use this! This is not safe and people can execute dangerous code with this function.

It's only as dangerous as you make it. If you add appropriate checks to ensure limited people have access to this command, there is no issue.

@MySixSenses
Copy link

Please do not use this! This is not safe and people can execute dangerous code with this function.

@commands.is_owner

@Zzz9194
Copy link

Zzz9194 commented Dec 21, 2020

Great overall, I'd suggest also stripping code block syntax labels e.g. ```py

@FrostiiWeeb
Copy link

It says "TypeError: arguement type "bot" is not iterable".

Copy link

ghost commented Feb 2, 2021

What is this code supposed to do?

@TheDarkKnight69
Copy link

it says insert_returns is not defined

@zwinplayer64
Copy link

zwinplayer64 commented Aug 19, 2023

it says insert_returns is not defined

you need to copy the whole thing not just the eval function

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment