bot/client.py
from __future__ import annotations
import logging
import discord
from discord.ext import commands
from bot import commands as bot_commands
from bot import embeds as em
from db import store
logger = logging.getLogger("bot.client")
def build_bot(db, cfg) -> discord.Client:
intents = discord.Intents.default()
bot = commands.Bot(command_prefix="!", intents=intents)
async def setup_hook() -> None:
await bot_commands.setup_commands(bot, db, cfg)
await bot.tree.sync()
bot.setup_hook = setup_hook
return bot
def target_channels(guild_cfg: dict | None) -> tuple[int | None, int | None]:
cfg = guild_cfg or {}
return (cfg.get("hits_channel_id"), cfg.get("logs_channel_id"))
async def _send(bot, channel_id: int | None, embed: discord.Embed) -> None:
if not channel_id:
return
channel = bot.get_channel(channel_id)
if channel is None:
try:
channel = await bot.fetch_channel(channel_id)
except discord.DiscordException:
logger.warning("could not resolve channel %s", channel_id)
return
try:
await channel.send(embed=embed)
except discord.DiscordException:
logger.warning("failed to send to channel %s", channel_id, exc_info=True)
async def dispatch_result(bot, guild_id, db, result) -> None:
guild_cfg = await store.get_guild_config(db, guild_id) if guild_id else None
hits_channel_id, logs_channel_id = target_channels(guild_cfg)
if result.authenticated:
await _send(bot, hits_channel_id, em.hits_embed(result))
status = "success" if result.authenticated else "failed"
await _send(
bot,
logs_channel_id,
em.logs_embed(guild_id, result.discord_user_id, result.method, status, result.fail_reason),
)