1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
import asyncio
import os
import re
from typing import List, Dict, Pattern
import discord
from discord import Embed, Color, Message
from discord.ext import commands
from discord.ext.commands import Context as CommandContext, Bot
from config import config
from utils import load_all_modules
REPLACEMENTS: Dict[Pattern, str] = {
re.compile(r'<@!?(?P<id>[0-9]+)>'): '(guild.get_member({id}) if guild is not None else 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, to_eval: str):
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,
'os': os,
'github': config.github.github,
'print': (lambda *text: client.loop.create_task(channel.send(' '.join(text)))),
'guild': channel.guild if hasattr(channel, 'guild') else None,
}
lines: List[str] = to_eval.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 = {}, {}
try:
exec(code, _globals, _locals)
except Exception as e:
await message.channel.send(
embed=discord.Embed(color=discord.Color.red(), description="Compiler Error: `%s`" % (str(e))))
return
result = {**_globals, **_locals}
try:
result = await result["code"](**variables)
except Exception as e:
await message.channel.send(
embed=discord.Embed(color=discord.Color.red(), description="Runtime Error: `%s`" % (str(e))))
return
return await channel.send(
embed=Embed(
color=Color.red(),
description="📥 Evaluation success: ```py\n%r\n```" % result))
class AdminCog(object):
def __init__(self, bot: commands.Bot):
self.bot: commands.Bot = bot
# noinspection PyMethodMayBeStatic
async def on_ready(self):
print('Logged in.')
@commands.command()
async def eval(self, ctx: CommandContext, *, to_eval: str = None):
if to_eval is None:
return await ctx.send(
embed=Embed(
description="<Insert generic insult about your stupidity here>",
color=Color.red()))
await handle_eval(ctx.message, self.bot, to_eval)
@commands.command()
async def reload(self, ctx: CommandContext, *extensions):
for extension in (extensions or self.bot.extensions.copy().keys()):
self.bot.unload_extension(extension)
messages: List[Message] = [
await ctx.send(
embed=Embed(
color=Color.red(),
description='Unloaded extensions')),
ctx.message]
if len(extensions) == 0:
load_all_modules(self.bot)
else:
for extension in extensions:
try:
self.bot.load_extension(extension)
except:
messages.append(
await ctx.send(
embed=Embed(
title=f"Failed to load module `{extension}`",
color=Color.red())))
messages.append(
await ctx.send(
embed=Embed(
title=f"Reloaded {len(extensions) or len(self.bot.extensions)} extension(s)",
color=Color.green())))
await asyncio.sleep(10)
for mes in messages:
await mes.delete()
def setup(bot: Bot):
bot.add_cog(AdminCog(bot))
|