2020-10-11 13:40:39 +00:00
import asyncio
import traceback
2021-01-14 09:38:32 +00:00
import re
2020-10-11 13:40:39 +00:00
from discord . ext import commands
2021-02-25 17:48:06 +00:00
2021-01-14 09:38:32 +00:00
import util
2021-02-25 17:48:06 +00:00
import eventbus
2020-10-11 13:40:39 +00:00
def setup ( bot ) :
2021-02-09 17:17:19 +00:00
@bot.group ( help = " Debug/random messing around utilities. Owner-only. " )
2021-01-14 09:38:32 +00:00
@commands.check ( util . admin_check )
2020-10-11 13:40:39 +00:00
async def magic ( ctx ) :
if ctx . invoked_subcommand == None :
return await ctx . send ( " Invalid magic command. " )
2021-02-09 17:17:19 +00:00
@magic.command ( rest_is_raw = True , brief = " Execute Python. " )
2020-10-11 13:40:39 +00:00
async def py ( ctx , * , code ) :
2021-02-09 17:17:19 +00:00
" Executes Python. You may supply a codeblock. Comments in the form #timeout:([0-9]+) will be used as a timeout specifier. React with :x: to stop, probably. "
2021-01-14 09:38:32 +00:00
timeout = 5.0
timeout_match = re . search ( " #timeout:([0-9]+) " , code , re . IGNORECASE )
if timeout_match :
timeout = int ( timeout_match . group ( 1 ) )
if timeout == 0 : timeout = None
2020-10-11 13:40:39 +00:00
code = util . extract_codeblock ( code )
try :
loc = {
* * locals ( ) ,
" bot " : bot ,
" ctx " : ctx ,
2021-02-25 17:48:06 +00:00
" db " : bot . database ,
" util " : util ,
" eventbus " : eventbus
2020-10-11 13:40:39 +00:00
}
2021-01-14 09:38:32 +00:00
def check ( re , u ) : return str ( re . emoji ) == " ❌ " and u == ctx . author
result = None
async def run ( ) :
nonlocal result
result = await util . async_exec ( code , loc , globals ( ) )
halt_task = asyncio . create_task ( bot . wait_for ( " reaction_add " , check = check ) )
exec_task = asyncio . create_task ( run ( ) )
done , pending = await asyncio . wait ( ( exec_task , halt_task ) , timeout = timeout , return_when = asyncio . FIRST_COMPLETED )
for task in done : task . result ( ) # get exceptions
for task in pending : task . cancel ( )
2020-10-11 13:40:39 +00:00
if result != None :
if isinstance ( result , str ) :
2021-01-14 09:38:32 +00:00
await ctx . send ( result [ : 2000 ] )
2020-10-11 13:40:39 +00:00
else :
await ctx . send ( util . gen_codeblock ( repr ( result ) ) )
2021-01-14 09:38:32 +00:00
except ( TimeoutError , asyncio . CancelledError ) :
2020-10-11 13:40:39 +00:00
await ctx . send ( embed = util . error_embed ( " Timed out. " ) )
except BaseException as e :
await ctx . send ( embed = util . error_embed ( util . gen_codeblock ( traceback . format_exc ( ) ) ) )
2021-02-09 17:17:19 +00:00
@magic.command ( rest_is_raw = True , help = " Execute SQL code against the database. " )
2020-10-11 13:40:39 +00:00
async def sql ( ctx , * , code ) :
2021-02-09 17:17:19 +00:00
" Executes SQL (and commits). You may use a codeblock, similarly to with py. "
2020-10-11 13:40:39 +00:00
code = util . extract_codeblock ( code )
try :
csr = bot . database . execute ( code )
out = " "
async with csr as cursor :
async for row in cursor :
out + = " " . join ( map ( repr , row ) ) + " \n "
await ctx . send ( util . gen_codeblock ( out ) )
await bot . database . commit ( )
except Exception as e :
2020-11-25 19:04:10 +00:00
await ctx . send ( embed = util . error_embed ( util . gen_codeblock ( traceback . format_exc ( ) ) ) )
2021-02-09 17:17:19 +00:00
@magic.command ( help = " Reload configuration file. " )
2020-11-25 19:04:10 +00:00
async def reload_config ( ctx ) :
util . load_config ( )
2021-03-25 17:56:29 +00:00
await ctx . send ( " Done! " )
2021-01-14 09:38:32 +00:00
2021-02-09 17:17:19 +00:00
@magic.command ( help = " Reload extensions (all or the specified one). " )
async def reload_ext ( ctx , ext = " all " ) :
if ext == " all " :
for ext in util . extensions : bot . reload_extension ( ext )
else : bot . reload_extension ( ext )
2022-01-18 23:56:11 +00:00
await ctx . send ( " Done! " )