summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval_handler.py49
-rw-r--r--main.py13
2 files changed, 60 insertions, 2 deletions
diff --git a/eval_handler.py b/eval_handler.py
new file mode 100644
index 0000000..89e8e09
--- /dev/null
+++ b/eval_handler.py
@@ -0,0 +1,49 @@
+import re
+from typing import List, Dict, Pattern
+import discord
+
+REPLACEMENTS: Dict[Pattern, str] = {
+ re.compile(r'<@!?(?P<id>[0-9]+)>'): '(guild.get_member({id}) or client.get_user({id}))',
+ re.compile(r'<#(?P<id>[0-9]+)>'): '(discord.utils.get(all_channels, id={id}))',
+ re.compile(r'<@&(?P<id>[0-9]+)>'): '(discord.utils.get(all_roles, id={id}))',
+ # Maybe later emoji support
+}
+
+
+async def handle_eval(message: discord.Message, client: discord.Client):
+ content: str = message.content
+ command_start: int = content.find(' ')
+ channel: discord.TextChannel = message.channel
+ author: discord.Member = message.author
+
+ all_channels: List[discord.Guild] = []
+ all_roles: List[discord.Role] = []
+ for guild in client.guilds:
+ guild: discord.Guild = guild # for type hints
+ all_channels += guild.channels
+ all_roles += guild.roles
+
+ variables = {
+ 'message': message,
+ 'author': author,
+ 'channel': channel,
+ 'all_channels': all_channels,
+ 'all_roles': all_roles,
+ 'client': client,
+ 'discord': discord,
+ }
+ lines: List[str] = content[command_start:].strip().split('\n')
+ lines[-1] = 'return ' + lines[-1]
+ block: str = '\n'.join(' ' + line for line in lines)
+ code = f"async def code({', '.join(variables.keys())}):\n" \
+ f"{block}"
+
+ for regex, replacement in REPLACEMENTS.items():
+ code = re.sub(regex, lambda match: replacement.format(**match.groupdict()), code)
+
+ _globals, _locals = {}, {}
+ exec(code, _globals, _locals)
+ result = {**_globals, **_locals}
+ result = await result["code"](**variables)
+
+ return await channel.send("Evaluation success: ```tr\n%r\n```" % result)
diff --git a/main.py b/main.py
index 942c774..6385fa5 100644
--- a/main.py
+++ b/main.py
@@ -6,6 +6,8 @@ from discord import Object
from discord.ext import commands
import discord
+from eval_handler import handle_eval
+
bot = commands.Bot(
command_prefix='~',
self_bot=True,
@@ -20,7 +22,7 @@ banned_guilds = [
def check_guild(func):
@wraps(func)
async def wrapper(ctx: commands.Context, *args, **kwargs):
- if ctx.guild.id in banned_guilds:
+ if ctx.guild is not None and ctx.guild.id in banned_guilds:
return
return await func(ctx, *args, **kwargs)
@@ -64,6 +66,13 @@ def get_with_attr(arr, **attributes):
return list(_get_with_attr())
+@bot.command(name="eval", pass_context=True)
+async def eval_command(ctx: commands.Context):
+ await handle_eval(message=ctx.message,
+ client=bot,
+ )
+
+
@bot.command(name="channel", pass_context=True)
@check_guild
async def channel_cmd(ctx: commands.Context, channel: discord.TextChannel = None):
@@ -123,7 +132,7 @@ async def user_cmd(ctx: commands.Context, identifier):
em.set_thumbnail(url=discord_profile.avatar_url)
em.add_field(name='Joined Discord', value=discord_profile.created_at, inline=True)
guild: discord.Guild = ctx.guild
- if guild.get_member(identifier) is not None:
+ if guild is not None and guild.get_member(identifier) is not None:
member: discord.Member = guild.get_member(identifier)
em.colour = member.color
em.add_field(name="Permissions", value=dump_perms(member.guild_permissions), inline=True)