def test_shortcut(self): req: BoltRequest = BoltRequest(body=global_shortcut, mode="socket_mode") message = warning_unhandled_request(req) filtered_body = { "type": "shortcut", "callback_id": "test-shortcut", } assert (f"""Unhandled request ({filtered_body}) --- [Suggestion] You can handle this type of event with the following listener function: @app.shortcut("test-shortcut") def handle_shortcuts(ack, body, logger): ack() logger.info(body) """ == message) req: BoltRequest = BoltRequest(body=message_shortcut, mode="socket_mode") message = warning_unhandled_request(req) filtered_body = { "type": "message_action", "callback_id": "test-shortcut", } assert (f"""Unhandled request ({filtered_body}) --- [Suggestion] You can handle this type of event with the following listener function: @app.shortcut("test-shortcut") def handle_shortcuts(ack, body, logger): ack() logger.info(body) """ == message)
def test_attachment_actions(self): req: BoltRequest = BoltRequest(body=attachment_actions, mode="socket_mode") message = warning_unhandled_request(req) filtered_body = { "type": "interactive_message", "callback_id": "pick_channel_for_fun", "actions": [{ "name": "channel_list", "type": "select", "selected_options": [{ "value": "C111" }], }], } assert (f"""Unhandled request ({filtered_body}) --- [Suggestion] You can handle this type of event with the following listener function: @app.action("pick_channel_for_fun") def handle_some_action(ack, body, logger): ack() logger.info(body) """ == message)
async def async_dispatch(self, req: AsyncBoltRequest) -> BoltResponse: """Applies all middleware and dispatches an incoming request from Slack to the right code path. :param req: An incoming request from Slack. :return: The response generated by this Bolt app. """ self._init_context(req) resp: BoltResponse = BoltResponse(status=200, body="") middleware_state = {"next_called": False} async def async_middleware_next(): middleware_state["next_called"] = True for middleware in self._async_middleware_list: middleware_state["next_called"] = False if self._framework_logger.level <= logging.DEBUG: self._framework_logger.debug(f"Applying {middleware.name}") resp = await middleware.async_process(req=req, resp=resp, next=async_middleware_next) if not middleware_state["next_called"]: if resp is None: return BoltResponse( status=404, body={"error": "no next() calls in middleware"}) return resp for listener in self._async_listeners: listener_name = listener.ack_function.__name__ self._framework_logger.debug( debug_checking_listener(listener_name)) if await listener.async_matches(req=req, resp=resp): # run all the middleware attached to this listener first resp, next_was_not_called = await listener.run_async_middleware( req=req, resp=resp) if next_was_not_called: # The last listener middleware didn't call next() method. # This means the listener is not for this incoming request. continue self._framework_logger.debug( debug_running_listener(listener_name)) listener_response: Optional[ BoltResponse] = await self._async_listener_runner.run( request=req, response=resp, listener_name=listener_name, listener=listener, ) if listener_response is not None: return listener_response self._framework_logger.warning(warning_unhandled_request(req)) return BoltResponse(status=404, body={"error": "unhandled request"})
def test_view(self): req: BoltRequest = BoltRequest(body=view_submission, mode="socket_mode") message = warning_unhandled_request(req) filtered_body = { "type": "view_submission", "view": { "type": "modal", "callback_id": "view-id" }, } assert (f"""Unhandled request ({filtered_body}) --- [Suggestion] You can handle this type of event with the following listener function: @app.view("view-id") def handle_view_events(ack, body, logger): ack() logger.info(body) """ == message) req: BoltRequest = BoltRequest(body=view_closed, mode="socket_mode") message = warning_unhandled_request(req) filtered_body = { "type": "view_closed", "view": { "type": "modal", "callback_id": "view-id" }, } assert (f"""Unhandled request ({filtered_body}) --- [Suggestion] You can handle this type of event with the following listener function: @app.view("view-id") def handle_view_events(ack, body, logger): ack() logger.info(body) """ == message)
def test_commands(self): req: BoltRequest = BoltRequest(body=slash_command, mode="socket_mode") message = warning_unhandled_request(req) filtered_body = { "type": None, "command": "/start-conv", } assert (f"""Unhandled request ({filtered_body}) --- [Suggestion] You can handle this type of event with the following listener function: @app.command("/start-conv") def handle_some_command(ack, body, logger): ack() logger.info(body) """ == message)
def test_dialog_suggestion(self): req: BoltRequest = BoltRequest(body=dialog_suggestion, mode="socket_mode") message = warning_unhandled_request(req) filtered_body = { "type": "dialog_suggestion", "callback_id": "the-id", "value": "search keyword", } assert (f"""Unhandled request ({filtered_body}) --- [Suggestion] You can handle this type of event with the following listener function: @app.options({{"type": "dialog_suggestion", "callback_id": "the-id"}}) def handle_some_options(ack): ack(options=[ ... ]) """ == message)
def test_block_actions(self): req: BoltRequest = BoltRequest(body=block_actions, mode="socket_mode") message = warning_unhandled_request(req) filtered_body = { "type": "block_actions", "block_id": "b", "action_id": "action-id-value", } assert (f"""Unhandled request ({filtered_body}) --- [Suggestion] You can handle this type of event with the following listener function: @app.action("action-id-value") def handle_some_action(ack, body, logger): ack() logger.info(body) """ == message)
def test_app_mention_event(self): req: BoltRequest = BoltRequest(body=app_mention_event, mode="socket_mode") filtered_body = { "type": "event_callback", "event": { "type": "app_mention" }, } message = warning_unhandled_request(req) assert (f"""Unhandled request ({filtered_body}) --- [Suggestion] You can handle this type of event with the following listener function: @app.event("app_mention") def handle_app_mention_events(body, logger): logger.info(body) """ == message)
def test_step(self): req: BoltRequest = BoltRequest(body=step_edit_payload, mode="socket_mode") message = warning_unhandled_request(req) filtered_body = { "type": "workflow_step_edit", "callback_id": "copy_review", } assert (f"""Unhandled request ({filtered_body}) --- [Suggestion] You can handle this type of event with the following listener function: from slack_bolt.workflows.step import WorkflowStep ws = WorkflowStep( callback_id="copy_review", edit=edit, save=save, execute=execute, ) # Pass Step to set up listeners app.step(ws) """ == message) req: BoltRequest = BoltRequest(body=step_save_payload, mode="socket_mode") message = warning_unhandled_request(req) filtered_body = { "type": "view_submission", "view": { "type": "workflow_step", "callback_id": "copy_review" }, } assert (f"""Unhandled request ({filtered_body}) --- [Suggestion] You can handle this type of event with the following listener function: from slack_bolt.workflows.step import WorkflowStep ws = WorkflowStep( callback_id="copy_review", edit=edit, save=save, execute=execute, ) # Pass Step to set up listeners app.step(ws) """ == message) req: BoltRequest = BoltRequest(body=step_execute_payload, mode="socket_mode") message = warning_unhandled_request(req) filtered_body = { "type": "event_callback", "event": { "type": "workflow_step_execute" }, } assert (f"""Unhandled request ({filtered_body}) --- [Suggestion] You can handle this type of event with the following listener function: from slack_bolt.workflows.step import WorkflowStep ws = WorkflowStep( callback_id="your-callback-id", edit=edit, save=save, execute=execute, ) # Pass Step to set up listeners app.step(ws) """ == message)
def test_unknown_patterns(self): req: BoltRequest = BoltRequest(body={"type": "foo"}, mode="socket_mode") message = warning_unhandled_request(req) assert f"Unhandled request ({req.body})" == message
def dispatch(self, req: BoltRequest) -> BoltResponse: """Applies all middleware and dispatches an incoming request from Slack to the right code path. :param req: An incoming request from Slack. :return: The response generated by this Bolt app. """ starting_time = time.time() self._init_context(req) resp: BoltResponse = BoltResponse(status=200, body="") middleware_state = {"next_called": False} def middleware_next(): middleware_state["next_called"] = True for middleware in self._middleware_list: middleware_state["next_called"] = False if self._framework_logger.level <= logging.DEBUG: self._framework_logger.debug( debug_applying_middleware(middleware.name)) resp = middleware.process(req=req, resp=resp, next=middleware_next) if not middleware_state["next_called"]: if resp is None: return BoltResponse( status=404, body={"error": "no next() calls in middleware"}) return resp for listener in self._listeners: listener_name = get_name_for_callable(listener.ack_function) self._framework_logger.debug( debug_checking_listener(listener_name)) if listener.matches(req=req, resp=resp): # run all the middleware attached to this listener first middleware_resp, next_was_not_called = listener.run_middleware( req=req, resp=resp) if next_was_not_called: if middleware_resp is not None: if self._framework_logger.level <= logging.DEBUG: debug_message = debug_return_listener_middleware_response( listener_name, middleware_resp.status, middleware_resp.body, starting_time, ) self._framework_logger.debug(debug_message) return middleware_resp # The last listener middleware didn't call next() method. # This means the listener is not for this incoming request. continue if middleware_resp is not None: resp = middleware_resp self._framework_logger.debug( debug_running_listener(listener_name)) listener_response: Optional[ BoltResponse] = self._listener_runner.run( request=req, response=resp, listener_name=listener_name, listener=listener, ) if listener_response is not None: return listener_response self._framework_logger.warning(warning_unhandled_request(req)) return BoltResponse(status=404, body={"error": "unhandled request"})