This repository has been archived by the owner on Aug 4, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
code2.py
173 lines (167 loc) · 6.72 KB
/
code2.py
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
from discord.ext import commands
import time
import datetime
import math
import asyncio
import traceback
import discord
import inspect
import textwrap
from contextlib import redirect_stdout
import io
from simplepaginator import SimplePaginator
import quantumutils as utils
import json
oof=json.loads(open("configs.json").read())["hierarchy"]
allowed=oof["owner"]+oof["collaborators"]
class REPL():
'''custom command execution commands'''
def __init__(self, bot):
self.bot = bot
self._last_result = None
self.sessions = set()
def cleanup_code(self, content):
'Automatically removes code blocks from the code.'
if content.startswith('```') and content.endswith('```'):
return '\n'.join(content.split('\n')[1:(- 1)])
return content.strip('` \n')
def get_syntax_error(self, e):
if e.text is None:
return '```py\n{0.__class__.__name__}: {0}\n```'.format(e)
return '```py\n{0.text}{1:>{0.offset}}\n{2}: {0}```'.format(e, '^', type(e).__name__)
@commands.command(name='exec')
async def _eval(self, ctx, *, body: str):
'''for bot owner to execute statements'''
if ctx.author.id not in allowed:
return
env = {
'bot': self.bot,
'ctx': ctx,
'channel': ctx.channel,
'author': ctx.author,
'server': ctx.guild,
'message': ctx.message,
'_': self._last_result,
}
env.update(globals())
body = self.cleanup_code(body)
stdout = io.StringIO()
to_compile = 'async def func():\n%s' % textwrap.indent(body, ' ')
try:
exec(to_compile, env)
except SyntaxError as e:
return await ctx.send(self.get_syntax_error(e))
func = env['func']
try:
with redirect_stdout(stdout):
start=datetime.datetime.now()
ret = await func()
except Exception as e:
end=datetime.datetime.now()
time_diff=(end-start).microseconds/1000
await ctx.message.add_reaction('\u274C')
value = stdout.getvalue()
value=('py\n{}{}\n'.format(value, traceback.format_exc()))
sendlist = list(map(lambda x: "```" + x + "```", utils.partition(value, 1950)))
see = ""
embedlist = []
for i in range(len(sendlist)):
embedlist.append(
discord.Embed(title="Page {}/{} of error".format(i + 1, len(sendlist)), description=sendlist[i],
colour=discord.Colour.red()).set_footer(text="Executed in {}ms".format(time_diff)))
await SimplePaginator(extras=embedlist).paginate(ctx)
else:
end=datetime.datetime.now()
time_diff=(end-start).microseconds/1000
value = stdout.getvalue()
try:
await ctx.message.add_reaction('\u2705')
except:
pass
sendable=""
if ret is None:
if value:
sendable=value
else:
self._last_result = ret
sendable=str(value)+str(ret)
sendlist=list(map(lambda x: "```"+x+"```",utils.partition(sendable,1950)))
see=""
embedlist=[]
for i in range(len(sendlist)):
embedlist.append(
discord.Embed(title="Page {}/{} of output".format(i + 1, len(sendlist)), description=sendlist[i],
colour=discord.Colour.blurple()).set_footer(
text="Executed in {} ms".format(time_diff)))
await SimplePaginator(extras=embedlist).paginate(ctx)
@commands.command()
async def repl(self, ctx):
'''for bot owner to run series of commands'''
if ctx.author.id not in allowed:
return
msg = ctx.message
variables = {
'ctx': ctx,
'bot': self.bot,
'message': msg,
'server': msg.guild,
'channel': msg.channel,
'author': msg.author,
'_': None,
}
if msg.channel.id in self.sessions:
await ctx.send('Already running a REPL session in this channel. Exit it with `quit`.')
return
self.sessions.add(msg.channel.id)
await ctx.send('Enter code to execute or evaluate. `exit()` or `quit` to exit.')
while True:
response = await self.bot.wait_for('message', check=(lambda m: m.content.startswith('`') and m.author.id == ownerid and m.channel == ctx.channel))
cleaned = self.cleanup_code(response.content)
if cleaned in ('quit', 'exit', 'exit()'):
await ctx.send('Exiting.')
self.sessions.remove(msg.channel.id)
return
executor = exec
if cleaned.count('\n') == 0:
try:
code = compile(cleaned, '<repl session>', 'eval')
except SyntaxError:
pass
else:
executor = eval
if executor is exec:
try:
code = compile(cleaned, '<repl session>', 'exec')
except SyntaxError as e:
await ctx.send(self.get_syntax_error(e))
continue
variables['message'] = response
fmt = None
stdout = io.StringIO()
try:
with redirect_stdout(stdout):
result = executor(code, variables)
if inspect.isawaitable(result):
result = await result
except Exception as e:
value = stdout.getvalue()
fmt = '```py\n{}{}\n```'.format(value, traceback.format_exc())
else:
value = stdout.getvalue()
if result is not None:
fmt = '```py\n{}{}\n```'.format(value, result)
variables['_'] = result
elif value:
fmt = '```py\n{}\n```'.format(value)
try:
if fmt is not None:
if len(fmt) > 2000:
await msg.channel.send('Content too big to be printed.')
else:
await msg.channel.send(fmt)
except discord.Forbidden:
pass
except discord.HTTPException as e:
await msg.channel.send('Unexpected error: `{}`'.format(e))
def setup(bot):
bot.add_cog(REPL(bot))