diff --git a/deploy/playbooks/01_setup.yml b/deploy/playbooks/01_setup.yml index 4768bf3..0e2be55 100644 --- a/deploy/playbooks/01_setup.yml +++ b/deploy/playbooks/01_setup.yml @@ -92,4 +92,3 @@ - name: Display the public key debug: msg: "For private repositories, make sure to put this key as deploy key on github: {{ deploy_key.content | b64decode }}" - diff --git a/deploy/playbooks/04_cron.yml b/deploy/playbooks/04_cron.yml index 2b9f8fc..e9b2cd6 100644 --- a/deploy/playbooks/04_cron.yml +++ b/deploy/playbooks/04_cron.yml @@ -15,3 +15,11 @@ minute: "5" hour: "6" job: "make prod/cron/pretix" + + - name: "Schedule standup message on Monday morning" + ansible.builtin.cron: + name: "Send a standup message" + minute: "5" + hour: "9" + weekday: "1" + job: "make prod/cron/standup" diff --git a/deploy/templates/app/Makefile.app.j2 b/deploy/templates/app/Makefile.app.j2 index 5a21e97..9a016ad 100644 --- a/deploy/templates/app/Makefile.app.j2 +++ b/deploy/templates/app/Makefile.app.j2 @@ -7,7 +7,7 @@ prod/migrate: $(MAKE_APP) in-container/migrate prod/shell: - $(MAKE_APP) in-container/shell + $(MAKE_APP) in-container/manage ARG="shell_plus" prod/db_shell: $(MAKE_APP) in-container/db_shell @@ -22,5 +22,8 @@ prod/cron/pretalx: prod/cron/pretix: $(MAKE_APP) in-container/manage ARG="download_pretix_data --event=ep2025" +prod/cron/standup: + $(MAKE_APP) in-container/manage ARG="send_scheduled_message --template=standup" + logs: docker compose logs -f diff --git a/intbot/core/bot/channel_router.py b/intbot/core/bot/channel_router.py index be00b10..3209259 100644 --- a/intbot/core/bot/channel_router.py +++ b/intbot/core/bot/channel_router.py @@ -77,6 +77,12 @@ class Channels: channel_name=settings.DISCORD_GRANTS_CHANNEL_NAME, ) + # scheduled messages + standup_channel = DiscordChannel( + channel_id=settings.DISCORD_STANDUP_CHANNEL_ID, + channel_name=settings.DISCORD_STANDUP_CHANNEL_NAME, + ) + def discord_channel_router(wh: Webhook) -> DiscordChannel: if wh.source == "github": diff --git a/intbot/core/bot/config.py b/intbot/core/bot/config.py new file mode 100644 index 0000000..af1e4af --- /dev/null +++ b/intbot/core/bot/config.py @@ -0,0 +1,10 @@ +""" +Configuration for all things discord related +""" +from django.conf import settings + +class Roles: + # We keep this statically defined, because we want to use it in templates + # for scheduled messages, and we want to make the scheduling available + # withotu access to the discord server. + board_member_role_id = settings.DISCORD_BOARD_MEMBER_ROLE_ID diff --git a/intbot/core/bot/scheduled_messages.py b/intbot/core/bot/scheduled_messages.py new file mode 100644 index 0000000..a810c2d --- /dev/null +++ b/intbot/core/bot/scheduled_messages.py @@ -0,0 +1,36 @@ +""" +Factory functions for scheduled messages +""" + +from typing import Dict, Callable + +from core.models import DiscordMessage +from core.bot.channel_router import Channels +from core.bot.config import Roles + + +def standup_message_factory() -> DiscordMessage: + """Factory for weekly standup message.""" + content = ( + f"## Happy Monday <@&{Roles.board_member_role_id}>!\n\n" + f"Let's keep everyone in the loop :)\n\n" + f"(1) What you worked on last week\n" + f"(2) What are you planning to work on this week\n" + f"(3) Are there any blockers or where could you use some help?" + ) + + # Using the test channel for now - replace with appropriate channel later + channel = Channels.standup_channel + + return DiscordMessage( + channel_id=channel.channel_id, + channel_name=channel.channel_name, + content=content, + sent_at=None + ) + + +# Registry of message factories +MESSAGE_FACTORIES: Dict[str, Callable[[], DiscordMessage]] = { + "standup": standup_message_factory, +} diff --git a/intbot/core/management/commands/send_scheduled_message.py b/intbot/core/management/commands/send_scheduled_message.py new file mode 100644 index 0000000..46ba41a --- /dev/null +++ b/intbot/core/management/commands/send_scheduled_message.py @@ -0,0 +1,27 @@ +from core.bot.scheduled_messages import MESSAGE_FACTORIES +from django.core.management.base import BaseCommand + + +class Command(BaseCommand): + help = "Sends a scheduled message to Discord" + + def add_arguments(self, parser): + parser.add_argument( + "--template", + required=True, + choices=MESSAGE_FACTORIES.keys(), + help="Message template to send", + ) + + def handle(self, *args, **options): + message_template = options["template"] + + factory = MESSAGE_FACTORIES[message_template] + message = factory() + message.save() + + self.stdout.write( + self.style.SUCCESS( + f"Scheduled '{message_template}' message for channel {message.channel_name}" + ) + ) diff --git a/intbot/intbot/settings.py b/intbot/intbot/settings.py index 80b5fe6..1550ea3 100644 --- a/intbot/intbot/settings.py +++ b/intbot/intbot/settings.py @@ -178,6 +178,12 @@ def get(name) -> str: DISCORD_GRANTS_CHANNEL_ID = get("DISCORD_GRANTS_CHANNEL_ID") DISCORD_GRANTS_CHANNEL_NAME = get("DISCORD_GRANTS_CHANNEL_NAME") +DISCORD_STANDUP_CHANNEL_ID = get("DISCORD_STANDUP_CHANNEL_ID") +DISCORD_STANDUP_CHANNEL_NAME = get("DISCORD_STANDUP_CHANNEL_NAME") + +# Discord Roles +DISCORD_BOARD_MEMBER_ROLE_ID = get("DISCORD_BOARD_MEMBER_ROLE_ID") + # Github GITHUB_API_TOKEN = get("GITHUB_API_TOKEN") GITHUB_WEBHOOK_SECRET_TOKEN = get("GITHUB_WEBHOOK_SECRET_TOKEN")