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_failure_pattern(self): authorization = SingleTeamAuthorization(auth_test_result={}) req = BoltRequest(body="payload={}", headers={}) req.context["client"] = WebClient( base_url=self.mock_api_server_base_url, token="dummy" ) resp = BoltResponse(status=404) resp = authorization.process(req=req, resp=resp, next=next) assert resp.status == 200 assert resp.body == ":x: Please install this app into the workspace :bow:"
def test_success_pattern(self): authorization = SingleTeamAuthorization(auth_test_result={}) req = BoltRequest(body="payload={}", headers={}) req.context["client"] = WebClient( base_url=self.mock_api_server_base_url, token="xoxb-valid" ) resp = BoltResponse(status=404) resp = authorization.process(req=req, resp=resp, next=next) assert resp.status == 200 assert resp.body == ""
def test_invalid(self): middleware = RequestVerification(signing_secret=self.signing_secret) req = BoltRequest(body="payload={}", headers={}) resp = BoltResponse(status=404) resp = middleware.process(req=req, resp=resp, next=next) assert resp.status == 401 assert resp.body == """{"error": "invalid request"}"""
def _to_bolt_request(self, req: Request) -> BoltRequest: return BoltRequest( body=req.stream.read(req.content_length or 0).decode("utf-8"), query=req.query_string, headers={k.lower(): v for k, v in req.headers.items()}, )
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)
def process( self, *, req: BoltRequest, resp: BoltResponse, next: Callable[[], BoltResponse], ) -> BoltResponse: if _is_no_auth_required(req): return next() try: auth_result = req.context.client.auth_test() if auth_result: req.context["authorization_result"] = AuthorizationResult( enterprise_id=auth_result.get("enterprise_id", None), team_id=auth_result.get("team_id", None), bot_user_id=auth_result.get("user_id", None), bot_id=auth_result.get("bot_id", None), bot_token=req.context.client.token, user_id=req.context.user_id, ) return next() else: # Just in case self.logger.error( "auth.test API call result is unexpectedly None") return _build_error_response() except SlackApiError as e: self.logger.error( f"Failed to authorize with the given token ({e})") return _build_error_response()
def build_request(self) -> BoltRequest: body = { "type": "shortcut", "token": "verification_token", "action_ts": "111.111", "team": { "id": "T111", "domain": "workspace-domain", "enterprise_id": "E111", "enterprise_name": "Org Name", }, "user": { "id": "W111", "username": "******", "team_id": "T111" }, "callback_id": "test-shortcut", "trigger_id": "111.111.xxxxxx", } timestamp, body = str(int(time())), json.dumps(body) return BoltRequest( body=body, headers={ "content-type": ["application/json"], "x-slack-signature": [ self.signature_verifier.generate_signature( body=body, timestamp=timestamp, ) ], "x-slack-request-timestamp": [timestamp], }, )
def build_bolt_request() -> BoltRequest: req = cherrypy.request body = req.raw_body if hasattr(req, "raw_body") else "" return BoltRequest( body=body, query=req.query_string, headers=req.headers, )
def to_bolt_request(req: HttpRequest) -> BoltRequest: raw_body: bytes = req.body body: str = raw_body.decode("utf-8") if raw_body else "" return BoltRequest( body=body, query=req.META["QUERY_STRING"], headers=req.headers, )
def _init_context(self, req: BoltRequest): req.context["logger"] = get_bolt_app_logger(self.name) req.context["token"] = self._token if self._token is not None: # This WebClient instance can be safely singleton req.context["client"] = self._client else: # Set a new dedicated instance for this request client_per_request: WebClient = WebClient( token=None, # the token will be set later base_url=self._client.base_url, timeout=self._client.timeout, ssl=self._client.ssl, proxy=self._client.proxy, headers=self._client.headers, ) req.context["client"] = client_per_request
def to_bolt_request(req: Request) -> BoltRequest: body = req.body.read() if isinstance(body, bytes): body = body.decode("utf-8") return BoltRequest( body=body, query=req.query_string, headers=req.headers, )
def to_bolt_request(event) -> BoltRequest: body = event.get("body", "") if event["isBase64Encoded"]: body = base64.b64decode(body).decode("utf-8") cookies: Sequence[str] = event.get("cookies", []) headers = event.get("headers", {}) headers["cookie"] = cookies return BoltRequest( body=body, query=event.get("queryStringParameters", {}), headers=headers, )
def do_GET(self): if _bolt_oauth_flow: request_path, _, query = self.path.partition("?") if request_path == _bolt_oauth_flow.install_path: bolt_req = BoltRequest( body="", query=query, headers=self.headers ) bolt_resp = _bolt_oauth_flow.handle_installation(bolt_req) self._send_bolt_response(bolt_resp) elif request_path == _bolt_oauth_flow.redirect_uri_path: bolt_req = BoltRequest( body="", query=query, headers=self.headers ) bolt_resp = _bolt_oauth_flow.handle_callback(bolt_req) self._send_bolt_response(bolt_resp) else: self._send_response(404, headers={}) else: self._send_response(404, headers={})
def test_valid(self): middleware = RequestVerification(signing_secret=self.signing_secret) timestamp = str(int(time())) raw_body = "payload={}" req = BoltRequest(body=raw_body, headers=self.build_headers(timestamp, raw_body)) resp = BoltResponse(status=404, body="default") resp = middleware.process(req=req, resp=resp, next=next) assert resp.status == 200 assert resp.body == "next"
def process( self, *, req: BoltRequest, resp: BoltResponse, next: Callable[[], BoltResponse], ) -> BoltResponse: if _is_no_auth_required(req): return next() if _is_no_auth_test_call_required(req): req.context.set_authorize_result( AuthorizeResult( enterprise_id=req.context.enterprise_id, team_id=req.context.team_id, user_id=req.context.user_id, )) return next() try: auth_result: Optional[AuthorizeResult] = self.authorize( context=req.context, enterprise_id=req.context.enterprise_id, team_id=req.context.team_id, user_id=req.context.user_id, ) if auth_result is not None: req.context.set_authorize_result(auth_result) token = auth_result.bot_token or auth_result.user_token req.context["token"] = token req.context["client"] = create_web_client(token) return next() else: # Just in case self.logger.error( "auth.test API call result is unexpectedly None") return _build_error_response() except SlackApiError as e: self.logger.error( f"Failed to authorize with the given token ({e})") return _build_error_response()
def do_POST(self): request_path, _, query = self.path.partition("?") if _bolt_endpoint_path != request_path: self._send_response(404, headers={}) return len_header = self.headers.get("Content-Length") or 0 request_body = self.rfile.read(int(len_header)).decode("utf-8") bolt_req = BoltRequest( body=request_body, query=query, headers=self.headers ) bolt_resp: BoltResponse = _bolt_app.dispatch(bolt_req) self._send_bolt_response(bolt_resp)
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 build_request(self) -> BoltRequest: timestamp, body = str(int(time())), json.dumps(self.body) return BoltRequest( body=body, headers={ "content-type": ["application/json"], "x-slack-signature": [ self.signature_verifier.generate_signature( body=body, timestamp=timestamp, ) ], "x-slack-request-timestamp": [timestamp], }, )
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 process( self, *, req: BoltRequest, resp: BoltResponse, next: Callable[[], BoltResponse], ) -> BoltResponse: text = req.body.get("event", {}).get("text", "") if text: m = re.search(self.keyword, text) if m is not None: req.context["matches"] = m.groups() # tuple return next() # As the text doesn't match, skip running the listener return resp
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 process( self, *, req: BoltRequest, resp: BoltResponse, next: Callable[[], BoltResponse], ) -> BoltResponse: if _is_no_auth_required(req): return next() try: bot: Optional[Bot] = self.installation_store.find_bot( enterprise_id=req.context.enterprise_id, team_id=req.context.team_id, ) if bot is None: return _build_error_response() if self.verification_enabled: auth_result = req.context.client.auth_test(token=bot.bot_token) if auth_result: req.context["authorization_result"] = AuthorizationResult( enterprise_id=auth_result.get("enterprise_id", None), team_id=auth_result.get("team_id", None), bot_user_id=auth_result.get("user_id", None), bot_id=auth_result.get("bot_id", None), bot_token=bot.bot_token, ) # TODO: bot -> user token req.context["token"] = bot.bot_token req.context["client"] = create_web_client(bot.bot_token) return next() else: # Just in case self.logger.error( "auth.test API call result is unexpectedly None") return _build_error_response() else: req.context["authorization_result"] = AuthorizationResult( enterprise_id=bot.enterprise_id, team_id=bot.team_id, bot_user_id=bot.bot_user_id, bot_id=bot.bot_id, bot_token=bot.bot_token, ) # TODO: bot -> user token req.context["token"] = bot.bot_token req.context["client"] = create_web_client(bot.bot_token) return next() except SlackApiError as e: self.logger.error( f"Failed to authorize with the given token ({e})") return _build_error_response()
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 to_bolt_request(req: HTTPServerRequest) -> BoltRequest: return BoltRequest( body=req.body.decode("utf-8") if req.body else "", query=req.query, headers=req.headers, )
def build_valid_request(self) -> BoltRequest: timestamp, body = str(int(time())), json.dumps(slash_command_payload) return BoltRequest(body=body, headers=self.build_headers(timestamp, body))
def to_bolt_request(request: Request, body: str) -> BoltRequest: return BoltRequest(body=body, query=request.query_params, headers=request.headers,)
def run_bolt_app(app: App, req: SocketModeRequest): # type: ignore bolt_req: BoltRequest = BoltRequest(mode="socket_mode", body=req.payload) bolt_resp: BoltResponse = app.dispatch(bolt_req) return bolt_resp
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)