Skip to content

Instantly share code, notes, and snippets.

@Jerdak
Last active July 4, 2017 21:10
Show Gist options
  • Save Jerdak/637dc783b32066498cdfad8465148f29 to your computer and use it in GitHub Desktop.
Save Jerdak/637dc783b32066498cdfad8465148f29 to your computer and use it in GitHub Desktop.
# requires https://github.com/Rapptz/discord.py
# this snippet was scripted against discord.py v0.16.8 @ commit 7b806667cda6dc26b6a99d73473dcff5c2dd4044
import discord
import asyncio
import re
from types import ModuleType
sandbox = ModuleType('sandboxed_modules')
from discord.ext.commands import Bot
my_bot = Bot(command_prefix="!")
@my_bot.event
@asyncio.coroutine
def on_read():
print("Client logged in")
def __compile_that_shit(contents):
""" Compile source helper
Convert a discord.py message block to a viable bit of python source.
It's assumed the user will return a string.
Arguments:
contents (str) - Discord message contents. See 'expected content format' below.
Expected Content Format:
!discord_command
```python
def my_code():
return "my code ran, aren't I special"
```
NOTE:
discord.py doesn't like inline double quotes so for now
the source must contain escaped single quotes for string
literals.
TODO:
* Wrap user code so it always returns a string.
* Sanitize user code to disallow file system access, or use in VM only.
"""
# Ugly regex to pull out markdown code block.
m = re.search('`{3}python(?:(.*$)\n)?([\s\S]*)`{3}',contents)
code_block = m.group(2)
# Split code block along lines
code_blocks = code_block.split('\n')
# Recreate code block
code_block = "\n".join(code_blocks)
print("contents:",contents)
print("Code Block:",code_block)
code = compile(code_block,'','exec')
# Avoid function leakage, plop it in a custom namespace. (TODO: Tie this to user id?)
exec(code,sandbox.__dict__)
@my_bot.command(pass_context=True)
@asyncio.coroutine
def compile_that_shit(ctx):
""" Compile user code
Example:
!compile_that_shit
```python
def my_code():
return "my code ran, aren't I special"
```
"""
__compile_that_shit(ctx.message.content)
yield from my_bot.say("I compiled your shitty code, but I'm not happy about it. Use `!run_that_shit <function_name>` to trigger the function. Parens not supported")
@my_bot.command()
@asyncio.coroutine
def run_that_shit(*args):
""" Run compiled function
Example:
!run_that_shit my_code
TODO:
* Add argument support. e.g. !run_that_shit my_code('foo','bar')
"""
print(args)
if args[0] in sandbox.__dict__:
yield from my_bot.say(sandbox.__dict__[args[0]]())
else:
yield from my_bot.say("<{0}> not found, compile that shit first".format(args[0]))
# CLIENT TOKEN is your Discord bot's token.
my_bot.run('<CLIENT_TOKEN>')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment