mirror of
https://github.com/osmarks/autobotrobot
synced 2025-02-07 12:40:00 +00:00
improve, deliver, create, develop, design, operate, manage, produce, modernize, complicate, nationalize, placate, evolve, alter, amend, change or obliterate code
This commit is contained in:
parent
c1b5007d33
commit
d9c7df8d23
@ -45,7 +45,7 @@ async def achieve(bot: commands.Bot, message: discord.Message, achievement):
|
||||
metrics.achievements_achieved.inc()
|
||||
await bot.database.execute("INSERT INTO achievements VALUES (?, ?, ?)", (uid, achievement, util.timestamp()))
|
||||
await bot.database.commit()
|
||||
logging.info("Awarded achievement %s to %s", message.author.name, achievement)
|
||||
logging.info("Awarded achievement %s to %s", achievement, message.author.name)
|
||||
|
||||
def setup(bot):
|
||||
@bot.group(name="achievements", aliases=["ach", "achieve", "achievement"], brief="Achieve a wide variety of fun achievements!", help=f"""
|
||||
|
@ -1,53 +1,59 @@
|
||||
import subprocess
|
||||
import asyncio
|
||||
import argparse
|
||||
import random
|
||||
from numpy.random import default_rng
|
||||
import re
|
||||
import discord.ext.commands
|
||||
import aiohttp
|
||||
import discord.ext.commands as commands
|
||||
|
||||
import tio
|
||||
import util
|
||||
|
||||
def setup(bot):
|
||||
cleaner = discord.ext.commands.clean_content()
|
||||
def clean(ctx, text):
|
||||
return cleaner.convert(ctx, text)
|
||||
cleaner = commands.clean_content()
|
||||
def clean(ctx, text):
|
||||
return cleaner.convert(self, ctx, text)
|
||||
|
||||
@bot.command(help="Gives you a random fortune as generated by `fortune`.")
|
||||
async def fortune(ctx):
|
||||
await ctx.send(subprocess.run(["fortune"], stdout=subprocess.PIPE, encoding="UTF-8").stdout)
|
||||
class GeneralCommands(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.session = aiohttp.ClientSession()
|
||||
|
||||
@bot.command(help="Generates an apioform type.")
|
||||
async def apioform(ctx):
|
||||
@commands.command(help="Gives you a random fortune as generated by `fortune`.")
|
||||
async def fortune(self, ctx):
|
||||
proc = await asyncio.create_subprocess_exec("fortune", stdout=subprocess.PIPE)
|
||||
stdout = (await proc.communicate()).decode("utf-8")
|
||||
await ctx.send(stdout)
|
||||
|
||||
@commands.command(help="Generates an apioform type.")
|
||||
async def apioform(self, ctx):
|
||||
await ctx.send(util.apioform())
|
||||
|
||||
@bot.command(help="Says Pong.")
|
||||
async def ping(ctx):
|
||||
@commands.command(help="Says Pong.")
|
||||
async def ping(self, ctx):
|
||||
await ctx.send("Pong.")
|
||||
|
||||
@bot.command(help="Deletes the specified target.", rest_is_raw=True)
|
||||
async def delete(ctx, *, raw_target):
|
||||
target = await clean(ctx, raw_target.strip().replace("\n", " "))
|
||||
@commands.command(help="Deletes the specified target.", rest_is_raw=True)
|
||||
async def delete(self, ctx, *, raw_target):
|
||||
target = await clean(self, ctx, raw_target.strip().replace("\n", " "))
|
||||
if len(target) > 256:
|
||||
await ctx.send(embed=util.error_embed("Deletion target must be max 256 chars"))
|
||||
return
|
||||
async with ctx.typing():
|
||||
await ctx.send(f"Deleting {target}...")
|
||||
await asyncio.sleep(1)
|
||||
await bot.database.execute("INSERT INTO deleted_items (timestamp, item) VALUES (?, ?)", (util.timestamp(), target))
|
||||
await bot.database.commit()
|
||||
await self.bot.database.execute("INSERT INTO deleted_items (timestamp, item) VALUES (?, ?)", (util.timestamp(), target))
|
||||
await self.bot.database.commit()
|
||||
await ctx.send(f"Deleted {target} successfully.")
|
||||
|
||||
@bot.command(help="View recently deleted things, optionally matching a filter.")
|
||||
async def list_deleted(ctx, search=None):
|
||||
@commands.command(help="View recently deleted things, optionally matching a filter.")
|
||||
async def list_deleted(self, ctx, search=None):
|
||||
acc = "Recently deleted:\n"
|
||||
if search: acc = f"Recently deleted (matching {search}):\n"
|
||||
csr = None
|
||||
if search:
|
||||
csr = bot.database.execute("SELECT * FROM deleted_items WHERE item LIKE ? ORDER BY timestamp DESC LIMIT 100", (f"%{search}%",))
|
||||
csr = self.bot.database.execute("SELECT * FROM deleted_items WHERE item LIKE ? ORDER BY timestamp DESC LIMIT 100", (f"%{search}%",))
|
||||
else:
|
||||
csr = bot.database.execute("SELECT * FROM deleted_items ORDER BY timestamp DESC LIMIT 100")
|
||||
csr = self.bot.database.execute("SELECT * FROM deleted_items ORDER BY timestamp DESC LIMIT 100")
|
||||
async with csr as cursor:
|
||||
async for row in cursor:
|
||||
to_add = "- " + row[2].replace("```", "[REDACTED]") + "\n"
|
||||
@ -70,8 +76,8 @@ def setup(bot):
|
||||
exec_flag_parser.add_argument("--verbose", "-v", action="store_true")
|
||||
exec_flag_parser.add_argument("--language", "-L")
|
||||
|
||||
@bot.command(rest_is_raw=True, help="Execute provided code (in a codeblock) using TIO.run.")
|
||||
async def exec(ctx, *, arg):
|
||||
@commands.command(rest_is_raw=True, help="Execute provided code (in a codeblock) using TIO.run.")
|
||||
async def exec(self, ctx, *, arg):
|
||||
match = re.match(EXEC_REGEX, arg, flags=re.DOTALL)
|
||||
if match == None:
|
||||
await ctx.send(embed=util.error_embed("Invalid format. Expected a codeblock."))
|
||||
@ -86,7 +92,7 @@ def setup(bot):
|
||||
code = match.group(3)
|
||||
|
||||
async with ctx.typing():
|
||||
ok, real_lang, result, debug = await tio.run(lang, code)
|
||||
ok, real_lang, result, debug = await tio.run(self.session, lang, code)
|
||||
if not ok:
|
||||
await ctx.send(embed=util.error_embed(util.gen_codeblock(result), "Execution failed"))
|
||||
else:
|
||||
@ -98,9 +104,9 @@ def setup(bot):
|
||||
out = out[:2000]
|
||||
await ctx.send(out)
|
||||
|
||||
@bot.command(help="List supported languages, optionally matching a filter.")
|
||||
async def supported_langs(ctx, search=None):
|
||||
langs = sorted(tio.languages())
|
||||
@commands.command(help="List supported languages, optionally matching a filter.")
|
||||
async def supported_langs(self, ctx, search=None):
|
||||
langs = sorted(await tio.languages(self.session))
|
||||
acc = ""
|
||||
for lang in langs:
|
||||
if len(acc + lang) > 2000:
|
||||
@ -110,18 +116,18 @@ def setup(bot):
|
||||
if acc == "": acc = "No results."
|
||||
await ctx.send(acc)
|
||||
|
||||
@bot.command(help="Get some information about the bot.", aliases=["invite"])
|
||||
async def about(ctx):
|
||||
@commands.command(help="Get some information about the bot.", aliases=["invite"])
|
||||
async def about(self, 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.
|
||||
It can execute code via TIO.run, do reminders, print fortunes, bridge IRC, store data, and search things!
|
||||
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>
|
||||
AutoBotRobot is operated by gollark/osmarks.
|
||||
""")
|
||||
|
||||
@bot.command(help="Roll simulated dice (basic NdX syntax, N <= 50, X <= 1e6).")
|
||||
async def roll(ctx, dice):
|
||||
@commands.command(help="Roll simulated dice (basic NdX syntax, N <= 50, X <= 1e6).")
|
||||
async def roll(self, ctx, dice):
|
||||
match = re.match("([-0-9]*)d([0-9]+)", dice)
|
||||
if not match: raise ValueError("Invalid dice notation")
|
||||
n, x = match.groups()
|
||||
@ -145,8 +151,8 @@ AutoBotRobot is operated by gollark/osmarks.
|
||||
|
||||
rng = default_rng()
|
||||
|
||||
@bot.command(help="'Randomly' choose between the specified options.", name="choice", aliases=["choose"])
|
||||
async def random_choice(ctx, *choices):
|
||||
@commands.command(help="'Randomly' choose between the specified options.", name="choice", aliases=["choose"])
|
||||
async def random_choice(self, ctx, *choices):
|
||||
choices = list(choices)
|
||||
samples = 1
|
||||
# apparently doing typing.Optional[int] doesn't work properly with this, so just bodge around it
|
||||
@ -169,3 +175,6 @@ AutoBotRobot is operated by gollark/osmarks.
|
||||
results = map(lambda t: (choices[t[0]], t[1]), enumerate(rng.multinomial(samples, list(probabilities))))
|
||||
|
||||
await ctx.send("\n".join(map(lambda x: f"{x[0]} x{x[1]}", results)))
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(GeneralCommands(bot))
|
@ -63,7 +63,7 @@ async def on_command_error(ctx, err):
|
||||
await ctx.send(embed=util.error_embed(util.gen_codeblock(trace), title=f"Internal error in {ctx.invoked_with}"))
|
||||
await achievement.achieve(ctx.bot, ctx.message, "error")
|
||||
except Exception as e:
|
||||
logging.exception("Error in error handling!", e)
|
||||
logging.exception("Error in command error handling.")
|
||||
|
||||
@bot.check
|
||||
async def andrew_bad(ctx):
|
||||
@ -107,8 +107,9 @@ async def run_bot():
|
||||
if __name__ == "__main__":
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.create_task(prometheus_async.aio.web.start_http_server(port=config["metrics_port"]))
|
||||
loop.create_task(run_bot())
|
||||
try:
|
||||
loop.run_until_complete(run_bot())
|
||||
loop.run_forever()
|
||||
except KeyboardInterrupt:
|
||||
loop.run_until_complete(bot.logout())
|
||||
sys.exit(0)
|
||||
|
12
src/tio.py
12
src/tio.py
@ -1,25 +1,21 @@
|
||||
import pytio
|
||||
import http3
|
||||
import gzip
|
||||
import io
|
||||
|
||||
tio = pytio.Tio()
|
||||
|
||||
def languages():
|
||||
return tio.query_languages()
|
||||
async def languages(http_session):
|
||||
return await (await http_session.get("https://tio.run/languages.json")).json()
|
||||
|
||||
aliases = {
|
||||
"python": "python3",
|
||||
"javascript": "javascript-node"
|
||||
}
|
||||
|
||||
client = http3.AsyncClient()
|
||||
|
||||
async def run(lang, code):
|
||||
async def run(http_session, lang, code):
|
||||
real_lang = aliases.get(lang, lang)
|
||||
req = pytio.TioRequest(real_lang, code)
|
||||
res = await client.post("https://tio.run/cgi-bin/run/api/", data=req.as_deflated_bytes(), timeout=65)
|
||||
content = res.content.decode("UTF-8")
|
||||
res = await (await http_session.post("https://tio.run/cgi-bin/run/api/", data=req.as_deflated_bytes(), timeout=65)).text()
|
||||
split = list(filter(lambda x: x != "\n" and x != "", content.split(content[:16])))
|
||||
if len(split) == 1:
|
||||
return False, real_lang, split[0], None
|
||||
|
@ -18,7 +18,7 @@ config = {}
|
||||
|
||||
# update in place for runtime config reload
|
||||
def load_config():
|
||||
for k, v in toml.load(open("config.toml", "r")).items(): config[k] = v
|
||||
for k, v in toml.load(open(os.path.join(os.path.dirname(__file__), "../config.toml"), "r")).items(): config[k] = v
|
||||
|
||||
load_config()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user