From b9c0eda8b51fdef0b5011b0df7a1bb1cd40aff61 Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Mon, 13 Jul 2026 14:16:28 -0700 Subject: [PATCH] feat(bot): add subscribe/unsubscribe commands and bot bootstrap --- bot/Dockerfile | 6 ++++++ bot/chorus_bot/cogs/subscribe.py | 29 +++++++++++++++++++++++++ bot/chorus_bot/main.py | 37 ++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 bot/Dockerfile create mode 100644 bot/chorus_bot/cogs/subscribe.py create mode 100644 bot/chorus_bot/main.py diff --git a/bot/Dockerfile b/bot/Dockerfile new file mode 100644 index 0000000..0513fb9 --- /dev/null +++ b/bot/Dockerfile @@ -0,0 +1,6 @@ +FROM python:3.11-slim +WORKDIR /app +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt +COPY chorus_bot ./chorus_bot +CMD ["python", "-m", "chorus_bot.main"] diff --git a/bot/chorus_bot/cogs/subscribe.py b/bot/chorus_bot/cogs/subscribe.py new file mode 100644 index 0000000..1572278 --- /dev/null +++ b/bot/chorus_bot/cogs/subscribe.py @@ -0,0 +1,29 @@ +import discord +from discord import app_commands +from discord.ext import commands + + +class SubscribeCog(commands.Cog): + def __init__(self, bot: commands.Bot, config): + self.bot = bot + self.config = config + + @app_commands.command(name="subscribe", description="Get pinged when new items land in #inbox") + async def subscribe(self, interaction: discord.Interaction): + role = interaction.guild.get_role(self.config.triage_role_id) + await interaction.user.add_roles(role) + await interaction.response.send_message( + "You're subscribed to Chorus inbox pings.", ephemeral=True + ) + + @app_commands.command(name="unsubscribe", description="Stop getting pinged for new items") + async def unsubscribe(self, interaction: discord.Interaction): + role = interaction.guild.get_role(self.config.triage_role_id) + await interaction.user.remove_roles(role) + await interaction.response.send_message( + "You're unsubscribed from Chorus inbox pings.", ephemeral=True + ) + + +async def setup(bot: commands.Bot, config): + await bot.add_cog(SubscribeCog(bot, config)) diff --git a/bot/chorus_bot/main.py b/bot/chorus_bot/main.py new file mode 100644 index 0000000..34d0a2f --- /dev/null +++ b/bot/chorus_bot/main.py @@ -0,0 +1,37 @@ +import asyncio +import discord +from discord.ext import commands +from chorus_bot.config import load_config +from chorus_bot.backend_client import BackendClient +from chorus_bot.cogs.manual_share import setup as setup_manual_share +from chorus_bot.cogs.email_ingest import setup as setup_email_ingest +from chorus_bot.cogs.thread_ingest import setup as setup_thread_ingest +from chorus_bot.cogs.subscribe import setup as setup_subscribe + + +def build_bot() -> commands.Bot: + intents = discord.Intents.default() + intents.message_content = True + intents.members = True + return commands.Bot(command_prefix="!", intents=intents) + + +async def main(): + config = load_config() + bot = build_bot() + backend_client = BackendClient(config.backend_base_url) + + @bot.event + async def on_ready(): + await setup_manual_share(bot, config) + await setup_email_ingest(bot, config) + await setup_thread_ingest(bot, config, backend_client) + await setup_subscribe(bot, config) + await bot.tree.sync(guild=discord.Object(id=config.guild_id)) + print(f"Chorus bot ready as {bot.user}") + + await bot.start(config.discord_token) + + +if __name__ == "__main__": + asyncio.run(main())