diff --git a/src/templatebot/constants.py b/src/templatebot/constants.py new file mode 100644 index 0000000..957f030 --- /dev/null +++ b/src/templatebot/constants.py @@ -0,0 +1,4 @@ +"""Application constants.""" + +SELECT_PROJECT_TEMPLATE_ACTION = "templatebot_select_project_template" +"""Action ID of the static select menu for selecting a project template.""" diff --git a/src/templatebot/factory.py b/src/templatebot/factory.py index 1d6bc34..df770ec 100644 --- a/src/templatebot/factory.py +++ b/src/templatebot/factory.py @@ -6,6 +6,7 @@ from httpx import AsyncClient from structlog.stdlib import BoundLogger +from templatebot.services.slackblockactions import SlackBlockActionsService from templatebot.services.slackmessage import SlackMessageService from templatebot.storage.slack import SlackWebApiClient @@ -73,3 +74,9 @@ def create_slack_message_service(self) -> SlackMessageService: return SlackMessageService( logger=self._logger, slack_client=self.create_slack_web_client() ) + + def create_slack_block_actions_service(self) -> SlackBlockActionsService: + """Create a new Slack block actions handling service.""" + return SlackBlockActionsService( + logger=self._logger, slack_client=self.create_slack_web_client() + ) diff --git a/src/templatebot/handlers/kafka.py b/src/templatebot/handlers/kafka.py index 7ab4fc7..2503903 100644 --- a/src/templatebot/handlers/kafka.py +++ b/src/templatebot/handlers/kafka.py @@ -81,8 +81,11 @@ async def handle_slack_block_actions( ) -> None: """Handle a Slack block_actions interaction.""" logger = context.logger + factory = context.factory logger.debug( "Got Slack block_actions", actions=payload.actions[0].model_dump(mode="json"), ) + block_actions_service = factory.create_slack_block_actions_service() + await block_actions_service.handle_block_actions(payload) diff --git a/src/templatebot/services/slackblockactions.py b/src/templatebot/services/slackblockactions.py new file mode 100644 index 0000000..c886efe --- /dev/null +++ b/src/templatebot/services/slackblockactions.py @@ -0,0 +1,54 @@ +"""Slack service for handling block actions.""" + +from __future__ import annotations + +from rubin.squarebot.models.kafka import SquarebotSlackBlockActionsValue +from rubin.squarebot.models.slack import ( + SlackBlockActionBase, + SlackStaticSelectAction, +) +from structlog.stdlib import BoundLogger + +from templatebot.constants import SELECT_PROJECT_TEMPLATE_ACTION +from templatebot.storage.slack import SlackWebApiClient + +__all__ = ["SlackBlockActionsService"] + + +class SlackBlockActionsService: + """A service for processing Slack block actions.""" + + def __init__( + self, logger: BoundLogger, slack_client: SlackWebApiClient + ) -> None: + self._logger = logger + self._slack_client = slack_client + + async def handle_block_actions( + self, payload: SquarebotSlackBlockActionsValue + ) -> None: + """Handle a Slack block_actions interaction.""" + for action in payload.actions: + if action.action_id == SELECT_PROJECT_TEMPLATE_ACTION: + await self.handle_project_template_selection( + action=action, payload=payload + ) + + async def handle_project_template_selection( + self, + *, + action: SlackBlockActionBase, + payload: SquarebotSlackBlockActionsValue, + ) -> None: + """Handle a project template selection.""" + if not isinstance(action, SlackStaticSelectAction): + raise TypeError( + f"Expected action for {SELECT_PROJECT_TEMPLATE_ACTION} to be " + f"a SlackStaticSelectAction, but got {type(action)}" + ) + selected_option = action.selected_option + self._logger.debug( + "Selected project template", + value=selected_option.value, + text=selected_option.text.text, + ) diff --git a/src/templatebot/services/slackmessage.py b/src/templatebot/services/slackmessage.py index 5964f18..292448b 100644 --- a/src/templatebot/services/slackmessage.py +++ b/src/templatebot/services/slackmessage.py @@ -10,6 +10,7 @@ ) from structlog.stdlib import BoundLogger +from templatebot.constants import SELECT_PROJECT_TEMPLATE_ACTION from templatebot.storage.slack import ( SlackChatPostMessageRequest, SlackWebApiClient, @@ -108,7 +109,7 @@ async def _handle_create_project( self._logger.info("Creating a project") select_element = SlackStaticSelectElement( placeholder=SlackPlainTextObject(text="Choose a template…"), - action_id="templatebot_select_project_template", + action_id=SELECT_PROJECT_TEMPLATE_ACTION, option_groups=[ SlackOptionGroupObject( label=SlackPlainTextObject(text="SQuaRE"),