1
0
mirror of https://github.com/osmarks/autobotrobot synced 2024-06-25 22:43:15 +00:00

New commands and stuff

- ++apioform
- ++random using py-rolldice
- ++choose - random choice with new AutoBias™ algorithm
- ban andrew
- minor general fixes
- cheat at esobot typeraces autonomously
This commit is contained in:
osmarks 2020-09-10 18:51:38 +01:00
parent ef993de7e3
commit 26f5247acf
2 changed files with 133 additions and 16 deletions

View File

@ -9,6 +9,8 @@ import asyncio
import json import json
import argparse import argparse
import traceback import traceback
import random
import rolldice
from datetime import timezone, datetime from datetime import timezone, datetime
import tio import tio
@ -45,10 +47,35 @@ cleaner = discord.ext.commands.clean_content()
def clean(ctx, text): def clean(ctx, text):
return cleaner.convert(ctx, text) return cleaner.convert(ctx, text)
@bot.event
async def on_message(message):
words = message.content.split(" ")
if len(words) == 10 and message.author.id == 435756251205468160:
await message.channel.send(util.unlyric(message.content))
else:
if message.author.id == bot.user.id: return
ctx = await bot.get_context(message)
if not ctx.valid: return
await bot.invoke(ctx)
@bot.event
async def on_command_error(ctx, err):
print(ctx, err)
if isinstance(err, commands.CommandNotFound, commands.CheckFailure): return
try:
trace = re.sub("\n\n+", "\n", "\n".join(traceback.format_exception(err, err, err.__traceback__)))
print(trace)
await ctx.send(embed=error_embed(gen_codeblock(trace), title="Internal error"))
except Exception as e: print("meta-error:", e)
@bot.command(help="Gives you a random fortune as generated by `fortune`.") @bot.command(help="Gives you a random fortune as generated by `fortune`.")
async def fortune(ctx): async def fortune(ctx):
await ctx.send(subprocess.run(["fortune"], stdout=subprocess.PIPE, encoding="UTF-8").stdout) await ctx.send(subprocess.run(["fortune"], stdout=subprocess.PIPE, encoding="UTF-8").stdout)
@bot.command(help="Generates an apioform type.")
async def apioform(ctx):
await ctx.send(util.apioform())
@bot.command(help="Says Pong.") @bot.command(help="Says Pong.")
async def ping(ctx): async def ping(ctx):
await ctx.send("Pong.") await ctx.send("Pong.")
@ -97,6 +124,9 @@ exec_flag_parser = NonExitingArgumentParser(add_help=False)
exec_flag_parser.add_argument("--verbose", "-v", action="store_true") exec_flag_parser.add_argument("--verbose", "-v", action="store_true")
exec_flag_parser.add_argument("--language", "-L") exec_flag_parser.add_argument("--language", "-L")
def gen_codeblock(content):
return "```\n" + content.replace("```", "\\`\\`\\`")[:1900] + "\n```"
@bot.command(rest_is_raw=True, help="Execute provided code (in a codeblock) using TIO.run.") @bot.command(rest_is_raw=True, help="Execute provided code (in a codeblock) using TIO.run.")
async def exec(ctx, *, arg): async def exec(ctx, *, arg):
match = re.match(EXEC_REGEX, arg, flags=re.DOTALL) match = re.match(EXEC_REGEX, arg, flags=re.DOTALL)
@ -115,11 +145,11 @@ async def exec(ctx, *, arg):
async with ctx.typing(): async with ctx.typing():
ok, real_lang, result, debug = await tio.run(lang, code) ok, real_lang, result, debug = await tio.run(lang, code)
if not ok: if not ok:
await ctx.send(embed=error_embed(f"""```{result}```""", "Execution error")) await ctx.send(embed=error_embed(gen_codeblock(result), "Execution failed"))
else: else:
out = result out = result
if flags.verbose: if flags.verbose:
debug_block = f"""\n```{debug}\nLanguage: {real_lang}```""" debug_block = "\n" + gen_codeblock(f"""{debug}\nLanguage: {real_lang}""")
out = out[:2000 - len(debug_block)] + debug_block out = out[:2000 - len(debug_block)] + debug_block
else: else:
out = out[:2000] out = out[:2000]
@ -143,11 +173,12 @@ Reminders are checked every minute, so while precise times are not guaranteed, r
async def remind(ctx, time, *, reminder): async def remind(ctx, time, *, reminder):
reminder = reminder.strip() reminder = reminder.strip()
if len(reminder) > 512: if len(reminder) > 512:
await ctx.send(embed=error_embed("Maximum reminder length is 512 characters")) await ctx.send(embed=error_embed("Maximum reminder length is 512 characters", "Foolish user error"))
return return
extra_data = { extra_data = {
"author_id": ctx.author.id, "author_id": ctx.author.id,
"channel_id": ctx.message.channel.id, "channel_id": ctx.message.channel.id,
"message_id": ctx.message.id,
"original_time_spec": time "original_time_spec": time
} }
try: try:
@ -192,12 +223,59 @@ AutoBotRobot is open source - the code is available at <https://github.com/osmar
You can also invite it to your server: <https://discordapp.com/oauth2/authorize?&client_id=509849474647064576&scope=bot&permissions=68608> You can also invite it to your server: <https://discordapp.com/oauth2/authorize?&client_id=509849474647064576&scope=bot&permissions=68608>
""") """)
@bot.command(help="Randomly generate an integer using dice syntax.", name="random", rest_is_raw=True)
async def random_int(ctx, *, dice):
await ctx.send(rolldice.roll_dice(dice)[0])
bad_things = ["lyric", "endos", "solarflame", "lyric", "319753218592866315", "andrew", "6", "c++"]
good_things = ["potato", "heav", "gollark", "helloboi", "bees", "hellboy", "rust", "ferris", "crab", "transistor"]
negations = ["not", "bad", "un", "kill", "n't"]
def weight(thing):
lthing = thing.lower()
weight = 1.0
if lthing == "c": weight *= 0.3
for bad_thing in bad_things:
if bad_thing in lthing: weight *= 0.5
for good_thing in good_things:
if good_thing in lthing: weight *= 2.0
for negation in negations:
for _ in range(lthing.count(negation)): weight = 1 / weight
return weight
@bot.command(help="'Randomly' choose between the specified options.", name="choice", aliases=["choose"])
async def random_choice(ctx, *choices):
choicelist = list(choices)
samples = 1
try:
samples = int(choices[0])
choicelist.pop(0)
except: pass
if samples > 1e5:
await ctx.send("No.")
return
choices = random.choices(choicelist, weights=map(weight, choicelist), k=samples)
if len(choices) == 1:
await ctx.send(choices[0])
else:
counts = {}
for choice in choices:
counts[choice] = counts.get(choice, 0) + 1
await ctx.send("\n".join(map(lambda x: f"{x[0]} x{x[1]}", counts.items())))
async def admin_check(ctx): async def admin_check(ctx):
if not await bot.is_owner(ctx.author): if not await bot.is_owner(ctx.author):
await ctx.send(embed=error_embed(f"{ctx.author.name} is not in the sudoers file. This incident has been reported.")) # apparently this has to be a pure function because ++help calls it for some reason because of course
#await ctx.send(embed=error_embed(f"{ctx.author.name} is not in the sudoers file. This incident has been reported."))
return False return False
return True return True
@bot.check
async def andrew_bad(ctx):
return ctx.message.author.id != 543131534685765673
@bot.group() @bot.group()
@commands.check(admin_check) @commands.check(admin_check)
async def magic(ctx): async def magic(ctx):
@ -212,14 +290,18 @@ async def py(ctx, *, code):
**locals(), **locals(),
"bot": bot, "bot": bot,
"ctx": ctx, "ctx": ctx,
"db": database
} }
result = await asyncio.wait_for(util.async_exec(code, loc, globals()), timeout=5.0) result = await asyncio.wait_for(util.async_exec(code, loc, globals()), timeout=5.0)
if result != None: if result != None:
await ctx.send("```\n" + repr(result).replace("```", "\\`\\`\\`")[:1900] + "\n```") if isinstance(result, str):
await ctx.send(result[:1999])
else:
await ctx.send(gen_codeblock(repr(result)))
except TimeoutError: except TimeoutError:
await ctx.send(embed=error_embed("Timed out.")) await ctx.send(embed=error_embed("Timed out."))
except BaseException as e: except BaseException as e:
await ctx.send("Error:\n```\n" + traceback.format_exc().replace("```", "\\`\\`\\`")[:1900] + "\n```") await ctx.send(embed=error_embed(gen_codeblock(traceback.format_exc())))
@magic.command(rest_is_raw=True) @magic.command(rest_is_raw=True)
async def sql(ctx, *, code): async def sql(ctx, *, code):
@ -230,10 +312,10 @@ async def sql(ctx, *, code):
async with csr as cursor: async with csr as cursor:
async for row in cursor: async for row in cursor:
out += " ".join(map(repr, row)) + "\n" out += " ".join(map(repr, row)) + "\n"
await ctx.send("```\n" + out[:1990] + "```") await ctx.send(gen_codeblock(out))
await database.commit() await database.commit()
except Exception as e: except Exception as e:
await ctx.send(embed=error_embed("```\n" + traceback.format_exc() + "```")) await ctx.send(embed=error_embed(gen_codeblock(traceback.format_exc())))
@bot.event @bot.event
async def on_ready(): async def on_ready():

View File

@ -3,17 +3,18 @@ import datetime
import parsedatetime import parsedatetime
import ast import ast
import copy import copy
import random
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
# from here: https://github.com/Rapptz/RoboDanny/blob/18b92ae2f53927aedebc25fb5eca02c8f6d7a874/cogs/utils/time.py # from here: https://github.com/Rapptz/RoboDanny/blob/18b92ae2f53927aedebc25fb5eca02c8f6d7a874/cogs/utils/time.py
short_timedelta_regex = re.compile(""" short_timedelta_regex = re.compile("""
(?:(?P<years>[0-9]{1,8})(?:years?|y))? # e.g. 2y (?:(?P<years>[0-9]{1,12})(?:years?|y))? # e.g. 2y
(?:(?P<months>[0-9]{1,8})(?:months?|mo))? # e.g. 2months (?:(?P<months>[0-9]{1,12})(?:months?|mo))? # e.g. 2months
(?:(?P<weeks>[0-9]{1,8})(?:weeks?|w))? # e.g. 10w (?:(?P<weeks>[0-9]{1,12})(?:weeks?|w))? # e.g. 10w
(?:(?P<days>[0-9]{1,8})(?:days?|d))? # e.g. 14d (?:(?P<days>[0-9]{1,12})(?:days?|d))? # e.g. 14d
(?:(?P<hours>[0-9]{1,8})(?:hours?|h))? # e.g. 12h (?:(?P<hours>[0-9]{1,12})(?:hours?|h))? # e.g. 12h
(?:(?P<minutes>[0-9]{1,8})(?:minutes?|m))? # e.g. 10m (?:(?P<minutes>[0-9]{1,12})(?:minutes?|m))? # e.g. 10m
(?:(?P<seconds>[0-9]{1,8})(?:seconds?|s))? # e.g. 15s """, re.VERBOSE) (?:(?P<seconds>[0-9]{1,12})(?:seconds?|s))? # e.g. 15s """, re.VERBOSE)
def parse_short_timedelta(text): def parse_short_timedelta(text):
match = short_timedelta_regex.fullmatch(text) match = short_timedelta_regex.fullmatch(text)
@ -71,3 +72,37 @@ async def async_exec(code, loc, glob):
exec(compile(wrapper, "<repl>", "exec"), loc, glob) exec(compile(wrapper, "<repl>", "exec"), loc, glob)
return await (loc.get("repl_coroutine") or glob.get("repl_coroutine"))() return await (loc.get("repl_coroutine") or glob.get("repl_coroutine"))()
# https://github.com/LyricLy/Esobot/blob/bcc9e548c84ea9b23fc832d0b0aaa8288de64886/cogs/general.py
lyrictable_raw = {
"a": "а",
"c": "с",
"e": "е",
"s": "ѕ",
"i": "і",
"j": "ј",
"o": "о",
"p": "р",
"y": "у",
"x": "х"
}
lyrictable = str.maketrans({v: k for k, v in lyrictable_raw.items()})
apioprefixes = ["cryo", "meta", "chrono", "contra", "ortho", "macro", "micro"]
apioinfixes = ["cryo", "pyro", "chrono", "meta", "anarcho", "arachno", "aqua",
"hydro", "radio", "xeno", "morto", "thanato", "memeto", "contra", "umbra", "macrono"]
apiosuffixes = ["hazard", "form"]
def apioform():
out = ""
if random.randint(0, 4) == 0:
out += random.choice(apioprefixes)
out += "apio"
while True:
out += random.choice(apioinfixes)
if random.randint(0, 1) == 0: break
out += random.choice(apiosuffixes)
return out
def unlyric(text):
return text.translate(lyrictable).replace("\u200b", "")