autobotrobot/src/main.py

147 lines
6.0 KiB
Python
Raw Normal View History

2019-10-21 20:07:17 +00:00
import discord
import toml
import logging
import discord.ext.commands as commands
2020-05-12 16:08:03 +00:00
import discord.ext.tasks as tasks
2019-10-21 20:07:17 +00:00
import re
import asyncio
import json
2020-06-18 18:43:20 +00:00
import traceback
import random
import collections
2021-01-27 19:38:21 +00:00
import prometheus_client
import prometheus_async.aio
import typing
import sys
2019-10-21 20:07:17 +00:00
import tio
2020-04-18 12:14:31 +00:00
import db
2020-05-12 16:08:03 +00:00
import util
import eventbus
import irc_link
2020-11-01 17:32:02 +00:00
import achievement
2019-10-21 20:07:17 +00:00
config = util.config
2019-10-21 20:07:17 +00:00
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(asctime)s %(message)s", datefmt="%H:%M:%S %d/%m/%Y")
2020-11-25 19:00:43 +00:00
#intents = discord.Intents.default()
#intents.members = True
2021-01-14 09:38:32 +00:00
bot = commands.Bot(command_prefix=config["prefix"], description="AutoBotRobot, the most useless bot in the known universe." + util.config.get("description_suffix", ""),
2020-11-25 17:34:19 +00:00
case_insensitive=True, allowed_mentions=discord.AllowedMentions(everyone=False, users=True, roles=True))
2019-10-21 20:07:17 +00:00
bot._skip_check = lambda x, y: False
2021-01-27 19:38:21 +00:00
messages = prometheus_client.Counter("abr_messages", "Messages seen/handled by bot")
command_invocations = prometheus_client.Counter("abr_command_invocations", "Total commands invoked (includes failed)")
@bot.event
async def on_message(message):
2021-01-27 19:38:21 +00:00
messages.inc()
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 == bot.user or message.author.discriminator == "0000": return
ctx = await bot.get_context(message)
if not ctx.valid: return
2021-01-27 19:38:21 +00:00
command_invocations.inc()
await bot.invoke(ctx)
2021-01-27 19:38:21 +00:00
command_errors = prometheus_client.Counter("abr_errors", "Count of errors encountered in executing commands.")
@bot.event
async def on_command_error(ctx, err):
if isinstance(err, (commands.CommandNotFound, commands.CheckFailure)): return
2021-02-09 18:04:52 +00:00
if isinstance(err, commands.CommandInvokeError) and isinstance(err.original, ValueError): return await ctx.send(embed=util.error_embed(str(err.original)))
2021-03-08 10:25:11 +00:00
# TODO: really should find a way to detect ALL user errors here?
if isinstance(err, (commands.UserInputError)): return await ctx.send(embed=util.error_embed(str(err)))
try:
2021-01-27 19:38:21 +00:00
command_errors.inc()
trace = re.sub("\n\n+", "\n", "\n".join(traceback.format_exception(err, err, err.__traceback__)))
logging.error("command error occured (in %s)", ctx.invoked_with, exc_info=err)
await ctx.send(embed=util.error_embed(util.gen_codeblock(trace), title="Internal error"))
2020-11-01 17:32:02 +00:00
await achievement.achieve(ctx.bot, ctx.message, "error")
except Exception as e: print("meta-error:", e)
@bot.check
async def andrew_bad(ctx):
return ctx.message.author.id != 543131534685765673
2020-05-12 16:08:03 +00:00
@bot.event
async def on_ready():
logging.info("Connected as " + bot.user.name)
2020-11-01 17:07:36 +00:00
await bot.change_presence(status=discord.Status.online,
2020-11-01 17:13:52 +00:00
activity=discord.Activity(name=f"{bot.command_prefix}help", type=discord.ActivityType.listening))
2020-05-12 16:08:03 +00:00
webhooks = {}
async def initial_load_webhooks(db):
for row in await db.execute_fetchall("SELECT * FROM discord_webhooks"):
webhooks[row["channel_id"]] = row["webhook"]
@bot.listen("on_message")
async def send_to_bridge(msg):
# discard webhooks and bridge messages (hackily, admittedly, not sure how else to do this)
if (msg.author == bot.user and msg.content[0] == "<") or msg.author.discriminator == "0000": return
if msg.content == "": return
channel_id = msg.channel.id
msg = eventbus.Message(eventbus.AuthorInfo(msg.author.name, msg.author.id, str(msg.author.avatar_url), msg.author.bot), msg.content, ("discord", channel_id), msg.id)
await eventbus.push(msg)
async def on_bridge_message(channel_id, msg):
channel = bot.get_channel(channel_id)
if channel:
webhook = webhooks.get(channel_id)
if webhook:
wh_obj = discord.Webhook.from_url(webhook, adapter=discord.AsyncWebhookAdapter(bot.http._HTTPClient__session))
await wh_obj.send(
content=msg.message, username=msg.author.name, avatar_url=msg.author.avatar_url,
allowed_mentions=discord.AllowedMentions(everyone=False, roles=False, users=False))
else:
text = f"<{msg.author.name}> {msg.message}"
await channel.send(text[:2000], allowed_mentions=discord.AllowedMentions(everyone=False, roles=False, users=False))
else:
logging.warning("channel %d not found", channel_id)
eventbus.add_listener("discord", on_bridge_message)
2021-01-27 20:35:32 +00:00
visible_users = prometheus_client.Gauge("abr_visible_users", "Users the bot can see")
def get_visible_users():
return len(bot.users)
visible_users.set_function(get_visible_users)
heavserver_members = prometheus_client.Gauge("abr_heavserver_members", "Current member count of heavserver")
heavserver_bots = prometheus_client.Gauge("abr_heavserver_bots", "Current bot count of heavserver")
2021-01-27 20:35:32 +00:00
def get_heavserver_members():
if not bot.get_guild(util.config["heavserver"]["id"]): return 0
2021-01-27 20:35:32 +00:00
return len(bot.get_guild(util.config["heavserver"]["id"]).members)
def get_heavserver_bots():
if not bot.get_guild(util.config["heavserver"]["id"]): return 0
return len([ None for member in bot.get_guild(util.config["heavserver"]["id"]).members if member.bot ])
2021-01-27 20:35:32 +00:00
heavserver_members.set_function(get_heavserver_members)
heavserver_bots.set_function(get_heavserver_bots)
2021-01-27 20:35:32 +00:00
guild_count = prometheus_client.Gauge("abr_guilds", "Guilds the bot is in")
def get_guild_count():
return len(bot.guilds)
guild_count.set_function(get_guild_count)
2020-04-18 12:14:31 +00:00
async def run_bot():
bot.database = await db.init(config["database"])
await eventbus.initial_load(bot.database)
await initial_load_webhooks(bot.database)
2021-01-14 09:38:32 +00:00
for ext in util.extensions:
logging.info("loaded %s", ext)
bot.load_extension(ext)
2020-04-18 12:14:31 +00:00
await bot.start(config["token"])
if __name__ == '__main__':
loop = asyncio.get_event_loop()
2021-01-27 19:38:21 +00:00
loop.create_task(prometheus_async.aio.web.start_http_server(port=config["metrics_port"]))
2020-04-18 12:14:31 +00:00
try:
loop.run_until_complete(run_bot())
except KeyboardInterrupt:
loop.run_until_complete(bot.logout())
sys.exit(0)
2020-04-18 12:14:31 +00:00
finally:
2020-06-18 18:43:20 +00:00
loop.close()