mirror of
https://github.com/osmarks/autobotrobot
synced 2024-06-13 16:56:54 +00:00
129 lines
4.1 KiB
Python
129 lines
4.1 KiB
Python
|
import discord
|
||
|
import toml
|
||
|
import logging
|
||
|
import subprocess
|
||
|
import discord.ext.commands as commands
|
||
|
import re
|
||
|
import asyncio
|
||
|
import json
|
||
|
|
||
|
import tio
|
||
|
|
||
|
data = {}
|
||
|
data_file = "bot-data.json"
|
||
|
|
||
|
def save_data():
|
||
|
try:
|
||
|
with open(data_file, "w") as f:
|
||
|
global data
|
||
|
json.dump(data, f)
|
||
|
except Exception as e:
|
||
|
logging.error(f"Error saving data file: {repr(e)}.")
|
||
|
|
||
|
def load_data():
|
||
|
try:
|
||
|
with open(data_file, "r") as f:
|
||
|
global data
|
||
|
data = json.load(f)
|
||
|
except Exception as e:
|
||
|
logging.warning(f"Error loading data file: {repr(e)}. This is not a critical error.")
|
||
|
|
||
|
load_data()
|
||
|
|
||
|
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(asctime)s %(message)s", datefmt="%H:%M:%S %d/%m/%Y")
|
||
|
|
||
|
config = toml.load(open("config.toml", "r"))
|
||
|
|
||
|
bot = commands.Bot(command_prefix='++', description="AutoBotRobot, the most useless bot in the known universe.", case_insensitive=True)
|
||
|
bot._skip_check = lambda x, y: False
|
||
|
|
||
|
cleaner = discord.ext.commands.clean_content()
|
||
|
def clean(ctx, text):
|
||
|
return cleaner.convert(ctx, text)
|
||
|
|
||
|
@bot.event
|
||
|
async def on_ready():
|
||
|
await bot.change_presence(status=discord.Status.online, activity=discord.Activity(type=discord.ActivityType.listening, name="commands beginning with ++"))
|
||
|
|
||
|
@bot.event
|
||
|
async def on_message(message):
|
||
|
print(message.content)
|
||
|
await bot.process_commands(message)
|
||
|
|
||
|
@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)
|
||
|
|
||
|
@bot.command(help="Says Pong.")
|
||
|
async def ping(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())
|
||
|
async with ctx.typing():
|
||
|
await ctx.send(f"Deleting {target}...")
|
||
|
await asyncio.sleep(1)
|
||
|
deleted = data.get("deleted", [])
|
||
|
data["deleted"] = deleted + [target]
|
||
|
save_data()
|
||
|
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):
|
||
|
acc = "Recently deleted:\n"
|
||
|
for thing in reversed(data.get("deleted", [])):
|
||
|
to_add = "- " + thing + "\n"
|
||
|
if len(acc + to_add) > 2000:
|
||
|
break
|
||
|
if search == None or search in thing: acc += to_add
|
||
|
await ctx.send(acc)
|
||
|
|
||
|
EXEC_REGEX = "^(.*)\n```([a-zA-Z0-9_\\-+]+)\n(.*)```$"
|
||
|
|
||
|
def make_embed(*, fields=[], footer_text=None, **kwargs):
|
||
|
embed = discord.Embed(**kwargs)
|
||
|
for field in fields:
|
||
|
if len(field) > 2:
|
||
|
embed.add_field(name=field[0], value=field[1], inline=field[2])
|
||
|
else:
|
||
|
embed.add_field(name=field[0], value=field[1], inline=False)
|
||
|
if footer_text:
|
||
|
embed.set_footer(text=footer_text)
|
||
|
return embed
|
||
|
|
||
|
def error_embed(msg, title="Error"):
|
||
|
return make_embed(color=config["colors"]["error"], description=msg, title=title)
|
||
|
|
||
|
@bot.command(rest_is_raw=True, help="Execute provided code (in a codeblock) using TIO.run.")
|
||
|
async def exec(ctx, *, arg):
|
||
|
match = re.match(EXEC_REGEX, arg, flags=re.DOTALL)
|
||
|
if match == None:
|
||
|
await ctx.send(embed=error_embed("Invalid format. Expected a codeblock with language."))
|
||
|
return
|
||
|
flags = match.group(1)
|
||
|
lang = match.group(2)
|
||
|
code = match.group(3)
|
||
|
|
||
|
async with ctx.typing():
|
||
|
ok, result, debug = await tio.run(lang, code)
|
||
|
if not ok:
|
||
|
await ctx.send(embed=error_embed(result, "Execution error"))
|
||
|
else:
|
||
|
out = result
|
||
|
if "debug" in flags: out += debug
|
||
|
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())
|
||
|
acc = ""
|
||
|
for lang in langs:
|
||
|
if len(acc + lang) > 2000:
|
||
|
await ctx.send(acc)
|
||
|
acc = ""
|
||
|
if search == None or search in lang: acc += lang + " "
|
||
|
await ctx.send(acc)
|
||
|
|
||
|
bot.run(config["token"])
|