1
0
mirror of https://github.com/osmarks/autobotrobot synced 2025-01-21 12:46:53 +00:00

debug commands for owner

This commit is contained in:
osmarks 2020-06-18 19:43:20 +01:00
parent 6db8a42318
commit c9897729c2
2 changed files with 98 additions and 13 deletions

View File

@ -8,6 +8,7 @@ import re
import asyncio
import json
import argparse
import traceback
from datetime import timezone, datetime
import tio
@ -23,7 +24,7 @@ config = toml.load(open("config.toml", "r"))
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(asctime)s %(message)s", datefmt="%H:%M:%S %d/%m/%Y")
bot = commands.Bot(command_prefix='++', description="AutoBotRobot, the most useless bot in the known universe.", case_insensitive=True)
bot = commands.Bot(command_prefix=config["prefix"], description="AutoBotRobot, the most useless bot in the known universe.", case_insensitive=True)
bot._skip_check = lambda x, y: False
def make_embed(*, fields=[], footer_text=None, **kwargs):
@ -136,7 +137,9 @@ async def supported_langs(ctx, search=None):
if acc == "": acc = "No results."
await ctx.send(acc)
@bot.command(help="Set a reminder. All times are UTC. Reminders are only checked once per minute.", rest_is_raw=True)
@bot.command(brief="Set a reminder to be reminded about later.", rest_is_raw=True, help="""Sets a reminder which you will (probably) be reminded about at/after the specified time.
All times are UTC.
Reminders are checked every minute, so while precise times are not guaranteed, reminders should under normal conditions be received within 2 minutes of what you specify.""")
async def remind(ctx, time, *, reminder):
reminder = reminder.strip()
if len(reminder) > 512:
@ -147,7 +150,11 @@ async def remind(ctx, time, *, reminder):
"channel_id": ctx.message.channel.id,
"original_time_spec": time
}
time = util.parse_time(time)
try:
time = util.parse_time(time)
except:
await ctx.send(embed=error_embed("Invalid time"))
return
await database.execute("INSERT INTO reminders (remind_timestamp, created_timestamp, reminder, expired, extra) VALUES (?, ?, ?, ?, ?)",
(time.timestamp(), timestamp(), reminder, 0, json.dumps(extra_data)))
await database.commit()
@ -176,10 +183,53 @@ async def remind_worker():
await database.execute("UPDATE reminders SET expired = 1 WHERE id = ?", (expiry_id,))
await database.commit()
@bot.command(help="Get some information about the bot.")
async def about(ctx):
await ctx.send("""**AutoBotRobot: The least useful Discord bot ever designed.**
AutoBotRobot has many features, but not necessarily any practical ones.
It can execute code via TIO.run, do reminders, print fortunes, and not any more!
AutoBotRobot is open source - the code is available at <https://github.com/osmarks/autobotrobot> - and you could run your own instance if you wanted to and could get around the complete lack of user guide or documentation.
You can also invite it to your server: <https://discordapp.com/oauth2/authorize?&client_id=509849474647064576&scope=bot&permissions=68608>
""")
@bot.group()
async def magic(ctx):
if not await bot.is_owner(ctx.author):
return await ctx.send(embed=error_embed(f"{ctx.author.name} is not in the sudoers file. This incident has been reported."))
if ctx.invoked_subcommand == None:
return await ctx.send("Invalid magic command.")
@magic.command(rest_is_raw=True)
async def py(ctx, *, code):
code = util.extract_codeblock(code)
try:
loc = {
**locals(),
"bot": bot,
"ctx": ctx,
}
result = await asyncio.wait_for(util.async_exec(code, loc, globals()), timeout=5.0)
await ctx.send("```\n" + repr(result).replace("```", "\\`\\`\\`")[:1900] + "\n```")
except TimeoutError:
await ctx.send(embed=error_embed("Timed out."))
except BaseException as e:
await ctx.send("Error:\n```\n" + traceback.format_exc().replace("```", "\\`\\`\\`")[:1900] + "\n```")
@magic.command(rest_is_raw=True)
async def sql(ctx, *, code):
code = util.extract_codeblock(code)
csr = database.execute(code)
out = ""
async with csr as cursor:
async for row in cursor:
out += "`" + " ".join(map(repr, row)) + "`\n"
await ctx.send(out[:1999])
await database.commit()
@bot.event
async def on_ready():
logging.info("Connected as " + bot.user.name)
await bot.change_presence(status=discord.Status.online, activity=discord.Activity(type=discord.ActivityType.listening, name="commands beginning with ++"))
await bot.change_presence(status=discord.Status.online, activity=discord.Activity(type=discord.ActivityType.listening, name=f"commands beginning with {config['prefix']}"))
remind_worker.start()
async def run_bot():
@ -195,4 +245,4 @@ if __name__ == '__main__':
remind_worker.cancel()
loop.run_until_complete(bot.logout())
finally:
loop.close()
loop.close()

View File

@ -1,17 +1,19 @@
import re
import datetime
import parsedatetime
import ast
import copy
from dateutil.relativedelta import relativedelta
# from here: https://github.com/Rapptz/RoboDanny/blob/18b92ae2f53927aedebc25fb5eca02c8f6d7a874/cogs/utils/time.py
short_timedelta_regex = re.compile("""
(?:(?P<years>[0-9])(?:years?|y))? # e.g. 2y
(?:(?P<months>[0-9]{1,2})(?:months?|mo))? # e.g. 2months
(?:(?P<weeks>[0-9]{1,4})(?:weeks?|w))? # e.g. 10w
(?:(?P<days>[0-9]{1,5})(?:days?|d))? # e.g. 14d
(?:(?P<hours>[0-9]{1,5})(?:hours?|h))? # e.g. 12h
(?:(?P<minutes>[0-9]{1,6})(?:minutes?|m))? # e.g. 10m
(?:(?P<seconds>[0-9]{1,7})(?:seconds?|s))? # e.g. 15s """, re.VERBOSE)
(?:(?P<years>[0-9]{1,8})(?:years?|y))? # e.g. 2y
(?:(?P<months>[0-9]{1,8})(?:months?|mo))? # e.g. 2months
(?:(?P<weeks>[0-9]{1,8})(?:weeks?|w))? # e.g. 10w
(?:(?P<days>[0-9]{1,8})(?:days?|d))? # e.g. 14d
(?:(?P<hours>[0-9]{1,8})(?:hours?|h))? # e.g. 12h
(?:(?P<minutes>[0-9]{1,8})(?:minutes?|m))? # e.g. 10m
(?:(?P<seconds>[0-9]{1,8})(?:seconds?|s))? # e.g. 15s """, re.VERBOSE)
def parse_short_timedelta(text):
match = short_timedelta_regex.fullmatch(text)
@ -35,4 +37,37 @@ def parse_time(text):
raise ValueError("could not parse time")
def format_time(dt):
return dt.strftime("%H:%M:%S %d/%m/%Y")
return dt.strftime("%H:%M:%S %d/%m/%Y")
CODEBLOCK_REGEX = "^[^`]*```[a-zA-Z0-9_\-+]*\n(.+)```$"
CODELINE_REGEX = "^[^`]*`(.*)`$"
def extract_codeblock(s):
match1 = re.match(CODEBLOCK_REGEX, s, flags=re.DOTALL)
match2 = re.match(CODELINE_REGEX, s, flags=re.DOTALL)
if match1: return match1.group(1)
elif match2: return match2.group(1)
else:
return s.strip()
# from https://github.com/Gorialis/jishaku/blob/master/jishaku/repl/compilation.py
CORO_CODE = """
async def repl_coroutine():
import asyncio
import aiohttp
import discord
from discord.ext import commands
"""
async def async_exec(code, loc, glob):
user_code = ast.parse(code, mode='exec')
wrapper = ast.parse(CORO_CODE, mode='exec')
funcdef = wrapper.body[-1]
funcdef.body.extend(user_code.body)
last_expr = funcdef.body[-1]
if isinstance(last_expr, ast.Expr):
funcdef.body.pop()
funcdef.body.append(ast.Return(last_expr.value))
ast.fix_missing_locations(wrapper)
exec(compile(wrapper, "<repl>", "exec"), loc, glob)
return await (loc.get("repl_coroutine") or glob.get("repl_coroutine"))()