diff --git a/docs/english/_sidebar.json b/docs/english/_sidebar.json index aa75b0c15..6ba6c4175 100644 --- a/docs/english/_sidebar.json +++ b/docs/english/_sidebar.json @@ -6,7 +6,10 @@ "className": "sidebar-title" }, "tools/bolt-python/getting-started", - { "type": "html", "value": "
" }, + { + "type": "html", + "value": "
" + }, "tools/bolt-python/creating-an-app", { "type": "category", @@ -14,7 +17,7 @@ "link": { "type": "doc", "id": "tools/bolt-python/concepts/adding-agent-features" - }, + }, "items": [ "tools/bolt-python/concepts/adding-agent-features", "tools/bolt-python/concepts/using-the-assistant-class" @@ -100,9 +103,14 @@ { "type": "category", "label": "Legacy", - "items": ["tools/bolt-python/legacy/steps-from-apps"] + "items": [ + "tools/bolt-python/legacy/steps-from-apps" + ] + }, + { + "type": "html", + "value": "
" }, - { "type": "html", "value": "
" }, { "type": "category", "label": "Tutorials", @@ -116,13 +124,14 @@ "tools/bolt-python/tutorial/modals/modals" ] }, - { "type": "html", "value": "
" }, { - "type": "link", - "label": "Reference", - "href": "https://docs.slack.dev/tools/bolt-python/reference/index.html" + "type": "html", + "value": "
" + }, + { + "type": "html", + "value": "
" }, - { "type": "html", "value": "
" }, { "type": "category", "label": "日本語 (日本)", @@ -199,7 +208,9 @@ { "type": "category", "label": "レガシー(非推奨)", - "items": ["tools/bolt-python/ja-jp/legacy/steps-from-apps"] + "items": [ + "tools/bolt-python/ja-jp/legacy/steps-from-apps" + ] } ] } diff --git a/docs/english/reference/adapter/aiohttp/index.md b/docs/english/reference/adapter/aiohttp/index.md new file mode 100644 index 000000000..9e41cad68 --- /dev/null +++ b/docs/english/reference/adapter/aiohttp/index.md @@ -0,0 +1,16 @@ +--- +sidebar_label: aiohttp +title: slack_bolt.adapter.aiohttp +--- + +#### to\_bolt\_request + +```python +async def to_bolt_request(request: web.Request) -> AsyncBoltRequest +``` + +#### to\_aiohttp\_response + +```python +async def to_aiohttp_response(bolt_resp: BoltResponse) -> web.Response +``` diff --git a/docs/english/reference/adapter/asgi/aiohttp/index.md b/docs/english/reference/adapter/asgi/aiohttp/index.md new file mode 100644 index 000000000..1f8cceb74 --- /dev/null +++ b/docs/english/reference/adapter/asgi/aiohttp/index.md @@ -0,0 +1,58 @@ +--- +sidebar_label: aiohttp +title: slack_bolt.adapter.asgi.aiohttp +--- + +## AsyncSlackRequestHandler Objects + +```python +class AsyncSlackRequestHandler(SlackRequestHandler) +``` + +#### app: `AsyncApp` + +#### \_\_init\_\_ + +```python +def __init__(app: AsyncApp, path: str = '/slack/events') +``` + +Setup Bolt as an ASGI web framework, this will make your application compatible with ASGI web servers. +This can be used for production deployment. + +With the default settings, `http://localhost:3000/slack/events` +Run Bolt with [uvicron](https://www.uvicorn.org/) + +```python +# Python +app = AsyncApp() +api = SlackRequestHandler(app) + +# bash +export SLACK_SIGNING_SECRET=*** +export SLACK_BOT_TOKEN=xoxb-*** +uvicorn app:api --port 3000 --log-level debug +``` + +**Arguments**: + +- `app` _AsyncApp_ - Your bolt application +- `path` _str_ - The path to handle request from Slack (Default: `/slack/events`) + +#### dispatch + +```python +async def dispatch(request: AsgiHttpRequest) -> BoltResponse +``` + +#### handle\_installation + +```python +async def handle_installation(request: AsgiHttpRequest) -> BoltResponse +``` + +#### handle\_callback + +```python +async def handle_callback(request: AsgiHttpRequest) -> BoltResponse +``` diff --git a/docs/english/reference/adapter/asgi/async_handler.md b/docs/english/reference/adapter/asgi/async_handler.md new file mode 100644 index 000000000..09cee503b --- /dev/null +++ b/docs/english/reference/adapter/asgi/async_handler.md @@ -0,0 +1,58 @@ +--- +sidebar_label: async_handler +title: slack_bolt.adapter.asgi.async_handler +--- + +## AsyncSlackRequestHandler Objects + +```python +class AsyncSlackRequestHandler(SlackRequestHandler) +``` + +#### app: `AsyncApp` + +#### \_\_init\_\_ + +```python +def __init__(app: AsyncApp, path: str = '/slack/events') +``` + +Setup Bolt as an ASGI web framework, this will make your application compatible with ASGI web servers. +This can be used for production deployment. + +With the default settings, `http://localhost:3000/slack/events` +Run Bolt with [uvicron](https://www.uvicorn.org/) + +```python +# Python +app = AsyncApp() +api = SlackRequestHandler(app) + +# bash +export SLACK_SIGNING_SECRET=*** +export SLACK_BOT_TOKEN=xoxb-*** +uvicorn app:api --port 3000 --log-level debug +``` + +**Arguments**: + +- `app` _AsyncApp_ - Your bolt application +- `path` _str_ - The path to handle request from Slack (Default: `/slack/events`) + +#### dispatch + +```python +async def dispatch(request: AsgiHttpRequest) -> BoltResponse +``` + +#### handle\_installation + +```python +async def handle_installation(request: AsgiHttpRequest) -> BoltResponse +``` + +#### handle\_callback + +```python +async def handle_callback(request: AsgiHttpRequest) -> BoltResponse +``` diff --git a/docs/english/reference/adapter/asgi/base_handler.md b/docs/english/reference/adapter/asgi/base_handler.md new file mode 100644 index 000000000..a73273bcd --- /dev/null +++ b/docs/english/reference/adapter/asgi/base_handler.md @@ -0,0 +1,38 @@ +--- +sidebar_label: base_handler +title: slack_bolt.adapter.asgi.base_handler +--- + +## BaseSlackRequestHandler Objects + +```python +class BaseSlackRequestHandler() +``` + +#### app: `Union[App, AsyncApp]` + +#### path: `str` + +#### dispatch + +```python +async def dispatch(request: AsgiHttpRequest) -> BoltResponse +``` + +Dispatches a request to the Bolt App + +#### handle\_installation + +```python +async def handle_installation(request: AsgiHttpRequest) -> BoltResponse +``` + +Handles installation of the OAuthFlow + +#### handle\_callback + +```python +async def handle_callback(request: AsgiHttpRequest) -> BoltResponse +``` + +Handles the callback of the OAuthFlow diff --git a/docs/english/reference/adapter/asgi/builtin/index.md b/docs/english/reference/adapter/asgi/builtin/index.md new file mode 100644 index 000000000..5280151cc --- /dev/null +++ b/docs/english/reference/adapter/asgi/builtin/index.md @@ -0,0 +1,56 @@ +--- +sidebar_label: builtin +title: slack_bolt.adapter.asgi.builtin +--- + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler(BaseSlackRequestHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App, path: str = '/slack/events') +``` + +Setup Bolt as an ASGI web framework, this will make your application compatible with ASGI web servers. +This can be used for production deployment. + +With the default settings, `http://localhost:3000/slack/events` +Run Bolt with [uvicron](https://www.uvicorn.org/) + +```python +# Python +app = App() +api = SlackRequestHandler(app) + +# bash +export SLACK_SIGNING_SECRET=*** +export SLACK_BOT_TOKEN=xoxb-*** +uvicorn app:api --port 3000 --log-level debug +``` + +**Arguments**: + +- `app` _App_ - Your bolt application +- `path` _str_ - The path to handle request from Slack (Default: `/slack/events`) + +#### dispatch + +```python +async def dispatch(request: AsgiHttpRequest) -> BoltResponse +``` + +#### handle\_installation + +```python +async def handle_installation(request: AsgiHttpRequest) -> BoltResponse +``` + +#### handle\_callback + +```python +async def handle_callback(request: AsgiHttpRequest) -> BoltResponse +``` diff --git a/docs/english/reference/adapter/asgi/http_request.md b/docs/english/reference/adapter/asgi/http_request.md new file mode 100644 index 000000000..6fc4a2c6d --- /dev/null +++ b/docs/english/reference/adapter/asgi/http_request.md @@ -0,0 +1,30 @@ +--- +sidebar_label: http_request +title: slack_bolt.adapter.asgi.http_request +--- + +## AsgiHttpRequest Objects + +```python +class AsgiHttpRequest() +``` + +#### \_\_init\_\_ + +```python +def __init__(scope: scope_type, receive: Callable) +``` + +#### raw\_headers: `Iterable[Tuple[bytes, bytes]]` + +#### get\_headers + +```python +def get_headers() -> Dict[str, Union[str, Sequence[str]]] +``` + +#### get\_raw\_body + +```python +async def get_raw_body() -> str +``` diff --git a/docs/english/reference/adapter/asgi/http_response.md b/docs/english/reference/adapter/asgi/http_response.md new file mode 100644 index 000000000..5c0ffe1ca --- /dev/null +++ b/docs/english/reference/adapter/asgi/http_response.md @@ -0,0 +1,34 @@ +--- +sidebar_label: http_response +title: slack_bolt.adapter.asgi.http_response +--- + +## AsgiHttpResponse Objects + +```python +class AsgiHttpResponse() +``` + +#### \_\_init\_\_ + +```python +def __init__(status: int, headers: Dict[str, Sequence[str]] = {}, body: str = '') +``` + +#### status: `int` + +#### body: `bytes` + +#### raw\_headers: `List[Tuple[bytes, bytes]]` + +#### get\_response\_start + +```python +def get_response_start() -> Dict[str, Union[str, int, Iterable[Tuple[bytes, bytes]]]] +``` + +#### get\_response\_body + +```python +def get_response_body() -> Dict[str, Union[str, bytes, bool]] +``` diff --git a/docs/english/reference/adapter/asgi/index.md b/docs/english/reference/adapter/asgi/index.md new file mode 100644 index 000000000..76b482b8b --- /dev/null +++ b/docs/english/reference/adapter/asgi/index.md @@ -0,0 +1,66 @@ +--- +sidebar_label: asgi +title: slack_bolt.adapter.asgi +--- + +## Submodules + +- [slack_bolt.adapter.asgi.aiohttp](/tools/bolt-python/reference/adapter/asgi/aiohttp) +- [slack_bolt.adapter.asgi.async_handler](/tools/bolt-python/reference/adapter/asgi/async_handler) +- [slack_bolt.adapter.asgi.base_handler](/tools/bolt-python/reference/adapter/asgi/base_handler) +- [slack_bolt.adapter.asgi.builtin](/tools/bolt-python/reference/adapter/asgi/builtin) +- [slack_bolt.adapter.asgi.http_request](/tools/bolt-python/reference/adapter/asgi/http_request) +- [slack_bolt.adapter.asgi.http_response](/tools/bolt-python/reference/adapter/asgi/http_response) +- [slack_bolt.adapter.asgi.utils](/tools/bolt-python/reference/adapter/asgi/utils) + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler(BaseSlackRequestHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App, path: str = '/slack/events') +``` + +Setup Bolt as an ASGI web framework, this will make your application compatible with ASGI web servers. +This can be used for production deployment. + +With the default settings, `http://localhost:3000/slack/events` +Run Bolt with [uvicron](https://www.uvicorn.org/) + +```python +# Python +app = App() +api = SlackRequestHandler(app) + +# bash +export SLACK_SIGNING_SECRET=*** +export SLACK_BOT_TOKEN=xoxb-*** +uvicorn app:api --port 3000 --log-level debug +``` + +**Arguments**: + +- `app` _App_ - Your bolt application +- `path` _str_ - The path to handle request from Slack (Default: `/slack/events`) + +#### dispatch + +```python +async def dispatch(request: AsgiHttpRequest) -> BoltResponse +``` + +#### handle\_installation + +```python +async def handle_installation(request: AsgiHttpRequest) -> BoltResponse +``` + +#### handle\_callback + +```python +async def handle_callback(request: AsgiHttpRequest) -> BoltResponse +``` diff --git a/docs/english/reference/adapter/asgi/utils.md b/docs/english/reference/adapter/asgi/utils.md new file mode 100644 index 000000000..a9a25ebe6 --- /dev/null +++ b/docs/english/reference/adapter/asgi/utils.md @@ -0,0 +1,10 @@ +--- +sidebar_label: utils +title: slack_bolt.adapter.asgi.utils +--- + +#### ENCODING + +#### scope\_value\_type + +#### scope\_type diff --git a/docs/english/reference/adapter/aws_lambda/chalice_handler.md b/docs/english/reference/adapter/aws_lambda/chalice_handler.md new file mode 100644 index 000000000..a647098c4 --- /dev/null +++ b/docs/english/reference/adapter/aws_lambda/chalice_handler.md @@ -0,0 +1,46 @@ +--- +sidebar_label: chalice_handler +title: slack_bolt.adapter.aws_lambda.chalice_handler +--- + +## ChaliceSlackRequestHandler Objects + +```python +class ChaliceSlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App, chalice: Chalice, lambda_client: Optional[BaseClient] = None) +``` + +#### clear\_all\_log\_handlers + +```python +def clear_all_log_handlers() +``` + +#### handle + +```python +def handle(request: Request) +``` + +#### to\_bolt\_request + +```python +def to_bolt_request(request: Request, body: str) -> BoltRequest +``` + +#### to\_chalice\_response + +```python +def to_chalice_response(resp: BoltResponse) -> Response +``` + +#### not\_found + +```python +def not_found() -> Response +``` diff --git a/docs/english/reference/adapter/aws_lambda/chalice_lazy_listener_runner.md b/docs/english/reference/adapter/aws_lambda/chalice_lazy_listener_runner.md new file mode 100644 index 000000000..96644a442 --- /dev/null +++ b/docs/english/reference/adapter/aws_lambda/chalice_lazy_listener_runner.md @@ -0,0 +1,22 @@ +--- +sidebar_label: chalice_lazy_listener_runner +title: slack_bolt.adapter.aws_lambda.chalice_lazy_listener_runner +--- + +## ChaliceLazyListenerRunner Objects + +```python +class ChaliceLazyListenerRunner(LazyListenerRunner) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger, lambda_client: Optional[BaseClient] = None) +``` + +#### start + +```python +def start(function: Callable[..., None], request: BoltRequest) -> None +``` diff --git a/docs/english/reference/adapter/aws_lambda/handler.md b/docs/english/reference/adapter/aws_lambda/handler.md new file mode 100644 index 000000000..5de6c9992 --- /dev/null +++ b/docs/english/reference/adapter/aws_lambda/handler.md @@ -0,0 +1,46 @@ +--- +sidebar_label: handler +title: slack_bolt.adapter.aws_lambda.handler +--- + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### clear\_all\_log\_handlers + +```python +def clear_all_log_handlers() +``` + +#### handle + +```python +def handle(event, context) +``` + +#### to\_bolt\_request + +```python +def to_bolt_request(event) -> BoltRequest +``` + +#### to\_aws\_response + +```python +def to_aws_response(resp: BoltResponse) -> Dict[str, Any] +``` + +#### not\_found + +```python +def not_found() -> Dict[str, Any] +``` diff --git a/docs/english/reference/adapter/aws_lambda/index.md b/docs/english/reference/adapter/aws_lambda/index.md new file mode 100644 index 000000000..8666da643 --- /dev/null +++ b/docs/english/reference/adapter/aws_lambda/index.md @@ -0,0 +1,38 @@ +--- +sidebar_label: aws_lambda +title: slack_bolt.adapter.aws_lambda +--- + +## Submodules + +- [slack_bolt.adapter.aws_lambda.chalice_handler](/tools/bolt-python/reference/adapter/aws_lambda/chalice_handler) +- [slack_bolt.adapter.aws_lambda.chalice_lazy_listener_runner](/tools/bolt-python/reference/adapter/aws_lambda/chalice_lazy_listener_runner) +- [slack_bolt.adapter.aws_lambda.handler](/tools/bolt-python/reference/adapter/aws_lambda/handler) +- [slack_bolt.adapter.aws_lambda.internals](/tools/bolt-python/reference/adapter/aws_lambda/internals) +- [slack_bolt.adapter.aws_lambda.lambda_s3_oauth_flow](/tools/bolt-python/reference/adapter/aws_lambda/lambda_s3_oauth_flow) +- [slack_bolt.adapter.aws_lambda.lazy_listener_runner](/tools/bolt-python/reference/adapter/aws_lambda/lazy_listener_runner) +- [slack_bolt.adapter.aws_lambda.local_lambda_client](/tools/bolt-python/reference/adapter/aws_lambda/local_lambda_client) + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### clear\_all\_log\_handlers + +```python +def clear_all_log_handlers() +``` + +#### handle + +```python +def handle(event, context) +``` diff --git a/docs/english/reference/adapter/aws_lambda/internals.md b/docs/english/reference/adapter/aws_lambda/internals.md new file mode 100644 index 000000000..6f0b33a10 --- /dev/null +++ b/docs/english/reference/adapter/aws_lambda/internals.md @@ -0,0 +1,6 @@ +--- +sidebar_label: internals +title: slack_bolt.adapter.aws_lambda.internals +--- + + diff --git a/docs/english/reference/adapter/aws_lambda/lambda_s3_oauth_flow.md b/docs/english/reference/adapter/aws_lambda/lambda_s3_oauth_flow.md new file mode 100644 index 000000000..b050e5dea --- /dev/null +++ b/docs/english/reference/adapter/aws_lambda/lambda_s3_oauth_flow.md @@ -0,0 +1,36 @@ +--- +sidebar_label: lambda_s3_oauth_flow +title: slack_bolt.adapter.aws_lambda.lambda_s3_oauth_flow +--- + +## LambdaS3OAuthFlow Objects + +```python +class LambdaS3OAuthFlow(OAuthFlow) +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + client: Optional[WebClient] = None, + logger: Optional[Logger] = None, + settings: Optional[OAuthSettings] = None, + oauth_state_bucket_name: Optional[str] = None, + installation_bucket_name: Optional[str] = None) +``` + +#### client + +```python +@property +def client() -> WebClient +``` + +#### logger + +```python +@property +def logger() -> Logger +``` diff --git a/docs/english/reference/adapter/aws_lambda/lazy_listener_runner.md b/docs/english/reference/adapter/aws_lambda/lazy_listener_runner.md new file mode 100644 index 000000000..f4b38941a --- /dev/null +++ b/docs/english/reference/adapter/aws_lambda/lazy_listener_runner.md @@ -0,0 +1,22 @@ +--- +sidebar_label: lazy_listener_runner +title: slack_bolt.adapter.aws_lambda.lazy_listener_runner +--- + +## LambdaLazyListenerRunner Objects + +```python +class LambdaLazyListenerRunner(LazyListenerRunner) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger, lambda_client: Optional[Any] = None) +``` + +#### start + +```python +def start(function: Callable[..., None], request: BoltRequest) -> None +``` diff --git a/docs/english/reference/adapter/aws_lambda/local_lambda_client.md b/docs/english/reference/adapter/aws_lambda/local_lambda_client.md new file mode 100644 index 000000000..95a381253 --- /dev/null +++ b/docs/english/reference/adapter/aws_lambda/local_lambda_client.md @@ -0,0 +1,27 @@ +--- +sidebar_label: local_lambda_client +title: slack_bolt.adapter.aws_lambda.local_lambda_client +--- + +## LocalLambdaClient Objects + +```python +class LocalLambdaClient(BaseClient) +``` + +Lambda client implementing `invoke` for use when running with Chalice CLI. + +#### \_\_init\_\_ + +```python +def __init__(app: Chalice, config: Config) -> None +``` + +#### invoke + +```python +def invoke( + FunctionName: str, + InvocationType: str = 'Event', + Payload: str = '{}') -> InvokeResponse +``` diff --git a/docs/english/reference/adapter/bottle/handler.md b/docs/english/reference/adapter/bottle/handler.md new file mode 100644 index 000000000..727a643fc --- /dev/null +++ b/docs/english/reference/adapter/bottle/handler.md @@ -0,0 +1,34 @@ +--- +sidebar_label: handler +title: slack_bolt.adapter.bottle.handler +--- + +#### to\_bolt\_request + +```python +def to_bolt_request(req: Request) -> BoltRequest +``` + +#### set\_response + +```python +def set_response(bolt_resp: BoltResponse, resp: Response) -> None +``` + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +def handle(req: Request, resp: Response) -> str +``` diff --git a/docs/english/reference/adapter/bottle/index.md b/docs/english/reference/adapter/bottle/index.md new file mode 100644 index 000000000..703afa1c9 --- /dev/null +++ b/docs/english/reference/adapter/bottle/index.md @@ -0,0 +1,26 @@ +--- +sidebar_label: bottle +title: slack_bolt.adapter.bottle +--- + +## Submodules + +- [slack_bolt.adapter.bottle.handler](/tools/bolt-python/reference/adapter/bottle/handler) + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +def handle(req: Request, resp: Response) -> str +``` diff --git a/docs/english/reference/adapter/cherrypy/handler.md b/docs/english/reference/adapter/cherrypy/handler.md new file mode 100644 index 000000000..cd477de29 --- /dev/null +++ b/docs/english/reference/adapter/cherrypy/handler.md @@ -0,0 +1,40 @@ +--- +sidebar_label: handler +title: slack_bolt.adapter.cherrypy.handler +--- + +#### build\_bolt\_request + +```python +def build_bolt_request() -> BoltRequest +``` + +#### set\_response\_status\_and\_headers + +```python +def set_response_status_and_headers(bolt_resp: BoltResponse) -> None +``` + +#### slack\_in + +```python +def slack_in() +``` + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +def handle() -> bytes +``` diff --git a/docs/english/reference/adapter/cherrypy/index.md b/docs/english/reference/adapter/cherrypy/index.md new file mode 100644 index 000000000..036c74acc --- /dev/null +++ b/docs/english/reference/adapter/cherrypy/index.md @@ -0,0 +1,26 @@ +--- +sidebar_label: cherrypy +title: slack_bolt.adapter.cherrypy +--- + +## Submodules + +- [slack_bolt.adapter.cherrypy.handler](/tools/bolt-python/reference/adapter/cherrypy/handler) + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +def handle() -> bytes +``` diff --git a/docs/english/reference/adapter/django/handler.md b/docs/english/reference/adapter/django/handler.md new file mode 100644 index 000000000..38f69c2c3 --- /dev/null +++ b/docs/english/reference/adapter/django/handler.md @@ -0,0 +1,84 @@ +--- +sidebar_label: handler +title: slack_bolt.adapter.django.handler +--- + +#### to\_bolt\_request + +```python +def to_bolt_request(req: HttpRequest) -> BoltRequest +``` + +#### to\_django\_response + +```python +def to_django_response(bolt_resp: BoltResponse) -> HttpResponse +``` + +#### release\_thread\_local\_connections + +```python +def release_thread_local_connections(logger: Logger, execution_timing: str) +``` + +## DjangoListenerStartHandler Objects + +```python +class DjangoListenerStartHandler(ListenerStartHandler) +``` + +Django sets DB connections as a thread-local variable per thread. +If the thread is not managed on the Django app side, the connections won't be released by Django. +This handler releases the connections every time a ThreadListenerRunner execution completes. + +#### handle + +```python +def handle(request: BoltRequest, response: Optional[BoltResponse]) -> None +``` + +## DjangoListenerCompletionHandler Objects + +```python +class DjangoListenerCompletionHandler(ListenerCompletionHandler) +``` + +Django sets DB connections as a thread-local variable per thread. +If the thread is not managed on the Django app side, the connections won't be released by Django. +This handler releases the connections every time a ThreadListenerRunner execution completes. + +#### handle + +```python +def handle(request: BoltRequest, response: Optional[BoltResponse]) -> None +``` + +## DjangoThreadLazyListenerRunner Objects + +```python +class DjangoThreadLazyListenerRunner(ThreadLazyListenerRunner) +``` + +#### start + +```python +def start(function: Callable[..., None], request: BoltRequest) -> None +``` + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +def handle(req: HttpRequest) -> HttpResponse +``` diff --git a/docs/english/reference/adapter/django/index.md b/docs/english/reference/adapter/django/index.md new file mode 100644 index 000000000..2d0178e77 --- /dev/null +++ b/docs/english/reference/adapter/django/index.md @@ -0,0 +1,26 @@ +--- +sidebar_label: django +title: slack_bolt.adapter.django +--- + +## Submodules + +- [slack_bolt.adapter.django.handler](/tools/bolt-python/reference/adapter/django/handler) + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +def handle(req: HttpRequest) -> HttpResponse +``` diff --git a/docs/english/reference/adapter/falcon/async_resource.md b/docs/english/reference/adapter/falcon/async_resource.md new file mode 100644 index 000000000..0699ee88f --- /dev/null +++ b/docs/english/reference/adapter/falcon/async_resource.md @@ -0,0 +1,39 @@ +--- +sidebar_label: async_resource +title: slack_bolt.adapter.falcon.async_resource +--- + +## AsyncSlackAppResource Objects + +```python +class AsyncSlackAppResource() +``` + +For use with ASGI Falcon Apps. + +```python +from slack_bolt.async_app import AsyncApp +app = AsyncApp() + +import falcon +app = falcon.asgi.App() +app.add_route("/slack/events", AsyncSlackAppResource(app)) +``` + +#### \_\_init\_\_ + +```python +def __init__(app: AsyncApp) +``` + +#### on\_get + +```python +async def on_get(req: Request, resp: Response) +``` + +#### on\_post + +```python +async def on_post(req: Request, resp: Response) +``` diff --git a/docs/english/reference/adapter/falcon/index.md b/docs/english/reference/adapter/falcon/index.md new file mode 100644 index 000000000..044cb6703 --- /dev/null +++ b/docs/english/reference/adapter/falcon/index.md @@ -0,0 +1,42 @@ +--- +sidebar_label: falcon +title: slack_bolt.adapter.falcon +--- + +## Submodules + +- [slack_bolt.adapter.falcon.async_resource](/tools/bolt-python/reference/adapter/falcon/async_resource) +- [slack_bolt.adapter.falcon.resource](/tools/bolt-python/reference/adapter/falcon/resource) + +## SlackAppResource Objects + +```python +class SlackAppResource() +``` + +```python +from slack_bolt import App +app = App() + +import falcon +api = application = falcon.API() +api.add_route("/slack/events", SlackAppResource(app)) +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### on\_get + +```python +def on_get(req: Request, resp: Response) +``` + +#### on\_post + +```python +def on_post(req: Request, resp: Response) +``` diff --git a/docs/english/reference/adapter/falcon/resource.md b/docs/english/reference/adapter/falcon/resource.md new file mode 100644 index 000000000..d676a8629 --- /dev/null +++ b/docs/english/reference/adapter/falcon/resource.md @@ -0,0 +1,37 @@ +--- +sidebar_label: resource +title: slack_bolt.adapter.falcon.resource +--- + +## SlackAppResource Objects + +```python +class SlackAppResource() +``` + +```python +from slack_bolt import App +app = App() + +import falcon +api = application = falcon.API() +api.add_route("/slack/events", SlackAppResource(app)) +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### on\_get + +```python +def on_get(req: Request, resp: Response) +``` + +#### on\_post + +```python +def on_post(req: Request, resp: Response) +``` diff --git a/docs/english/reference/adapter/fastapi/async_handler.md b/docs/english/reference/adapter/fastapi/async_handler.md new file mode 100644 index 000000000..75497e71b --- /dev/null +++ b/docs/english/reference/adapter/fastapi/async_handler.md @@ -0,0 +1,24 @@ +--- +sidebar_label: async_handler +title: slack_bolt.adapter.fastapi.async_handler +--- + +## AsyncSlackRequestHandler Objects + +```python +class AsyncSlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: AsyncApp) +``` + +#### handle + +```python +async def handle( + req: Request, + addition_context_properties: Optional[Dict[str, Any]] = None) -> Response +``` diff --git a/docs/english/reference/adapter/fastapi/index.md b/docs/english/reference/adapter/fastapi/index.md new file mode 100644 index 000000000..469bc7bb7 --- /dev/null +++ b/docs/english/reference/adapter/fastapi/index.md @@ -0,0 +1,28 @@ +--- +sidebar_label: fastapi +title: slack_bolt.adapter.fastapi +--- + +## Submodules + +- [slack_bolt.adapter.fastapi.async_handler](/tools/bolt-python/reference/adapter/fastapi/async_handler) + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +async def handle( + req: Request, + addition_context_properties: Optional[Dict[str, Any]] = None) -> Response +``` diff --git a/docs/english/reference/adapter/flask/handler.md b/docs/english/reference/adapter/flask/handler.md new file mode 100644 index 000000000..3657debd0 --- /dev/null +++ b/docs/english/reference/adapter/flask/handler.md @@ -0,0 +1,34 @@ +--- +sidebar_label: handler +title: slack_bolt.adapter.flask.handler +--- + +#### to\_bolt\_request + +```python +def to_bolt_request(req: Request) -> BoltRequest +``` + +#### to\_flask\_response + +```python +def to_flask_response(bolt_resp: BoltResponse) -> Response +``` + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +def handle(req: Request) -> Response +``` diff --git a/docs/english/reference/adapter/flask/index.md b/docs/english/reference/adapter/flask/index.md new file mode 100644 index 000000000..80807da8a --- /dev/null +++ b/docs/english/reference/adapter/flask/index.md @@ -0,0 +1,26 @@ +--- +sidebar_label: flask +title: slack_bolt.adapter.flask +--- + +## Submodules + +- [slack_bolt.adapter.flask.handler](/tools/bolt-python/reference/adapter/flask/handler) + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +def handle(req: Request) -> Response +``` diff --git a/docs/english/reference/adapter/google_cloud_functions/handler.md b/docs/english/reference/adapter/google_cloud_functions/handler.md new file mode 100644 index 000000000..0d8807ba8 --- /dev/null +++ b/docs/english/reference/adapter/google_cloud_functions/handler.md @@ -0,0 +1,34 @@ +--- +sidebar_label: handler +title: slack_bolt.adapter.google_cloud_functions.handler +--- + +## NoopLazyListenerRunner Objects + +```python +class NoopLazyListenerRunner(LazyListenerRunner) +``` + +#### start + +```python +def start(function: Callable[..., None], request: BoltRequest) -> None +``` + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +def handle(req: Request) -> Response +``` diff --git a/docs/english/reference/adapter/google_cloud_functions/index.md b/docs/english/reference/adapter/google_cloud_functions/index.md new file mode 100644 index 000000000..56129e6dd --- /dev/null +++ b/docs/english/reference/adapter/google_cloud_functions/index.md @@ -0,0 +1,26 @@ +--- +sidebar_label: google_cloud_functions +title: slack_bolt.adapter.google_cloud_functions +--- + +## Submodules + +- [slack_bolt.adapter.google_cloud_functions.handler](/tools/bolt-python/reference/adapter/google_cloud_functions/handler) + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +def handle(req: Request) -> Response +``` diff --git a/docs/english/reference/adapter/index.md b/docs/english/reference/adapter/index.md new file mode 100644 index 000000000..b0ae1a448 --- /dev/null +++ b/docs/english/reference/adapter/index.md @@ -0,0 +1,25 @@ +--- +sidebar_label: adapter +title: slack_bolt.adapter +--- + +Adapter modules for running Bolt apps along with Web frameworks or Socket Mode. + +## Submodules + +- [slack_bolt.adapter.aiohttp](/tools/bolt-python/reference/adapter/aiohttp) +- [slack_bolt.adapter.asgi](/tools/bolt-python/reference/adapter/asgi) +- [slack_bolt.adapter.aws_lambda](/tools/bolt-python/reference/adapter/aws_lambda) +- [slack_bolt.adapter.bottle](/tools/bolt-python/reference/adapter/bottle) +- [slack_bolt.adapter.cherrypy](/tools/bolt-python/reference/adapter/cherrypy) +- [slack_bolt.adapter.django](/tools/bolt-python/reference/adapter/django) +- [slack_bolt.adapter.falcon](/tools/bolt-python/reference/adapter/falcon) +- [slack_bolt.adapter.fastapi](/tools/bolt-python/reference/adapter/fastapi) +- [slack_bolt.adapter.flask](/tools/bolt-python/reference/adapter/flask) +- [slack_bolt.adapter.google_cloud_functions](/tools/bolt-python/reference/adapter/google_cloud_functions) +- [slack_bolt.adapter.pyramid](/tools/bolt-python/reference/adapter/pyramid) +- [slack_bolt.adapter.sanic](/tools/bolt-python/reference/adapter/sanic) +- [slack_bolt.adapter.socket_mode](/tools/bolt-python/reference/adapter/socket_mode) +- [slack_bolt.adapter.starlette](/tools/bolt-python/reference/adapter/starlette) +- [slack_bolt.adapter.tornado](/tools/bolt-python/reference/adapter/tornado) +- [slack_bolt.adapter.wsgi](/tools/bolt-python/reference/adapter/wsgi) diff --git a/docs/english/reference/adapter/pyramid/handler.md b/docs/english/reference/adapter/pyramid/handler.md new file mode 100644 index 000000000..614d2c19b --- /dev/null +++ b/docs/english/reference/adapter/pyramid/handler.md @@ -0,0 +1,34 @@ +--- +sidebar_label: handler +title: slack_bolt.adapter.pyramid.handler +--- + +#### to\_bolt\_request + +```python +def to_bolt_request(request: Request) -> BoltRequest +``` + +#### to\_pyramid\_response + +```python +def to_pyramid_response(bolt_resp: BoltResponse) -> Response +``` + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +def handle(request: Request) -> Response +``` diff --git a/docs/english/reference/adapter/pyramid/index.md b/docs/english/reference/adapter/pyramid/index.md new file mode 100644 index 000000000..013feb456 --- /dev/null +++ b/docs/english/reference/adapter/pyramid/index.md @@ -0,0 +1,26 @@ +--- +sidebar_label: pyramid +title: slack_bolt.adapter.pyramid +--- + +## Submodules + +- [slack_bolt.adapter.pyramid.handler](/tools/bolt-python/reference/adapter/pyramid/handler) + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +def handle(request: Request) -> Response +``` diff --git a/docs/english/reference/adapter/sanic/async_handler.md b/docs/english/reference/adapter/sanic/async_handler.md new file mode 100644 index 000000000..f24dd05ee --- /dev/null +++ b/docs/english/reference/adapter/sanic/async_handler.md @@ -0,0 +1,38 @@ +--- +sidebar_label: async_handler +title: slack_bolt.adapter.sanic.async_handler +--- + +#### to\_async\_bolt\_request + +```python +def to_async_bolt_request( + req: Request, + addition_context_properties: Optional[Dict[str, Any]] = None) -> AsyncBoltRequest +``` + +#### to\_sanic\_response + +```python +def to_sanic_response(bolt_resp: BoltResponse) -> HTTPResponse +``` + +## AsyncSlackRequestHandler Objects + +```python +class AsyncSlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: AsyncApp) +``` + +#### handle + +```python +async def handle( + req: Request, + addition_context_properties: Optional[Dict[str, Any]] = None) -> HTTPResponse +``` diff --git a/docs/english/reference/adapter/sanic/index.md b/docs/english/reference/adapter/sanic/index.md new file mode 100644 index 000000000..fccec02f8 --- /dev/null +++ b/docs/english/reference/adapter/sanic/index.md @@ -0,0 +1,28 @@ +--- +sidebar_label: sanic +title: slack_bolt.adapter.sanic +--- + +## Submodules + +- [slack_bolt.adapter.sanic.async_handler](/tools/bolt-python/reference/adapter/sanic/async_handler) + +## AsyncSlackRequestHandler Objects + +```python +class AsyncSlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: AsyncApp) +``` + +#### handle + +```python +async def handle( + req: Request, + addition_context_properties: Optional[Dict[str, Any]] = None) -> HTTPResponse +``` diff --git a/docs/english/reference/adapter/socket_mode/aiohttp/index.md b/docs/english/reference/adapter/socket_mode/aiohttp/index.md new file mode 100644 index 000000000..c815720a8 --- /dev/null +++ b/docs/english/reference/adapter/socket_mode/aiohttp/index.md @@ -0,0 +1,78 @@ +--- +sidebar_label: aiohttp +title: slack_bolt.adapter.socket_mode.aiohttp +--- + +[`aiohttp`](https://pypi.org/project/aiohttp/) based implementation / asyncio compatible + +## SocketModeHandler Objects + +```python +class SocketModeHandler(AsyncBaseSocketModeHandler) +``` + +#### app: `App` + +#### app\_token: `str` + +#### client: `SocketModeClient` + +#### \_\_init\_\_ + +```python +def __init__( + app: App, + app_token: Optional[str] = None, + logger: Optional[Logger] = None, + web_client: Optional[AsyncWebClient] = None, + proxy: Optional[str] = None, + ping_interval: float = 10) +``` + +Socket Mode adapter for Bolt apps + +**Arguments**: + +- `app` _App_ - The Bolt app +- `app_token` _Optional[str]_ - App-level token starting with `xapp-` +- `logger` _Optional[Logger]_ - Custom logger +- `web_client` _Optional[AsyncWebClient]_ - custom `slack_sdk.web.WebClient` instance +- `proxy` _Optional[str]_ - HTTP proxy URL +- `ping_interval` _float_ - The ping-pong internal (seconds) + +#### handle + +```python +async def handle(client: SocketModeClient, req: SocketModeRequest) -> None +``` + +## AsyncSocketModeHandler Objects + +```python +class AsyncSocketModeHandler(AsyncBaseSocketModeHandler) +``` + +#### app: `AsyncApp` + +#### app\_token: `str` + +#### client: `SocketModeClient` + +#### \_\_init\_\_ + +```python +def __init__( + app: AsyncApp, + app_token: Optional[str] = None, + logger: Optional[Logger] = None, + web_client: Optional[AsyncWebClient] = None, + proxy: Optional[str] = None, + ping_interval: float = 10, + loop: Optional[AbstractEventLoop] = None) +``` + +#### handle + +```python +async def handle(client: SocketModeClient, req: SocketModeRequest) -> None +``` diff --git a/docs/english/reference/adapter/socket_mode/async_base_handler.md b/docs/english/reference/adapter/socket_mode/async_base_handler.md new file mode 100644 index 000000000..7bdf141da --- /dev/null +++ b/docs/english/reference/adapter/socket_mode/async_base_handler.md @@ -0,0 +1,63 @@ +--- +sidebar_label: async_base_handler +title: slack_bolt.adapter.socket_mode.async_base_handler +--- + +The base class of asyncio-based Socket Mode client implementation + +## AsyncBaseSocketModeHandler Objects + +```python +class AsyncBaseSocketModeHandler() +``` + +#### app: `Union[App, AsyncApp]` + +#### client: `AsyncBaseSocketModeClient` + +#### handle + +```python +async def handle(client: AsyncBaseSocketModeClient, req: SocketModeRequest) -> None +``` + +Handles Socket Mode envelope requests through a WebSocket connection. + +**Arguments**: + +- `client` _AsyncBaseSocketModeClient_ - this Socket Mode client instance +- `req` _SocketModeRequest_ - the request data + +#### connect\_async + +```python +async def connect_async() +``` + +Establishes a new connection with the Socket Mode server + +#### disconnect\_async + +```python +async def disconnect_async() +``` + +Disconnects the current WebSocket connection with the Socket Mode server + +#### close\_async + +```python +async def close_async() +``` + +Disconnects from the Socket Mode server and cleans the resources this instance holds up + +#### start\_async + +```python +async def start_async() +``` + +Establishes a new connection and then starts infinite sleep +to prevent the termination of this process. +If you don't want to have the sleep, use `#connect()` method instead. diff --git a/docs/english/reference/adapter/socket_mode/async_handler.md b/docs/english/reference/adapter/socket_mode/async_handler.md new file mode 100644 index 000000000..6f4503a26 --- /dev/null +++ b/docs/english/reference/adapter/socket_mode/async_handler.md @@ -0,0 +1,37 @@ +--- +sidebar_label: async_handler +title: slack_bolt.adapter.socket_mode.async_handler +--- + +Default implementation is the aiohttp-based one. + +## AsyncSocketModeHandler Objects + +```python +class AsyncSocketModeHandler(AsyncBaseSocketModeHandler) +``` + +#### app: `AsyncApp` + +#### app\_token: `str` + +#### client: `SocketModeClient` + +#### \_\_init\_\_ + +```python +def __init__( + app: AsyncApp, + app_token: Optional[str] = None, + logger: Optional[Logger] = None, + web_client: Optional[AsyncWebClient] = None, + proxy: Optional[str] = None, + ping_interval: float = 10, + loop: Optional[AbstractEventLoop] = None) +``` + +#### handle + +```python +async def handle(client: SocketModeClient, req: SocketModeRequest) -> None +``` diff --git a/docs/english/reference/adapter/socket_mode/async_internals.md b/docs/english/reference/adapter/socket_mode/async_internals.md new file mode 100644 index 000000000..38805123b --- /dev/null +++ b/docs/english/reference/adapter/socket_mode/async_internals.md @@ -0,0 +1,22 @@ +--- +sidebar_label: async_internals +title: slack_bolt.adapter.socket_mode.async_internals +--- + +Internal functions + +#### run\_async\_bolt\_app + +```python +async def run_async_bolt_app(app: AsyncApp, req: SocketModeRequest) +``` + +#### send\_async\_response + +```python +async def send_async_response( + client: AsyncBaseSocketModeClient, + req: SocketModeRequest, + bolt_resp: BoltResponse, + start_time: float) +``` diff --git a/docs/english/reference/adapter/socket_mode/base_handler.md b/docs/english/reference/adapter/socket_mode/base_handler.md new file mode 100644 index 000000000..68524f6a3 --- /dev/null +++ b/docs/english/reference/adapter/socket_mode/base_handler.md @@ -0,0 +1,64 @@ +--- +sidebar_label: base_handler +title: slack_bolt.adapter.socket_mode.base_handler +--- + +The base class of Socket Mode client implementation. +If you want to build asyncio-based ones, use `AsyncBaseSocketModeHandler` instead. + +## BaseSocketModeHandler Objects + +```python +class BaseSocketModeHandler() +``` + +#### app: `App` + +#### client: `BaseSocketModeClient` + +#### handle + +```python +def handle(client: BaseSocketModeClient, req: SocketModeRequest) -> None +``` + +Handles Socket Mode envelope requests through a WebSocket connection. + +**Arguments**: + +- `client` _BaseSocketModeClient_ - this Socket Mode client instance +- `req` _SocketModeRequest_ - the request data + +#### connect + +```python +def connect() +``` + +Establishes a new connection with the Socket Mode server + +#### disconnect + +```python +def disconnect() +``` + +Disconnects the current WebSocket connection with the Socket Mode server + +#### close + +```python +def close() +``` + +Disconnects from the Socket Mode server and cleans the resources this instance holds up + +#### start + +```python +def start() +``` + +Establishes a new connection and then blocks the current thread +to prevent the termination of this process. +If you don't want to block the current thread, use `#connect()` method instead. diff --git a/docs/english/reference/adapter/socket_mode/builtin/index.md b/docs/english/reference/adapter/socket_mode/builtin/index.md new file mode 100644 index 000000000..94cb7ae75 --- /dev/null +++ b/docs/english/reference/adapter/socket_mode/builtin/index.md @@ -0,0 +1,61 @@ +--- +sidebar_label: builtin +title: slack_bolt.adapter.socket_mode.builtin +--- + +The built-in implementation, which does not have any external dependencies + +## SocketModeHandler Objects + +```python +class SocketModeHandler(BaseSocketModeHandler) +``` + +#### app: `App` + +#### app\_token: `str` + +#### client: `SocketModeClient` + +#### \_\_init\_\_ + +```python +def __init__( + app: App, + app_token: Optional[str] = None, + logger: Optional[Logger] = None, + web_client: Optional[WebClient] = None, + proxy: Optional[str] = None, + proxy_headers: Optional[Dict[str, str]] = None, + auto_reconnect_enabled: bool = True, + trace_enabled: bool = False, + all_message_trace_enabled: bool = False, + ping_pong_trace_enabled: bool = False, + ping_interval: float = 10, + receive_buffer_size: int = 1024, + concurrency: int = 10) +``` + +Socket Mode adapter for Bolt apps + +**Arguments**: + +- `app` _App_ - The Bolt app +- `app_token` _Optional[str]_ - App-level token starting with `xapp-` +- `logger` _Optional[Logger]_ - Custom logger +- `web_client` _Optional[WebClient]_ - custom `slack_sdk.web.WebClient` instance +- `proxy` _Optional[str]_ - HTTP proxy URL +- `proxy_headers` _Optional[Dict[str, str]]_ - Additional request header for proxy connections +- `auto_reconnect_enabled` _bool_ - True if the auto-reconnect logic works +- `trace_enabled` _bool_ - True if trace-level logging is enabled +- `all_message_trace_enabled` _bool_ - True if trace-logging for all received WebSocket messages is enabled +- `ping_pong_trace_enabled` _bool_ - True if trace-logging for all ping-pong communications +- `ping_interval` _float_ - The ping-pong internal (seconds) +- `receive_buffer_size` _int_ - The data length for a single socket recv operation +- `concurrency` _int_ - The size of the underlying thread pool + +#### handle + +```python +def handle(client: SocketModeClient, req: SocketModeRequest) -> None +``` diff --git a/docs/english/reference/adapter/socket_mode/index.md b/docs/english/reference/adapter/socket_mode/index.md new file mode 100644 index 000000000..d934d9c17 --- /dev/null +++ b/docs/english/reference/adapter/socket_mode/index.md @@ -0,0 +1,78 @@ +--- +sidebar_label: socket_mode +title: slack_bolt.adapter.socket_mode +--- + +Socket Mode adapter package provides the following implementations. If you don't have strong reasons to use 3rd party library based adapters, we recommend using the built-in client based one. + +* `slack_bolt.adapter.socket_mode.builtin` +* `slack_bolt.adapter.socket_mode.websocket_client` +* `slack_bolt.adapter.socket_mode.aiohttp` +* `slack_bolt.adapter.socket_mode.websockets` + +## Submodules + +- [slack_bolt.adapter.socket_mode.aiohttp](/tools/bolt-python/reference/adapter/socket_mode/aiohttp) +- [slack_bolt.adapter.socket_mode.async_base_handler](/tools/bolt-python/reference/adapter/socket_mode/async_base_handler) +- [slack_bolt.adapter.socket_mode.async_handler](/tools/bolt-python/reference/adapter/socket_mode/async_handler) +- [slack_bolt.adapter.socket_mode.async_internals](/tools/bolt-python/reference/adapter/socket_mode/async_internals) +- [slack_bolt.adapter.socket_mode.base_handler](/tools/bolt-python/reference/adapter/socket_mode/base_handler) +- [slack_bolt.adapter.socket_mode.builtin](/tools/bolt-python/reference/adapter/socket_mode/builtin) +- [slack_bolt.adapter.socket_mode.internals](/tools/bolt-python/reference/adapter/socket_mode/internals) +- [slack_bolt.adapter.socket_mode.websocket_client](/tools/bolt-python/reference/adapter/socket_mode/websocket_client) +- [slack_bolt.adapter.socket_mode.websockets](/tools/bolt-python/reference/adapter/socket_mode/websockets) + +## SocketModeHandler Objects + +```python +class SocketModeHandler(BaseSocketModeHandler) +``` + +#### app: `App` + +#### app\_token: `str` + +#### client: `SocketModeClient` + +#### \_\_init\_\_ + +```python +def __init__( + app: App, + app_token: Optional[str] = None, + logger: Optional[Logger] = None, + web_client: Optional[WebClient] = None, + proxy: Optional[str] = None, + proxy_headers: Optional[Dict[str, str]] = None, + auto_reconnect_enabled: bool = True, + trace_enabled: bool = False, + all_message_trace_enabled: bool = False, + ping_pong_trace_enabled: bool = False, + ping_interval: float = 10, + receive_buffer_size: int = 1024, + concurrency: int = 10) +``` + +Socket Mode adapter for Bolt apps + +**Arguments**: + +- `app` _App_ - The Bolt app +- `app_token` _Optional[str]_ - App-level token starting with `xapp-` +- `logger` _Optional[Logger]_ - Custom logger +- `web_client` _Optional[WebClient]_ - custom `slack_sdk.web.WebClient` instance +- `proxy` _Optional[str]_ - HTTP proxy URL +- `proxy_headers` _Optional[Dict[str, str]]_ - Additional request header for proxy connections +- `auto_reconnect_enabled` _bool_ - True if the auto-reconnect logic works +- `trace_enabled` _bool_ - True if trace-level logging is enabled +- `all_message_trace_enabled` _bool_ - True if trace-logging for all received WebSocket messages is enabled +- `ping_pong_trace_enabled` _bool_ - True if trace-logging for all ping-pong communications +- `ping_interval` _float_ - The ping-pong internal (seconds) +- `receive_buffer_size` _int_ - The data length for a single socket recv operation +- `concurrency` _int_ - The size of the underlying thread pool + +#### handle + +```python +def handle(client: SocketModeClient, req: SocketModeRequest) -> None +``` diff --git a/docs/english/reference/adapter/socket_mode/internals.md b/docs/english/reference/adapter/socket_mode/internals.md new file mode 100644 index 000000000..794cfd995 --- /dev/null +++ b/docs/english/reference/adapter/socket_mode/internals.md @@ -0,0 +1,29 @@ +--- +sidebar_label: internals +title: slack_bolt.adapter.socket_mode.internals +--- + +Internal functions + +#### build\_headers + +```python +def build_headers( + req: SocketModeRequest) -> Optional[Dict[str, Union[str, Sequence[str]]]] +``` + +#### run\_bolt\_app + +```python +def run_bolt_app(app: App, req: SocketModeRequest) +``` + +#### send\_response + +```python +def send_response( + client: BaseSocketModeClient, + req: SocketModeRequest, + bolt_resp: BoltResponse, + start_time: float) +``` diff --git a/docs/english/reference/adapter/socket_mode/websocket_client/index.md b/docs/english/reference/adapter/socket_mode/websocket_client/index.md new file mode 100644 index 000000000..c2b503621 --- /dev/null +++ b/docs/english/reference/adapter/socket_mode/websocket_client/index.md @@ -0,0 +1,57 @@ +--- +sidebar_label: websocket_client +title: slack_bolt.adapter.socket_mode.websocket_client +--- + +[`websocket-client`](https://pypi.org/project/websocket-client/) based implementation + +## SocketModeHandler Objects + +```python +class SocketModeHandler(BaseSocketModeHandler) +``` + +#### app: `App` + +#### app\_token: `str` + +#### client: `SocketModeClient` + +#### \_\_init\_\_ + +```python +def __init__( + app: App, + app_token: Optional[str] = None, + logger: Optional[Logger] = None, + web_client: Optional[WebClient] = None, + ping_interval: float = 10, + concurrency: int = 10, + http_proxy_host: Optional[str] = None, + http_proxy_port: Optional[int] = None, + http_proxy_auth: Optional[Tuple[str, str]] = None, + proxy_type: Optional[str] = None, + trace_enabled: bool = False) +``` + +Socket Mode adapter for Bolt apps + +**Arguments**: + +- `app` _App_ - The Bolt app +- `app_token` _Optional[str]_ - App-level token starting with `xapp-` +- `logger` _Optional[Logger]_ - Custom logger +- `web_client` _Optional[WebClient]_ - custom `slack_sdk.web.WebClient` instance +- `ping_interval` _float_ - The ping-pong internal (seconds) +- `concurrency` _int_ - The size of the underlying thread pool +- `http_proxy_host` _Optional[str]_ - HTTP proxy host +- `http_proxy_port` _Optional[int]_ - HTTP proxy port +- `http_proxy_auth` _Optional[Tuple[str, str]]_ - HTTP proxy authentication (username, password) +- `proxy_type` _Optional[str]_ - Proxy type +- `trace_enabled` _bool_ - True if trace-level logging is enabled + +#### handle + +```python +def handle(client: SocketModeClient, req: SocketModeRequest) -> None +``` diff --git a/docs/english/reference/adapter/socket_mode/websockets/index.md b/docs/english/reference/adapter/socket_mode/websockets/index.md new file mode 100644 index 000000000..6d77a1bb2 --- /dev/null +++ b/docs/english/reference/adapter/socket_mode/websockets/index.md @@ -0,0 +1,78 @@ +--- +sidebar_label: websockets +title: slack_bolt.adapter.socket_mode.websockets +--- + +[`websockets`](https://pypi.org/project/websockets/) based implementation / asyncio compatible + +## SocketModeHandler Objects + +```python +class SocketModeHandler(AsyncBaseSocketModeHandler) +``` + +#### app: `App` + +#### app\_token: `str` + +#### client: `SocketModeClient` + +#### \_\_init\_\_ + +```python +def __init__( + app: App, + app_token: Optional[str] = None, + logger: Optional[Logger] = None, + web_client: Optional[AsyncWebClient] = None, + ping_interval: float = 10) +``` + +Socket Mode adapter for Bolt apps. + +Please note that this adapter does not support proxy configuration +as the underlying websockets module does not support proxy-wired connections. +If you use proxy, consider using one of the other Socket Mode adapters. + +**Arguments**: + +- `app` _App_ - The Bolt app +- `app_token` _Optional[str]_ - App-level token starting with `xapp-` +- `logger` _Optional[Logger]_ - Custom logger +- `web_client` _Optional[AsyncWebClient]_ - custom `slack_sdk.web.WebClient` instance +- `ping_interval` _float_ - The ping-pong internal (seconds) + +#### handle + +```python +async def handle(client: SocketModeClient, req: SocketModeRequest) -> None +``` + +## AsyncSocketModeHandler Objects + +```python +class AsyncSocketModeHandler(AsyncBaseSocketModeHandler) +``` + +#### app: `AsyncApp` + +#### app\_token: `str` + +#### client: `SocketModeClient` + +#### \_\_init\_\_ + +```python +def __init__( + app: AsyncApp, + app_token: Optional[str] = None, + logger: Optional[Logger] = None, + web_client: Optional[AsyncWebClient] = None, + ping_interval: float = 10) +``` + +#### handle + +```python +async def handle(client: SocketModeClient, req: SocketModeRequest) -> None +``` diff --git a/docs/english/reference/adapter/starlette/async_handler.md b/docs/english/reference/adapter/starlette/async_handler.md new file mode 100644 index 000000000..2ac2f00b3 --- /dev/null +++ b/docs/english/reference/adapter/starlette/async_handler.md @@ -0,0 +1,39 @@ +--- +sidebar_label: async_handler +title: slack_bolt.adapter.starlette.async_handler +--- + +#### to\_async\_bolt\_request + +```python +def to_async_bolt_request( + req: Request, + body: bytes, + addition_context_properties: Optional[Dict[str, Any]] = None) -> AsyncBoltRequest +``` + +#### to\_starlette\_response + +```python +def to_starlette_response(bolt_resp: BoltResponse) -> Response +``` + +## AsyncSlackRequestHandler Objects + +```python +class AsyncSlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: AsyncApp) +``` + +#### handle + +```python +async def handle( + req: Request, + addition_context_properties: Optional[Dict[str, Any]] = None) -> Response +``` diff --git a/docs/english/reference/adapter/starlette/handler.md b/docs/english/reference/adapter/starlette/handler.md new file mode 100644 index 000000000..206ccad91 --- /dev/null +++ b/docs/english/reference/adapter/starlette/handler.md @@ -0,0 +1,39 @@ +--- +sidebar_label: handler +title: slack_bolt.adapter.starlette.handler +--- + +#### to\_bolt\_request + +```python +def to_bolt_request( + req: Request, + body: bytes, + addition_context_properties: Optional[Dict[str, Any]] = None) -> BoltRequest +``` + +#### to\_starlette\_response + +```python +def to_starlette_response(bolt_resp: BoltResponse) -> Response +``` + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +async def handle( + req: Request, + addition_context_properties: Optional[Dict[str, Any]] = None) -> Response +``` diff --git a/docs/english/reference/adapter/starlette/index.md b/docs/english/reference/adapter/starlette/index.md new file mode 100644 index 000000000..fd29b9306 --- /dev/null +++ b/docs/english/reference/adapter/starlette/index.md @@ -0,0 +1,29 @@ +--- +sidebar_label: starlette +title: slack_bolt.adapter.starlette +--- + +## Submodules + +- [slack_bolt.adapter.starlette.async_handler](/tools/bolt-python/reference/adapter/starlette/async_handler) +- [slack_bolt.adapter.starlette.handler](/tools/bolt-python/reference/adapter/starlette/handler) + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App) +``` + +#### handle + +```python +async def handle( + req: Request, + addition_context_properties: Optional[Dict[str, Any]] = None) -> Response +``` diff --git a/docs/english/reference/adapter/tornado/async_handler.md b/docs/english/reference/adapter/tornado/async_handler.md new file mode 100644 index 000000000..cc9f21ff8 --- /dev/null +++ b/docs/english/reference/adapter/tornado/async_handler.md @@ -0,0 +1,46 @@ +--- +sidebar_label: async_handler +title: slack_bolt.adapter.tornado.async_handler +--- + +## AsyncSlackEventsHandler Objects + +```python +class AsyncSlackEventsHandler(RequestHandler) +``` + +#### initialize + +```python +def initialize(app: AsyncApp) +``` + +#### post + +```python +async def post() +``` + +## AsyncSlackOAuthHandler Objects + +```python +class AsyncSlackOAuthHandler(RequestHandler) +``` + +#### initialize + +```python +def initialize(app: AsyncApp) +``` + +#### get + +```python +async def get() +``` + +#### to\_async\_bolt\_request + +```python +def to_async_bolt_request(req: HTTPServerRequest) -> AsyncBoltRequest +``` diff --git a/docs/english/reference/adapter/tornado/handler.md b/docs/english/reference/adapter/tornado/handler.md new file mode 100644 index 000000000..a549c990c --- /dev/null +++ b/docs/english/reference/adapter/tornado/handler.md @@ -0,0 +1,52 @@ +--- +sidebar_label: handler +title: slack_bolt.adapter.tornado.handler +--- + +## SlackEventsHandler Objects + +```python +class SlackEventsHandler(RequestHandler) +``` + +#### initialize + +```python +def initialize(app: App) +``` + +#### post + +```python +def post() +``` + +## SlackOAuthHandler Objects + +```python +class SlackOAuthHandler(RequestHandler) +``` + +#### initialize + +```python +def initialize(app: App) +``` + +#### get + +```python +def get() +``` + +#### to\_bolt\_request + +```python +def to_bolt_request(req: HTTPServerRequest) -> BoltRequest +``` + +#### set\_response + +```python +def set_response(self, bolt_resp) -> None +``` diff --git a/docs/english/reference/adapter/tornado/index.md b/docs/english/reference/adapter/tornado/index.md new file mode 100644 index 000000000..2877d5848 --- /dev/null +++ b/docs/english/reference/adapter/tornado/index.md @@ -0,0 +1,45 @@ +--- +sidebar_label: tornado +title: slack_bolt.adapter.tornado +--- + +## Submodules + +- [slack_bolt.adapter.tornado.async_handler](/tools/bolt-python/reference/adapter/tornado/async_handler) +- [slack_bolt.adapter.tornado.handler](/tools/bolt-python/reference/adapter/tornado/handler) + +## SlackEventsHandler Objects + +```python +class SlackEventsHandler(RequestHandler) +``` + +#### initialize + +```python +def initialize(app: App) +``` + +#### post + +```python +def post() +``` + +## SlackOAuthHandler Objects + +```python +class SlackOAuthHandler(RequestHandler) +``` + +#### initialize + +```python +def initialize(app: App) +``` + +#### get + +```python +def get() +``` diff --git a/docs/english/reference/adapter/wsgi/handler.md b/docs/english/reference/adapter/wsgi/handler.md new file mode 100644 index 000000000..b3fc3f009 --- /dev/null +++ b/docs/english/reference/adapter/wsgi/handler.md @@ -0,0 +1,58 @@ +--- +sidebar_label: handler +title: slack_bolt.adapter.wsgi.handler +--- + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App, path: str = '/slack/events') +``` + +Setup Bolt as a WSGI web framework, this will make your application compatible with WSGI web servers. +This can be used for production deployments. + +With the default settings, `http://localhost:3000/slack/events` +Run Bolt with [gunicorn](https://gunicorn.org/) + +```python +app = App() + +api = SlackRequestHandler(app) +``` + +```bash +export SLACK_SIGNING_SECRET=*** +export SLACK_BOT_TOKEN=xoxb-*** + +gunicorn app:api -b 0.0.0.0:3000 --log-level debug +``` + +**Arguments**: + +- `app` _App_ - Your bolt application +- `path` _str_ - The path to handle request from Slack (Default: `/slack/events`) + +#### dispatch + +```python +def dispatch(request: WsgiHttpRequest) -> BoltResponse +``` + +#### handle\_installation + +```python +def handle_installation(request: WsgiHttpRequest) -> BoltResponse +``` + +#### handle\_callback + +```python +def handle_callback(request: WsgiHttpRequest) -> BoltResponse +``` diff --git a/docs/english/reference/adapter/wsgi/http_request.md b/docs/english/reference/adapter/wsgi/http_request.md new file mode 100644 index 000000000..7134a5c6e --- /dev/null +++ b/docs/english/reference/adapter/wsgi/http_request.md @@ -0,0 +1,41 @@ +--- +sidebar_label: http_request +title: slack_bolt.adapter.wsgi.http_request +--- + +## WsgiHttpRequest Objects + +```python +class WsgiHttpRequest() +``` + +This Class uses the PEP 3333 standard to extract request information +from the WSGI web server running the application + +PEP 3333: https://peps.python.org/pep-3333/ + +#### \_\_init\_\_ + +```python +def __init__(environ: WSGIEnvironment) +``` + +#### method: `str` + +#### path: `str` + +#### query\_string: `str` + +#### protocol: `str` + +#### get\_headers + +```python +def get_headers() -> Dict[str, Union[str, Sequence[str]]] +``` + +#### get\_body + +```python +def get_body() -> str +``` diff --git a/docs/english/reference/adapter/wsgi/http_response.md b/docs/english/reference/adapter/wsgi/http_response.md new file mode 100644 index 000000000..272e49981 --- /dev/null +++ b/docs/english/reference/adapter/wsgi/http_response.md @@ -0,0 +1,36 @@ +--- +sidebar_label: http_response +title: slack_bolt.adapter.wsgi.http_response +--- + +## WsgiHttpResponse Objects + +```python +class WsgiHttpResponse() +``` + +This Class uses the PEP 3333 standard to adapt bolt response information +for the WSGI web server running the application + +PEP 3333: https://peps.python.org/pep-3333/ + +#### \_\_init\_\_ + +```python +def __init__( + status: int, + headers: Optional[Dict[str, Sequence[str]]] = None, + body: str = '') +``` + +#### get\_headers + +```python +def get_headers() -> List[Tuple[str, str]] +``` + +#### get\_body + +```python +def get_body() -> Iterable[bytes] +``` diff --git a/docs/english/reference/adapter/wsgi/index.md b/docs/english/reference/adapter/wsgi/index.md new file mode 100644 index 000000000..336f6cdca --- /dev/null +++ b/docs/english/reference/adapter/wsgi/index.md @@ -0,0 +1,65 @@ +--- +sidebar_label: wsgi +title: slack_bolt.adapter.wsgi +--- + +## Submodules + +- [slack_bolt.adapter.wsgi.handler](/tools/bolt-python/reference/adapter/wsgi/handler) +- [slack_bolt.adapter.wsgi.http_request](/tools/bolt-python/reference/adapter/wsgi/http_request) +- [slack_bolt.adapter.wsgi.http_response](/tools/bolt-python/reference/adapter/wsgi/http_response) +- [slack_bolt.adapter.wsgi.internals](/tools/bolt-python/reference/adapter/wsgi/internals) + +## SlackRequestHandler Objects + +```python +class SlackRequestHandler() +``` + +#### \_\_init\_\_ + +```python +def __init__(app: App, path: str = '/slack/events') +``` + +Setup Bolt as a WSGI web framework, this will make your application compatible with WSGI web servers. +This can be used for production deployments. + +With the default settings, `http://localhost:3000/slack/events` +Run Bolt with [gunicorn](https://gunicorn.org/) + +```python +app = App() + +api = SlackRequestHandler(app) +``` + +```bash +export SLACK_SIGNING_SECRET=*** +export SLACK_BOT_TOKEN=xoxb-*** + +gunicorn app:api -b 0.0.0.0:3000 --log-level debug +``` + +**Arguments**: + +- `app` _App_ - Your bolt application +- `path` _str_ - The path to handle request from Slack (Default: `/slack/events`) + +#### dispatch + +```python +def dispatch(request: WsgiHttpRequest) -> BoltResponse +``` + +#### handle\_installation + +```python +def handle_installation(request: WsgiHttpRequest) -> BoltResponse +``` + +#### handle\_callback + +```python +def handle_callback(request: WsgiHttpRequest) -> BoltResponse +``` diff --git a/docs/english/reference/adapter/wsgi/internals.md b/docs/english/reference/adapter/wsgi/internals.md new file mode 100644 index 000000000..19433fb00 --- /dev/null +++ b/docs/english/reference/adapter/wsgi/internals.md @@ -0,0 +1,6 @@ +--- +sidebar_label: internals +title: slack_bolt.adapter.wsgi.internals +--- + +#### ENCODING diff --git a/docs/english/reference/app/app.md b/docs/english/reference/app/app.md new file mode 100644 index 000000000..d376234ba --- /dev/null +++ b/docs/english/reference/app/app.md @@ -0,0 +1,837 @@ +--- +sidebar_label: app +title: slack_bolt.app.app +slug: app +--- + +## App Objects + +```python +class App() +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + logger: Optional[logging.Logger] = None, + name: Optional[str] = None, + process_before_response: bool = False, + raise_error_for_unhandled_request: bool = False, + signing_secret: Optional[str] = None, + token: Optional[str] = None, + token_verification_enabled: bool = True, + client: Optional[WebClient] = None, + before_authorize: Optional[Union[Middleware, Callable[..., Any]]] = None, + authorize: Optional[Callable[..., AuthorizeResult]] = None, + user_facing_authorize_error_message: Optional[str] = None, + installation_store: Optional[InstallationStore] = None, + installation_store_bot_only: Optional[bool] = None, + request_verification_enabled: bool = True, + ignoring_self_events_enabled: bool = True, + ignoring_self_assistant_message_events_enabled: bool = True, + ssl_check_enabled: bool = True, + url_verification_enabled: bool = True, + attaching_function_token_enabled: bool = True, + oauth_settings: Optional[OAuthSettings] = None, + oauth_flow: Optional[OAuthFlow] = None, + verification_token: Optional[str] = None, + listener_executor: Optional[Executor] = None, + assistant_thread_context_store: Optional[AssistantThreadContextStore] = None, + attaching_conversation_kwargs_enabled: bool = True) +``` + +Bolt App that provides functionalities to register middleware/listeners. + +```python +import os +from slack_bolt import App + +# Initializes your app with your bot token and signing secret +app = App( + token=os.environ.get("SLACK_BOT_TOKEN"), + signing_secret=os.environ.get("SLACK_SIGNING_SECRET") +) + +# Listens to incoming messages that contain "hello" +@app.message("hello") +def message_hello(message, say): + # say() sends a message to the channel where the event was triggered + say(f"Hey there <@{message['user']}>!") + +# Start your app +if __name__ == "__main__": + app.start(port=int(os.environ.get("PORT", 3000))) +``` + +Refer to https://docs.slack.dev/tools/bolt-python/creating-an-app for details. + +If you would like to build an OAuth app for enabling the app to run with multiple workspaces, +refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app. + +**Arguments**: + +- `logger` _Optional[logging.Logger]_ - The custom logger that can be used in this app. +- `name` _Optional[str]_ - The application name that will be used in logging. If absent, the source file name will be used. +- `process_before_response` _bool_ - True if this app runs on Function as a Service. (Default: False) +- `raise_error_for_unhandled_request` _bool_ - True if you want to raise exceptions for unhandled requests + and use @app.error listeners instead of + the built-in handler, which pints warning logs and returns 404 to Slack (Default: False) +- `signing_secret` _Optional[str]_ - The Signing Secret value used for verifying requests from Slack. +- `token` _Optional[str]_ - The bot/user access token required only for single-workspace app. +- `token_verification_enabled` _bool_ - Verifies the validity of the given token if True. +- `client` _Optional[WebClient]_ - The singleton `slack_sdk.WebClient` instance for this app. +- `before_authorize` _Optional[Union[Middleware, Callable[..., Any]]]_ - A global middleware that can be executed right before authorize function +- `authorize` _Optional[Callable[..., AuthorizeResult]]_ - The function to authorize an incoming request from Slack + by checking if there is a team/user in the installation data. +- `user_facing_authorize_error_message` _Optional[str]_ - The user-facing error message to display + when the app is installed but the installation is not managed by this app's installation store +- `installation_store` _Optional[InstallationStore]_ - The module offering save/find operations of installation data +- `installation_store_bot_only` _Optional[bool]_ - Use `InstallationStore#find_bot()` if True (Default: False) +- `request_verification_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `RequestVerification` is a built-in middleware that verifies the signature in HTTP Mode requests. + Make sure if it's safe enough when you turn a built-in middleware off. + We strongly recommend using RequestVerification for better security. + If you have a proxy that verifies request signature in front of the Bolt app, + it's totally fine to disable RequestVerification to avoid duplication of work. + Don't turn it off just for easiness of development. +- `ignoring_self_events_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `IgnoringSelfEvents` is a built-in middleware that enables Bolt apps to easily skip the events + generated by this app's bot user (this is useful for avoiding code error causing an infinite loop). +- `ignoring_self_assistant_message_events_enabled` _bool_ - False if you would like to disable the built-in middleware. + `IgnoringSelfEvents` for this app's bot user message events within an assistant thread + This is useful for avoiding code error causing an infinite loop; Default: True +- `url_verification_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `UrlVerification` is a built-in middleware that handles url_verification requests + that verify the endpoint for Events API in HTTP Mode requests. +- `attaching_function_token_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `AttachingFunctionToken` is a built-in middleware that injects the just-in-time workflow-execution tokens + when your app receives `function_executed` or interactivity events scoped to a custom step. +- `ssl_check_enabled` _bool_ - bool = False if you would like to disable the built-in middleware (Default: True). + `SslCheck` is a built-in middleware that handles ssl_check requests from Slack. +- `oauth_settings` _Optional[OAuthSettings]_ - The settings related to Slack app installation flow (OAuth flow) +- `oauth_flow` _Optional[OAuthFlow]_ - Instantiated `slack_bolt.oauth.OAuthFlow`. This is always prioritized over oauth_settings. +- `verification_token` _Optional[str]_ - Deprecated verification mechanism. This can be used only for ssl_check requests. +- `listener_executor` _Optional[Executor]_ - Custom executor to run background tasks. If absent, the default `ThreadPoolExecutor` will + be used. +- `assistant_thread_context_store` _Optional[AssistantThreadContextStore]_ - Custom AssistantThreadContext store (Default: the built-in implementation, + which uses a parent message's metadata to store the latest context) + +#### name + +```python +@property +def name() -> str +``` + +The name of this app (default: the filename) + +#### oauth\_flow + +```python +@property +def oauth_flow() -> Optional[OAuthFlow] +``` + +Configured `OAuthFlow` object if exists. + +#### logger + +```python +@property +def logger() -> logging.Logger +``` + +The logger this app uses. + +#### client + +```python +@property +def client() -> WebClient +``` + +The singleton `slack_sdk.WebClient` instance in this app. + +#### installation\_store + +```python +@property +def installation_store() -> Optional[InstallationStore] +``` + +The `slack_sdk.oauth.InstallationStore` that can be used in the `authorize` middleware. + +#### listener\_runner + +```python +@property +def listener_runner() -> ThreadListenerRunner +``` + +The thread executor for asynchronously running listeners. + +#### process\_before\_response + +```python +@property +def process_before_response() -> bool +``` + +#### start + +```python +def start( + port: int = 3000, + path: str = '/slack/events', + http_server_logger_enabled: bool = True) -> None +``` + +Starts a web server for local development. + +```python +# With the default settings, `http://localhost:3000/slack/events` +# is available for handling incoming requests from Slack +app.start() +``` + +This method internally starts a Web server process built with the `http.server` module. +For production, consider using a production-ready WSGI server such as Gunicorn. + +**Arguments**: + +- `port` _int_ - The port to listen on (Default: 3000) +- `path` _str_ - The path to handle request from Slack (Default: `/slack/events`) +- `http_server_logger_enabled` _bool_ - The flag to enable http.server logging if True (Default: True) + +#### dispatch + +```python +def dispatch(req: BoltRequest) -> BoltResponse +``` + +Applies all middleware and dispatches an incoming request from Slack to the right code path. + +**Arguments**: + +- `req` _BoltRequest_ - An incoming request from Slack + +**Returns**: + +- `BoltResponse` - The response generated by this Bolt app + +#### use + +```python +def use(*args) -> Optional[Callable] +``` + +Registers a new global middleware to this app. This method can be used as either a decorator or a method. + +Refer to `App#middleware()` method's docstring for details. + +#### middleware + +```python +def middleware(*args) -> Optional[Callable] +``` + +Registers a new middleware to this app. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.middleware +def middleware_func(logger, body, next): + logger.info(f"request body: {body}") + next() + +# Pass a function to this method +app.middleware(middleware_func) +``` + +Refer to https://docs.slack.dev/tools/bolt-python/concepts/global-middleware for details. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `*args` - A function that works as a global middleware. + +#### assistant + +```python +def assistant(assistant: Assistant) -> Optional[Callable] +``` + +#### step + +```python +def step( + callback_id: Union[str, Pattern, WorkflowStep, WorkflowStepBuilder], + edit: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None, + save: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None, + execute: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +Registers a new step from app listener. + +Unlike others, this method doesn't behave as a decorator. +If you want to register a step from app by a decorator, use `WorkflowStepBuilder`'s methods. + +```python +# Create a new WorkflowStep instance +from slack_bolt.workflows.step import WorkflowStep +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +# Pass Step to set up listeners +app.step(ws) +``` + +Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +For further information about WorkflowStep specific function arguments +such as `configure`, `update`, `complete`, and `fail`, +refer to `slack_bolt.workflows.step.utilities` API documents. + +**Arguments**: + +- `callback_id` _Union[str, Pattern, WorkflowStep, WorkflowStepBuilder]_ - The Callback ID for this step from app +- `edit` _Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]]_ - The function for displaying a modal in the Workflow Builder +- `save` _Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]]_ - The function for handling configuration in the Workflow Builder +- `execute` _Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]]_ - The function for handling the step execution + +#### error + +```python +def error( + func: Callable[..., Optional[BoltResponse]]) -> Callable[..., Optional[BoltResponse]] +``` + +Updates the global error handler. This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.error +def custom_error_handler(error, body, logger): + logger.exception(f"Error: {error}") + logger.info(f"Request body: {body}") + +# Pass a function to this method +app.error(custom_error_handler) +``` + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `func` _Callable[..., Optional[BoltResponse]]_ - The function that is supposed to be executed + when getting an unhandled error in Bolt app. + +#### event + +```python +def event( + event: Union[str, Pattern, Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]]], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new event listener. This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.event("team_join") +def ask_for_introduction(event, say): + welcome_channel_id = "C12345" + user_id = event["user"] + text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel." + say(text=text, channel=welcome_channel_id) + +# Pass a function to this method +app.event("team_join")(ask_for_introduction) +``` + +Refer to https://docs.slack.dev/apis/events-api/ for details of Events API. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `event` _Union[str, Pattern, Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]]]_ - The conditions that match a request payload. + If you pass a dict for this, you can have type, subtype in the constraint. +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### message + +```python +def message( + keyword: Union[str, Pattern] = '', + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new message event listener. This method can be used as either a decorator or a method. +Check the `App#event` method's docstring for details. + +```python +# Use this method as a decorator +@app.message(":wave:") +def say_hello(message, say): + user = message['user'] + say(f"Hi there, <@{user}>!") + +# Pass a function to this method +app.message(":wave:")(say_hello) +``` + +Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `keyword` _Union[str, Pattern]_ - The keyword to match +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### function + +```python +def function( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None, + auto_acknowledge: bool = True, + ack_timeout: int = 3) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new Function listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.function("reverse") +def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail): + try: + ack() + string_to_reverse = inputs["stringToReverse"] + complete(outputs={"reverseString": string_to_reverse[::-1]}) + except Exception as e: + fail(f"Cannot reverse string (error: {e})") + raise e + +# Pass a function to this method +app.function("reverse")(reverse_string) +``` + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `callback_id` _Union[str, Pattern]_ - The callback id to identify the function +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### command + +```python +def command( + command: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new slash command listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.command("/echo") +def repeat_text(ack, say, command): + # Acknowledge command request + ack() + say(f"{command['text']}") + +# Pass a function to this method +app.command("/echo")(repeat_text) +``` + +Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `command` _Union[str, Pattern]_ - The conditions that match a request payload +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### shortcut + +```python +def shortcut( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new shortcut listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.shortcut("open_modal") +def open_modal(ack, body, client): + # Acknowledge the command request + ack() + # Call views_open with the built-in client + client.views_open( + # Pass a valid trigger_id within 3 seconds of receiving it + trigger_id=body["trigger_id"], + # View payload + view={ ... } + ) + +# Pass a function to this method +app.shortcut("open_modal")(open_modal) +``` + +Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `constraints` _Union[str, Pattern, Dict[str, Union[str, Pattern]]]_ - The conditions that match a request payload. +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### global\_shortcut + +```python +def global_shortcut( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new global shortcut listener. + +#### message\_shortcut + +```python +def message_shortcut( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new message shortcut listener. + +#### action + +```python +def action( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new action listener. This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.action("approve_button") +def update_message(ack): + ack() + +# Pass a function to this method +app.action("approve_button")(update_message) +``` + +* Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`. +* Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`. +* Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `constraints` _Union[str, Pattern, Dict[str, Union[str, Pattern]]]_ - The conditions that match a request payload +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### block\_action + +```python +def block_action( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `block_actions` action listener. +Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details. + +#### attachment\_action + +```python +def attachment_action( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `interactive_message` action listener. +Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details. + +#### dialog\_submission + +```python +def dialog_submission( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `dialog_submission` listener. +Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details. + +#### dialog\_cancellation + +```python +def dialog_cancellation( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `dialog_cancellation` listener. +Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details. + +#### view + +```python +def view( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `view_submission`/`view_closed` event listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.view("view_1") +def handle_submission(ack, body, client, view): + # Assume there's an input block with `block_c` as the block_id and `dreamy_input` + hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"] + user = body["user"]["id"] + # Validate the inputs + errors = {} + if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5: + errors["block_c"] = "The value must be longer than 5 characters" + if len(errors) > 0: + ack(response_action="errors", errors=errors) + return + # Acknowledge the view_submission event and close the modal + ack() + # Do whatever you want with the input data - here we're saving it to a DB + +# Pass a function to this method +app.view("view_1")(handle_submission) +``` + +Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `constraints` _Union[str, Pattern, Dict[str, Union[str, Pattern]]]_ - The conditions that match a request payload +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### view\_submission + +```python +def view_submission( + constraints: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `view_submission` listener. +Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for +details. + +#### view\_closed + +```python +def view_closed( + constraints: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `view_closed` listener. +Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details. + +#### options + +```python +def options( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new options listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.options("menu_selection") +def show_menu_options(ack): + options = [ + { + "text": {"type": "plain_text", "text": "Option 1"}, + "value": "1-1", + }, + { + "text": {"type": "plain_text", "text": "Option 2"}, + "value": "1-2", + }, + ] + ack(options=options) + +# Pass a function to this method +app.options("menu_selection")(show_menu_options) +``` + +Refer to the following documents for details: + +* https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select +* https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### block\_suggestion + +```python +def block_suggestion( + action_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `block_suggestion` listener. + +#### dialog\_suggestion + +```python +def dialog_suggestion( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `dialog_suggestion` listener. +Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details. + +#### default\_tokens\_revoked\_event\_listener + +```python +def default_tokens_revoked_event_listener() -> Callable[..., Optional[BoltResponse]] +``` + +#### default\_app\_uninstalled\_event\_listener + +```python +def default_app_uninstalled_event_listener() -> Callable[..., Optional[BoltResponse]] +``` + +#### enable\_token\_revocation\_listeners + +```python +def enable_token_revocation_listeners() -> None +``` + +## SlackAppDevelopmentServer Objects + +```python +class SlackAppDevelopmentServer() +``` + +#### \_\_init\_\_ + +```python +def __init__( + port: int, + path: str, + app: App, + oauth_flow: Optional[OAuthFlow] = None, + http_server_logger_enabled: bool = True) +``` + +Slack App Development Server + +This is a thin wrapper of http.server.HTTPServer and is good enough +for your local development or prototyping. + +However, as mentioned in Python official documents, using http.server module in production +is not recommended. Please consider using an adapter (refer to slack_bolt.adapter.*) +along with a production-grade server when running the app for end users. +https://docs.python.org/3/library/http.server.html#http.server.HTTPServer + +**Arguments**: + +- `port` _int_ - the port number +- `path` _str_ - the path to receive incoming requests +- `app` _App_ - the `App` instance to execute +- `oauth_flow` _Optional[OAuthFlow]_ - the `OAuthFlow` instance to use for OAuth flow +- `http_server_logger_enabled` _bool_ - The flag to turn on/off http.server's logging + +#### start + +```python +def start() -> None +``` + +Starts a new web server process. diff --git a/docs/english/reference/app/async_app.md b/docs/english/reference/app/async_app.md new file mode 100644 index 000000000..068410200 --- /dev/null +++ b/docs/english/reference/app/async_app.md @@ -0,0 +1,823 @@ +--- +sidebar_label: async_app +title: slack_bolt.app.async_app +--- + +## AsyncApp Objects + +```python +class AsyncApp() +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + logger: Optional[logging.Logger] = None, + name: Optional[str] = None, + process_before_response: bool = False, + raise_error_for_unhandled_request: bool = False, + signing_secret: Optional[str] = None, + token: Optional[str] = None, + client: Optional[AsyncWebClient] = None, + before_authorize: Optional[Union[AsyncMiddleware, Callable[..., Awaitable[Any]]]] = None, + authorize: Optional[Callable[..., Awaitable[AuthorizeResult]]] = None, + user_facing_authorize_error_message: Optional[str] = None, + installation_store: Optional[AsyncInstallationStore] = None, + installation_store_bot_only: Optional[bool] = None, + request_verification_enabled: bool = True, + ignoring_self_events_enabled: bool = True, + ignoring_self_assistant_message_events_enabled: bool = True, + ssl_check_enabled: bool = True, + url_verification_enabled: bool = True, + attaching_function_token_enabled: bool = True, + oauth_settings: Optional[AsyncOAuthSettings] = None, + oauth_flow: Optional[AsyncOAuthFlow] = None, + verification_token: Optional[str] = None, + assistant_thread_context_store: Optional[AsyncAssistantThreadContextStore] = None, + attaching_conversation_kwargs_enabled: bool = True) +``` + +Bolt App that provides functionalities to register middleware/listeners. + +```python +import os +from slack_bolt.async_app import AsyncApp + +# Initializes your app with your bot token and signing secret +app = AsyncApp( + token=os.environ.get("SLACK_BOT_TOKEN"), + signing_secret=os.environ.get("SLACK_SIGNING_SECRET") +) + +# Listens to incoming messages that contain "hello" +@app.message("hello") +async def message_hello(message, say): # async function + # say() sends a message to the channel where the event was triggered + await say(f"Hey there <@{message['user']}>!") + +# Start your app +if __name__ == "__main__": + app.start(port=int(os.environ.get("PORT", 3000))) +``` + +Refer to https://docs.slack.dev/tools/bolt-python/concepts/async for details. + +If you would like to build an OAuth app for enabling the app to run with multiple workspaces, +refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app. + +**Arguments**: + +- `logger` _Optional[logging.Logger]_ - The custom logger that can be used in this app. +- `name` _Optional[str]_ - The application name that will be used in logging. If absent, the source file name will be used. +- `process_before_response` _bool_ - True if this app runs on Function as a Service. (Default: False) +- `raise_error_for_unhandled_request` _bool_ - True if you want to raise exceptions for unhandled requests + and use @app.error listeners instead of + the built-in handler, which pints warning logs and returns 404 to Slack (Default: False) +- `signing_secret` _Optional[str]_ - The Signing Secret value used for verifying requests from Slack. +- `token` _Optional[str]_ - The bot/user access token required only for single-workspace app. +- `client` _Optional[AsyncWebClient]_ - The singleton `slack_sdk.web.async_client.AsyncWebClient` instance for this app. +- `before_authorize` _Optional[Union[AsyncMiddleware, Callable[..., Awaitable[Any]]]]_ - A global middleware that can be executed right before authorize function +- `authorize` _Optional[Callable[..., Awaitable[AuthorizeResult]]]_ - The function to authorize an incoming request from Slack + by checking if there is a team/user in the installation data. +- `user_facing_authorize_error_message` _Optional[str]_ - The user-facing error message to display + when the app is installed but the installation is not managed by this app's installation store +- `installation_store` _Optional[AsyncInstallationStore]_ - The module offering save/find operations of installation data +- `installation_store_bot_only` _Optional[bool]_ - Use `AsyncInstallationStore#async_find_bot()` if True (Default: False) +- `request_verification_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `AsyncRequestVerification` is a built-in middleware that verifies the signature in HTTP Mode requests. + Make sure if it's safe enough when you turn a built-in middleware off. + We strongly recommend using RequestVerification for better security. + If you have a proxy that verifies request signature in front of the Bolt app, + it's totally fine to disable RequestVerification to avoid duplication of work. + Don't turn it off just for easiness of development. +- `ignoring_self_events_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `AsyncIgnoringSelfEvents` is a built-in middleware that enables Bolt apps to easily skip the events + generated by this app's bot user (this is useful for avoiding code error causing an infinite loop). +- `ignoring_self_assistant_message_events_enabled` _bool_ - False if you would like to disable the built-in middleware. + `IgnoringSelfEvents` for this app's bot user message events within an assistant thread + This is useful for avoiding code error causing an infinite loop; Default: True +- `url_verification_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `AsyncUrlVerification` is a built-in middleware that handles url_verification requests + that verify the endpoint for Events API in HTTP Mode requests. +- `ssl_check_enabled` _bool_ - bool = False if you would like to disable the built-in middleware (Default: True). + `AsyncSslCheck` is a built-in middleware that handles ssl_check requests from Slack. +- `attaching_function_token_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `AsyncAttachingFunctionToken` is a built-in middleware that injects the just-in-time workflow-execution token + when your app receives `function_executed` or interactivity events scoped to a custom step. +- `oauth_settings` _Optional[AsyncOAuthSettings]_ - The settings related to Slack app installation flow (OAuth flow) +- `oauth_flow` _Optional[AsyncOAuthFlow]_ - Instantiated `slack_bolt.oauth.AsyncOAuthFlow`. This is always prioritized over oauth_settings. +- `verification_token` _Optional[str]_ - Deprecated verification mechanism. This can be used only for ssl_check requests. +- `assistant_thread_context_store` _Optional[AsyncAssistantThreadContextStore]_ - Custom AssistantThreadContext store (Default: the built-in implementation, + which uses a parent message's metadata to store the latest context) + +#### name + +```python +@property +def name() -> str +``` + +The name of this app (default: the filename) + +#### oauth\_flow + +```python +@property +def oauth_flow() -> Optional[AsyncOAuthFlow] +``` + +Configured `OAuthFlow` object if exists. + +#### client + +```python +@property +def client() -> AsyncWebClient +``` + +The singleton `slack_sdk.web.async_client.AsyncWebClient` instance in this app. + +#### logger + +```python +@property +def logger() -> logging.Logger +``` + +The logger this app uses. + +#### installation\_store + +```python +@property +def installation_store() -> Optional[AsyncInstallationStore] +``` + +The `slack_sdk.oauth.AsyncInstallationStore` that can be used in the `authorize` middleware. + +#### listener\_runner + +```python +@property +def listener_runner() -> AsyncioListenerRunner +``` + +The asyncio-based executor for asynchronously running listeners. + +#### process\_before\_response + +```python +@property +def process_before_response() -> bool +``` + +#### server + +```python +def server( + port: int = 3000, + path: str = '/slack/events', + host: Optional[str] = None) -> AsyncSlackAppServer +``` + +Configure a web server using AIOHTTP. +Refer to https://docs.aiohttp.org/ for more details about AIOHTTP. + +**Arguments**: + +- `port` _int_ - The port to listen on (Default: 3000) +- `path` _str_ - The path to handle request from Slack (Default: `/slack/events`) +- `host` _Optional[str]_ - The hostname to serve the web endpoints. (Default: 0.0.0.0) + +#### web\_app + +```python +def web_app(path: str = '/slack/events', port: int = 3000) -> web.Application +``` + +Returns a `web.Application` instance for aiohttp-devtools users. + +```python +from slack_bolt.async_app import AsyncApp +app = AsyncApp() + +@app.event("app_mention") +async def event_test(body, say, logger): + logger.info(body) + await say("What's up?") + +def app_factory(): + return app.web_app() + +# adev runserver --port 3000 --app-factory app_factory async_app.py +``` + +**Arguments**: + +- `path` _str_ - The path to receive incoming requests from Slack +- `port` _int_ - The port to listen on (Default: 3000) + +#### start + +```python +def start( + port: int = 3000, + path: str = '/slack/events', + host: Optional[str] = None) -> None +``` + +Start a web server using AIOHTTP. +Refer to https://docs.aiohttp.org/ for more details about AIOHTTP. + +**Arguments**: + +- `port` _int_ - The port to listen on (Default: 3000) +- `path` _str_ - The path to handle request from Slack (Default: `/slack/events`) +- `host` _Optional[str]_ - The hostname to serve the web endpoints. (Default: 0.0.0.0) + +#### async\_dispatch + +```python +async def async_dispatch(req: AsyncBoltRequest) -> BoltResponse +``` + +Applies all middleware and dispatches an incoming request from Slack to the right code path. + +**Arguments**: + +- `req` _AsyncBoltRequest_ - An incoming request from Slack. + +**Returns**: + +- `BoltResponse` - The response generated by this Bolt app. + +#### use + +```python +def use(*args) -> Optional[Callable] +``` + +Refer to `AsyncApp#middleware()` method's docstring for details. + +#### middleware + +```python +def middleware(*args) -> Optional[Callable] +``` + +Registers a new middleware to this app. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.middleware +async def middleware_func(logger, body, next): + logger.info(f"request body: {body}") + await next() + +# Pass a function to this method +app.middleware(middleware_func) +``` + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `*args` - A function that works as a global middleware. + +#### assistant + +```python +def assistant(assistant: AsyncAssistant) -> Optional[Callable] +``` + +#### step + +```python +def step( + callback_id: Union[str, Pattern, AsyncWorkflowStep, AsyncWorkflowStepBuilder], + edit: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None, + save: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None, + execute: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +Registers a new step from app listener. + +Unlike others, this method doesn't behave as a decorator. +If you want to register a step from app by a decorator, use `AsyncWorkflowStepBuilder`'s methods. + +```python +# Create a new WorkflowStep instance +from slack_bolt.workflows.async_step import AsyncWorkflowStep +ws = AsyncWorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +# Pass Step to set up listeners +app.step(ws) +``` + +Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. +For further information about AsyncWorkflowStep specific function arguments +such as `configure`, `update`, `complete`, and `fail`, +refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents. + +**Arguments**: + +- `callback_id` _Union[str, Pattern, AsyncWorkflowStep, AsyncWorkflowStepBuilder]_ - The Callback ID for this step from app +- `edit` _Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]]_ - The function for displaying a modal in the Workflow Builder +- `save` _Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]]_ - The function for handling configuration in the Workflow Builder +- `execute` _Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]]_ - The function for handling the step execution + +#### error + +```python +def error( + func: Callable[..., Awaitable[Optional[BoltResponse]]]) -> Callable[..., Awaitable[Optional[BoltResponse]]] +``` + +Updates the global error handler. This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.error +async def custom_error_handler(error, body, logger): + logger.exception(f"Error: {error}") + logger.info(f"Request body: {body}") + +# Pass a function to this method +app.error(custom_error_handler) +``` + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `func` _Callable[..., Awaitable[Optional[BoltResponse]]]_ - The function that is supposed to be executed + when getting an unhandled error in Bolt app. + +#### event + +```python +def event( + event: Union[str, Pattern, Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]]], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new event listener. This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.event("team_join") +async def ask_for_introduction(event, say): + welcome_channel_id = "C12345" + user_id = event["user"] + text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel." + await say(text=text, channel=welcome_channel_id) + +# Pass a function to this method +app.event("team_join")(ask_for_introduction) +``` + +Refer to https://docs.slack.dev/apis/events-api/ for details of Events API. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `event` _Union[str, Pattern, Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]]]_ - The conditions that match a request payload. + If you pass a dict for this, you can have type, subtype in the constraint. +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### message + +```python +def message( + keyword: Union[str, Pattern] = '', + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new message event listener. This method can be used as either a decorator or a method. +Check the `App#event` method's docstring for details. + +```python +# Use this method as a decorator +@app.message(":wave:") +async def say_hello(message, say): + user = message['user'] + await say(f"Hi there, <@{user}>!") + +# Pass a function to this method +app.message(":wave:")(say_hello) +``` + +Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `keyword` _Union[str, Pattern]_ - The keyword to match +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### function + +```python +def function( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None, + auto_acknowledge: bool = True, + ack_timeout: int = 3) -> Callable[..., Optional[Callable[..., Awaitable[BoltResponse]]]] +``` + +Registers a new Function listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.function("reverse") +async def reverse_string(ack: AsyncAck, inputs: dict, complete: AsyncComplete, fail: AsyncFail): + try: + await ack() + string_to_reverse = inputs["stringToReverse"] + await complete({"reverseString": string_to_reverse[::-1]}) + except Exception as e: + await fail(f"Cannot reverse string (error: {e})") + raise e + +# Pass a function to this method +app.function("reverse")(reverse_string) +``` + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `callback_id` _Union[str, Pattern]_ - The callback id to identify the function +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### command + +```python +def command( + command: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new slash command listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.command("/echo") +async def repeat_text(ack, say, command): + # Acknowledge command request + await ack() + await say(f"{command['text']}") + +# Pass a function to this method +app.command("/echo")(repeat_text) +``` + +Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `command` _Union[str, Pattern]_ - The conditions that match a request payload +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### shortcut + +```python +def shortcut( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new shortcut listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.shortcut("open_modal") +async def open_modal(ack, body, client): + # Acknowledge the command request + await ack() + # Call views_open with the built-in client + await client.views_open( + # Pass a valid trigger_id within 3 seconds of receiving it + trigger_id=body["trigger_id"], + # View payload + view={ ... } + ) + +# Pass a function to this method +app.shortcut("open_modal")(open_modal) +``` + +Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `constraints` _Union[str, Pattern, Dict[str, Union[str, Pattern]]]_ - The conditions that match a request payload. +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### global\_shortcut + +```python +def global_shortcut( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new global shortcut listener. + +#### message\_shortcut + +```python +def message_shortcut( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new message shortcut listener. + +#### action + +```python +def action( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new action listener. This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.action("approve_button") +async def update_message(ack): + await ack() + +# Pass a function to this method +app.action("approve_button")(update_message) +``` + +* Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`. +* Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`. +* Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `constraints` _Union[str, Pattern, Dict[str, Union[str, Pattern]]]_ - The conditions that match a request payload +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### block\_action + +```python +def block_action( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `block_actions` action listener. +Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details. + +#### attachment\_action + +```python +def attachment_action( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `interactive_message` action listener. +Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details. + +#### dialog\_submission + +```python +def dialog_submission( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `dialog_submission` listener. +Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details. + +#### dialog\_cancellation + +```python +def dialog_cancellation( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `dialog_submission` listener. +Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details. + +#### view + +```python +def view( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `view_submission`/`view_closed` event listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.view("view_1") +async def handle_submission(ack, body, client, view): + # Assume there's an input block with `block_c` as the block_id and `dreamy_input` + hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"] + user = body["user"]["id"] + # Validate the inputs + errors = {} + if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5: + errors["block_c"] = "The value must be longer than 5 characters" + if len(errors) > 0: + await ack(response_action="errors", errors=errors) + return + # Acknowledge the view_submission event and close the modal + await ack() + # Do whatever you want with the input data - here we're saving it to a DB + +# Pass a function to this method +app.view("view_1")(handle_submission) +``` + +Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `constraints` _Union[str, Pattern, Dict[str, Union[str, Pattern]]]_ - The conditions that match a request payload +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### view\_submission + +```python +def view_submission( + constraints: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `view_submission` listener. +Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for +details. + +#### view\_closed + +```python +def view_closed( + constraints: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `view_closed` listener. +Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details. + +#### options + +```python +def options( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new options listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.options("menu_selection") +async def show_menu_options(ack): + options = [ + { + "text": {"type": "plain_text", "text": "Option 1"}, + "value": "1-1", + }, + { + "text": {"type": "plain_text", "text": "Option 2"}, + "value": "1-2", + }, + ] + await ack(options=options) + +# Pass a function to this method +app.options("menu_selection")(show_menu_options) +``` + +Refer to the following documents for details: + +* https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select +* https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### block\_suggestion + +```python +def block_suggestion( + action_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `block_suggestion` listener. + +#### dialog\_suggestion + +```python +def dialog_suggestion( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `dialog_suggestion` listener. +Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details. + +#### default\_tokens\_revoked\_event\_listener + +```python +def default_tokens_revoked_event_listener( +) -> Callable[..., Awaitable[Optional[BoltResponse]]] +``` + +#### default\_app\_uninstalled\_event\_listener + +```python +def default_app_uninstalled_event_listener( +) -> Callable[..., Awaitable[Optional[BoltResponse]]] +``` + +#### enable\_token\_revocation\_listeners + +```python +def enable_token_revocation_listeners() -> None +``` diff --git a/docs/english/reference/app/async_server.md b/docs/english/reference/app/async_server.md new file mode 100644 index 000000000..f92808a1d --- /dev/null +++ b/docs/english/reference/app/async_server.md @@ -0,0 +1,56 @@ +--- +sidebar_label: async_server +title: slack_bolt.app.async_server +--- + +## AsyncSlackAppServer Objects + +```python +class AsyncSlackAppServer() +``` + +#### port: `int` + +#### path: `str` + +#### host: `str` + +#### bolt\_app: `AsyncApp` + +#### web\_app: `web.Application` + +#### \_\_init\_\_ + +```python +def __init__(port: int, path: str, app: AsyncApp, host: Optional[str] = None) +``` + +Standalone AIOHTTP Web Server. +Refer to https://docs.aiohttp.org/en/stable/web.html for details of AIOHTTP. + +**Arguments**: + +- `port` _int_ - The port to listen on +- `path` _str_ - The path to receive incoming requests from Slack +- `app` _AsyncApp_ - The `AsyncApp` instance that is used for processing requests +- `host` _Optional[str]_ - The hostname to serve the web endpoints. (Default: 0.0.0.0) + +#### handle\_get\_requests + +```python +async def handle_get_requests(request: web.Request) -> web.Response +``` + +#### handle\_post\_requests + +```python +async def handle_post_requests(request: web.Request) -> web.Response +``` + +#### start + +```python +def start(host: Optional[str] = None) -> None +``` + +Starts a new web server process. diff --git a/docs/english/reference/app/index.md b/docs/english/reference/app/index.md new file mode 100644 index 000000000..09d175eb0 --- /dev/null +++ b/docs/english/reference/app/index.md @@ -0,0 +1,805 @@ +--- +sidebar_label: app +title: slack_bolt.app +--- + +Application interface in Bolt. + +For most use cases, we recommend using `slack_bolt.app.app`. +If you already have knowledge about asyncio and prefer the programming model, +you can use `slack_bolt.app.async_app` for building async apps. + +## Submodules + +- [slack_bolt.app.app](/tools/bolt-python/reference/app/app) +- [slack_bolt.app.async_app](/tools/bolt-python/reference/app/async_app) +- [slack_bolt.app.async_server](/tools/bolt-python/reference/app/async_server) + +## App Objects + +```python +class App() +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + logger: Optional[logging.Logger] = None, + name: Optional[str] = None, + process_before_response: bool = False, + raise_error_for_unhandled_request: bool = False, + signing_secret: Optional[str] = None, + token: Optional[str] = None, + token_verification_enabled: bool = True, + client: Optional[WebClient] = None, + before_authorize: Optional[Union[Middleware, Callable[..., Any]]] = None, + authorize: Optional[Callable[..., AuthorizeResult]] = None, + user_facing_authorize_error_message: Optional[str] = None, + installation_store: Optional[InstallationStore] = None, + installation_store_bot_only: Optional[bool] = None, + request_verification_enabled: bool = True, + ignoring_self_events_enabled: bool = True, + ignoring_self_assistant_message_events_enabled: bool = True, + ssl_check_enabled: bool = True, + url_verification_enabled: bool = True, + attaching_function_token_enabled: bool = True, + oauth_settings: Optional[OAuthSettings] = None, + oauth_flow: Optional[OAuthFlow] = None, + verification_token: Optional[str] = None, + listener_executor: Optional[Executor] = None, + assistant_thread_context_store: Optional[AssistantThreadContextStore] = None, + attaching_conversation_kwargs_enabled: bool = True) +``` + +Bolt App that provides functionalities to register middleware/listeners. + +```python +import os +from slack_bolt import App + +# Initializes your app with your bot token and signing secret +app = App( + token=os.environ.get("SLACK_BOT_TOKEN"), + signing_secret=os.environ.get("SLACK_SIGNING_SECRET") +) + +# Listens to incoming messages that contain "hello" +@app.message("hello") +def message_hello(message, say): + # say() sends a message to the channel where the event was triggered + say(f"Hey there <@{message['user']}>!") + +# Start your app +if __name__ == "__main__": + app.start(port=int(os.environ.get("PORT", 3000))) +``` + +Refer to https://docs.slack.dev/tools/bolt-python/creating-an-app for details. + +If you would like to build an OAuth app for enabling the app to run with multiple workspaces, +refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app. + +**Arguments**: + +- `logger` _Optional[logging.Logger]_ - The custom logger that can be used in this app. +- `name` _Optional[str]_ - The application name that will be used in logging. If absent, the source file name will be used. +- `process_before_response` _bool_ - True if this app runs on Function as a Service. (Default: False) +- `raise_error_for_unhandled_request` _bool_ - True if you want to raise exceptions for unhandled requests + and use @app.error listeners instead of + the built-in handler, which pints warning logs and returns 404 to Slack (Default: False) +- `signing_secret` _Optional[str]_ - The Signing Secret value used for verifying requests from Slack. +- `token` _Optional[str]_ - The bot/user access token required only for single-workspace app. +- `token_verification_enabled` _bool_ - Verifies the validity of the given token if True. +- `client` _Optional[WebClient]_ - The singleton `slack_sdk.WebClient` instance for this app. +- `before_authorize` _Optional[Union[Middleware, Callable[..., Any]]]_ - A global middleware that can be executed right before authorize function +- `authorize` _Optional[Callable[..., AuthorizeResult]]_ - The function to authorize an incoming request from Slack + by checking if there is a team/user in the installation data. +- `user_facing_authorize_error_message` _Optional[str]_ - The user-facing error message to display + when the app is installed but the installation is not managed by this app's installation store +- `installation_store` _Optional[InstallationStore]_ - The module offering save/find operations of installation data +- `installation_store_bot_only` _Optional[bool]_ - Use `InstallationStore#find_bot()` if True (Default: False) +- `request_verification_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `RequestVerification` is a built-in middleware that verifies the signature in HTTP Mode requests. + Make sure if it's safe enough when you turn a built-in middleware off. + We strongly recommend using RequestVerification for better security. + If you have a proxy that verifies request signature in front of the Bolt app, + it's totally fine to disable RequestVerification to avoid duplication of work. + Don't turn it off just for easiness of development. +- `ignoring_self_events_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `IgnoringSelfEvents` is a built-in middleware that enables Bolt apps to easily skip the events + generated by this app's bot user (this is useful for avoiding code error causing an infinite loop). +- `ignoring_self_assistant_message_events_enabled` _bool_ - False if you would like to disable the built-in middleware. + `IgnoringSelfEvents` for this app's bot user message events within an assistant thread + This is useful for avoiding code error causing an infinite loop; Default: True +- `url_verification_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `UrlVerification` is a built-in middleware that handles url_verification requests + that verify the endpoint for Events API in HTTP Mode requests. +- `attaching_function_token_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `AttachingFunctionToken` is a built-in middleware that injects the just-in-time workflow-execution tokens + when your app receives `function_executed` or interactivity events scoped to a custom step. +- `ssl_check_enabled` _bool_ - bool = False if you would like to disable the built-in middleware (Default: True). + `SslCheck` is a built-in middleware that handles ssl_check requests from Slack. +- `oauth_settings` _Optional[OAuthSettings]_ - The settings related to Slack app installation flow (OAuth flow) +- `oauth_flow` _Optional[OAuthFlow]_ - Instantiated `slack_bolt.oauth.OAuthFlow`. This is always prioritized over oauth_settings. +- `verification_token` _Optional[str]_ - Deprecated verification mechanism. This can be used only for ssl_check requests. +- `listener_executor` _Optional[Executor]_ - Custom executor to run background tasks. If absent, the default `ThreadPoolExecutor` will + be used. +- `assistant_thread_context_store` _Optional[AssistantThreadContextStore]_ - Custom AssistantThreadContext store (Default: the built-in implementation, + which uses a parent message's metadata to store the latest context) + +#### name + +```python +@property +def name() -> str +``` + +The name of this app (default: the filename) + +#### oauth\_flow + +```python +@property +def oauth_flow() -> Optional[OAuthFlow] +``` + +Configured `OAuthFlow` object if exists. + +#### logger + +```python +@property +def logger() -> logging.Logger +``` + +The logger this app uses. + +#### client + +```python +@property +def client() -> WebClient +``` + +The singleton `slack_sdk.WebClient` instance in this app. + +#### installation\_store + +```python +@property +def installation_store() -> Optional[InstallationStore] +``` + +The `slack_sdk.oauth.InstallationStore` that can be used in the `authorize` middleware. + +#### listener\_runner + +```python +@property +def listener_runner() -> ThreadListenerRunner +``` + +The thread executor for asynchronously running listeners. + +#### process\_before\_response + +```python +@property +def process_before_response() -> bool +``` + +#### start + +```python +def start( + port: int = 3000, + path: str = '/slack/events', + http_server_logger_enabled: bool = True) -> None +``` + +Starts a web server for local development. + +```python +# With the default settings, `http://localhost:3000/slack/events` +# is available for handling incoming requests from Slack +app.start() +``` + +This method internally starts a Web server process built with the `http.server` module. +For production, consider using a production-ready WSGI server such as Gunicorn. + +**Arguments**: + +- `port` _int_ - The port to listen on (Default: 3000) +- `path` _str_ - The path to handle request from Slack (Default: `/slack/events`) +- `http_server_logger_enabled` _bool_ - The flag to enable http.server logging if True (Default: True) + +#### dispatch + +```python +def dispatch(req: BoltRequest) -> BoltResponse +``` + +Applies all middleware and dispatches an incoming request from Slack to the right code path. + +**Arguments**: + +- `req` _BoltRequest_ - An incoming request from Slack + +**Returns**: + +- `BoltResponse` - The response generated by this Bolt app + +#### use + +```python +def use(*args) -> Optional[Callable] +``` + +Registers a new global middleware to this app. This method can be used as either a decorator or a method. + +Refer to `App#middleware()` method's docstring for details. + +#### middleware + +```python +def middleware(*args) -> Optional[Callable] +``` + +Registers a new middleware to this app. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.middleware +def middleware_func(logger, body, next): + logger.info(f"request body: {body}") + next() + +# Pass a function to this method +app.middleware(middleware_func) +``` + +Refer to https://docs.slack.dev/tools/bolt-python/concepts/global-middleware for details. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `*args` - A function that works as a global middleware. + +#### assistant + +```python +def assistant(assistant: Assistant) -> Optional[Callable] +``` + +#### step + +```python +def step( + callback_id: Union[str, Pattern, WorkflowStep, WorkflowStepBuilder], + edit: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None, + save: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None, + execute: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +Registers a new step from app listener. + +Unlike others, this method doesn't behave as a decorator. +If you want to register a step from app by a decorator, use `WorkflowStepBuilder`'s methods. + +```python +# Create a new WorkflowStep instance +from slack_bolt.workflows.step import WorkflowStep +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +# Pass Step to set up listeners +app.step(ws) +``` + +Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +For further information about WorkflowStep specific function arguments +such as `configure`, `update`, `complete`, and `fail`, +refer to `slack_bolt.workflows.step.utilities` API documents. + +**Arguments**: + +- `callback_id` _Union[str, Pattern, WorkflowStep, WorkflowStepBuilder]_ - The Callback ID for this step from app +- `edit` _Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]]_ - The function for displaying a modal in the Workflow Builder +- `save` _Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]]_ - The function for handling configuration in the Workflow Builder +- `execute` _Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]]_ - The function for handling the step execution + +#### error + +```python +def error( + func: Callable[..., Optional[BoltResponse]]) -> Callable[..., Optional[BoltResponse]] +``` + +Updates the global error handler. This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.error +def custom_error_handler(error, body, logger): + logger.exception(f"Error: {error}") + logger.info(f"Request body: {body}") + +# Pass a function to this method +app.error(custom_error_handler) +``` + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `func` _Callable[..., Optional[BoltResponse]]_ - The function that is supposed to be executed + when getting an unhandled error in Bolt app. + +#### event + +```python +def event( + event: Union[str, Pattern, Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]]], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new event listener. This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.event("team_join") +def ask_for_introduction(event, say): + welcome_channel_id = "C12345" + user_id = event["user"] + text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel." + say(text=text, channel=welcome_channel_id) + +# Pass a function to this method +app.event("team_join")(ask_for_introduction) +``` + +Refer to https://docs.slack.dev/apis/events-api/ for details of Events API. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `event` _Union[str, Pattern, Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]]]_ - The conditions that match a request payload. + If you pass a dict for this, you can have type, subtype in the constraint. +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### message + +```python +def message( + keyword: Union[str, Pattern] = '', + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new message event listener. This method can be used as either a decorator or a method. +Check the `App#event` method's docstring for details. + +```python +# Use this method as a decorator +@app.message(":wave:") +def say_hello(message, say): + user = message['user'] + say(f"Hi there, <@{user}>!") + +# Pass a function to this method +app.message(":wave:")(say_hello) +``` + +Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `keyword` _Union[str, Pattern]_ - The keyword to match +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### function + +```python +def function( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None, + auto_acknowledge: bool = True, + ack_timeout: int = 3) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new Function listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.function("reverse") +def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail): + try: + ack() + string_to_reverse = inputs["stringToReverse"] + complete(outputs={"reverseString": string_to_reverse[::-1]}) + except Exception as e: + fail(f"Cannot reverse string (error: {e})") + raise e + +# Pass a function to this method +app.function("reverse")(reverse_string) +``` + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `callback_id` _Union[str, Pattern]_ - The callback id to identify the function +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### command + +```python +def command( + command: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new slash command listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.command("/echo") +def repeat_text(ack, say, command): + # Acknowledge command request + ack() + say(f"{command['text']}") + +# Pass a function to this method +app.command("/echo")(repeat_text) +``` + +Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `command` _Union[str, Pattern]_ - The conditions that match a request payload +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### shortcut + +```python +def shortcut( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new shortcut listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.shortcut("open_modal") +def open_modal(ack, body, client): + # Acknowledge the command request + ack() + # Call views_open with the built-in client + client.views_open( + # Pass a valid trigger_id within 3 seconds of receiving it + trigger_id=body["trigger_id"], + # View payload + view={ ... } + ) + +# Pass a function to this method +app.shortcut("open_modal")(open_modal) +``` + +Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `constraints` _Union[str, Pattern, Dict[str, Union[str, Pattern]]]_ - The conditions that match a request payload. +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### global\_shortcut + +```python +def global_shortcut( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new global shortcut listener. + +#### message\_shortcut + +```python +def message_shortcut( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new message shortcut listener. + +#### action + +```python +def action( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new action listener. This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.action("approve_button") +def update_message(ack): + ack() + +# Pass a function to this method +app.action("approve_button")(update_message) +``` + +* Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`. +* Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`. +* Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `constraints` _Union[str, Pattern, Dict[str, Union[str, Pattern]]]_ - The conditions that match a request payload +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### block\_action + +```python +def block_action( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `block_actions` action listener. +Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details. + +#### attachment\_action + +```python +def attachment_action( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `interactive_message` action listener. +Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details. + +#### dialog\_submission + +```python +def dialog_submission( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `dialog_submission` listener. +Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details. + +#### dialog\_cancellation + +```python +def dialog_cancellation( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `dialog_cancellation` listener. +Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details. + +#### view + +```python +def view( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `view_submission`/`view_closed` event listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.view("view_1") +def handle_submission(ack, body, client, view): + # Assume there's an input block with `block_c` as the block_id and `dreamy_input` + hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"] + user = body["user"]["id"] + # Validate the inputs + errors = {} + if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5: + errors["block_c"] = "The value must be longer than 5 characters" + if len(errors) > 0: + ack(response_action="errors", errors=errors) + return + # Acknowledge the view_submission event and close the modal + ack() + # Do whatever you want with the input data - here we're saving it to a DB + +# Pass a function to this method +app.view("view_1")(handle_submission) +``` + +Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `constraints` _Union[str, Pattern, Dict[str, Union[str, Pattern]]]_ - The conditions that match a request payload +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### view\_submission + +```python +def view_submission( + constraints: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `view_submission` listener. +Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for +details. + +#### view\_closed + +```python +def view_closed( + constraints: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `view_closed` listener. +Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details. + +#### options + +```python +def options( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new options listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.options("menu_selection") +def show_menu_options(ack): + options = [ + { + "text": {"type": "plain_text", "text": "Option 1"}, + "value": "1-1", + }, + { + "text": {"type": "plain_text", "text": "Option 2"}, + "value": "1-2", + }, + ] + ack(options=options) + +# Pass a function to this method +app.options("menu_selection")(show_menu_options) +``` + +Refer to the following documents for details: + +* https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select +* https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. + +**Arguments**: + +- `matchers` _Optional[Sequence[Callable[..., bool]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, Middleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### block\_suggestion + +```python +def block_suggestion( + action_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `block_suggestion` listener. + +#### dialog\_suggestion + +```python +def dialog_suggestion( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., bool]]] = None, + middleware: Optional[Sequence[Union[Callable, Middleware]]] = None) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]] +``` + +Registers a new `dialog_suggestion` listener. +Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details. + +#### default\_tokens\_revoked\_event\_listener + +```python +def default_tokens_revoked_event_listener() -> Callable[..., Optional[BoltResponse]] +``` + +#### default\_app\_uninstalled\_event\_listener + +```python +def default_app_uninstalled_event_listener() -> Callable[..., Optional[BoltResponse]] +``` + +#### enable\_token\_revocation\_listeners + +```python +def enable_token_revocation_listeners() -> None +``` diff --git a/docs/english/reference/async_app.md b/docs/english/reference/async_app.md new file mode 100644 index 000000000..e80201abd --- /dev/null +++ b/docs/english/reference/async_app.md @@ -0,0 +1,1519 @@ +--- +sidebar_label: async_app +title: slack_bolt.async_app +--- + +Module for creating asyncio based apps + +### Creating an async app + +If you'd prefer to build your app with [asyncio](https://docs.python.org/3/library/asyncio.html), you can import the [AIOHTTP](https://docs.aiohttp.org/en/stable/) library and call the `AsyncApp` constructor. Within async apps, you can use the async/await pattern. + +```bash +# Python 3.7+ required +python -m venv .venv +source .venv/bin/activate + +pip install -U pip +# aiohttp is required +pip install slack_bolt aiohttp +``` + +In async apps, all middleware/listeners must be async functions. When calling utility methods (like `ack` and `say`) within these functions, it's required to use the `await` keyword. + +```python +# Import the async app instead of the regular one +from slack_bolt.async_app import AsyncApp + +app = AsyncApp() + +@app.event("app_mention") +async def event_test(body, say, logger): + logger.info(body) + await say("What's up?") + +@app.command("/hello-bolt-python") +async def command(ack, body, respond): + await ack() + await respond(f"Hi <@{body['user_id']}>!") + +if __name__ == "__main__": + app.start(3000) +``` + +If you want to use another async Web framework (e.g., Sanic, FastAPI, Starlette), take a look at the built-in adapters and their examples. + +* [The Bolt app examples](https://github.com/slackapi/bolt-python/tree/main/examples) +* [The built-in adapters](https://github.com/slackapi/bolt-python/tree/main/slack_bolt/adapter) +Apps can be run the same way as the synchronous example above. If you'd prefer another async Web framework (e.g., Sanic, FastAPI, Starlette), take a look at [the built-in adapters](https://github.com/slackapi/bolt-python/tree/main/slack_bolt/adapter) and their corresponding [examples](https://github.com/slackapi/bolt-python/tree/main/examples). + +Refer to `slack_bolt.app.async_app` for more details. + +## AsyncApp Objects + +```python +class AsyncApp() +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + logger: Optional[logging.Logger] = None, + name: Optional[str] = None, + process_before_response: bool = False, + raise_error_for_unhandled_request: bool = False, + signing_secret: Optional[str] = None, + token: Optional[str] = None, + client: Optional[AsyncWebClient] = None, + before_authorize: Optional[Union[AsyncMiddleware, Callable[..., Awaitable[Any]]]] = None, + authorize: Optional[Callable[..., Awaitable[AuthorizeResult]]] = None, + user_facing_authorize_error_message: Optional[str] = None, + installation_store: Optional[AsyncInstallationStore] = None, + installation_store_bot_only: Optional[bool] = None, + request_verification_enabled: bool = True, + ignoring_self_events_enabled: bool = True, + ignoring_self_assistant_message_events_enabled: bool = True, + ssl_check_enabled: bool = True, + url_verification_enabled: bool = True, + attaching_function_token_enabled: bool = True, + oauth_settings: Optional[AsyncOAuthSettings] = None, + oauth_flow: Optional[AsyncOAuthFlow] = None, + verification_token: Optional[str] = None, + assistant_thread_context_store: Optional[AsyncAssistantThreadContextStore] = None, + attaching_conversation_kwargs_enabled: bool = True) +``` + +Bolt App that provides functionalities to register middleware/listeners. + +```python +import os +from slack_bolt.async_app import AsyncApp + +# Initializes your app with your bot token and signing secret +app = AsyncApp( + token=os.environ.get("SLACK_BOT_TOKEN"), + signing_secret=os.environ.get("SLACK_SIGNING_SECRET") +) + +# Listens to incoming messages that contain "hello" +@app.message("hello") +async def message_hello(message, say): # async function + # say() sends a message to the channel where the event was triggered + await say(f"Hey there <@{message['user']}>!") + +# Start your app +if __name__ == "__main__": + app.start(port=int(os.environ.get("PORT", 3000))) +``` + +Refer to https://docs.slack.dev/tools/bolt-python/concepts/async for details. + +If you would like to build an OAuth app for enabling the app to run with multiple workspaces, +refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app. + +**Arguments**: + +- `logger` _Optional[logging.Logger]_ - The custom logger that can be used in this app. +- `name` _Optional[str]_ - The application name that will be used in logging. If absent, the source file name will be used. +- `process_before_response` _bool_ - True if this app runs on Function as a Service. (Default: False) +- `raise_error_for_unhandled_request` _bool_ - True if you want to raise exceptions for unhandled requests + and use @app.error listeners instead of + the built-in handler, which pints warning logs and returns 404 to Slack (Default: False) +- `signing_secret` _Optional[str]_ - The Signing Secret value used for verifying requests from Slack. +- `token` _Optional[str]_ - The bot/user access token required only for single-workspace app. +- `client` _Optional[AsyncWebClient]_ - The singleton `slack_sdk.web.async_client.AsyncWebClient` instance for this app. +- `before_authorize` _Optional[Union[AsyncMiddleware, Callable[..., Awaitable[Any]]]]_ - A global middleware that can be executed right before authorize function +- `authorize` _Optional[Callable[..., Awaitable[AuthorizeResult]]]_ - The function to authorize an incoming request from Slack + by checking if there is a team/user in the installation data. +- `user_facing_authorize_error_message` _Optional[str]_ - The user-facing error message to display + when the app is installed but the installation is not managed by this app's installation store +- `installation_store` _Optional[AsyncInstallationStore]_ - The module offering save/find operations of installation data +- `installation_store_bot_only` _Optional[bool]_ - Use `AsyncInstallationStore#async_find_bot()` if True (Default: False) +- `request_verification_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `AsyncRequestVerification` is a built-in middleware that verifies the signature in HTTP Mode requests. + Make sure if it's safe enough when you turn a built-in middleware off. + We strongly recommend using RequestVerification for better security. + If you have a proxy that verifies request signature in front of the Bolt app, + it's totally fine to disable RequestVerification to avoid duplication of work. + Don't turn it off just for easiness of development. +- `ignoring_self_events_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `AsyncIgnoringSelfEvents` is a built-in middleware that enables Bolt apps to easily skip the events + generated by this app's bot user (this is useful for avoiding code error causing an infinite loop). +- `ignoring_self_assistant_message_events_enabled` _bool_ - False if you would like to disable the built-in middleware. + `IgnoringSelfEvents` for this app's bot user message events within an assistant thread + This is useful for avoiding code error causing an infinite loop; Default: True +- `url_verification_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `AsyncUrlVerification` is a built-in middleware that handles url_verification requests + that verify the endpoint for Events API in HTTP Mode requests. +- `ssl_check_enabled` _bool_ - bool = False if you would like to disable the built-in middleware (Default: True). + `AsyncSslCheck` is a built-in middleware that handles ssl_check requests from Slack. +- `attaching_function_token_enabled` _bool_ - False if you would like to disable the built-in middleware (Default: True). + `AsyncAttachingFunctionToken` is a built-in middleware that injects the just-in-time workflow-execution token + when your app receives `function_executed` or interactivity events scoped to a custom step. +- `oauth_settings` _Optional[AsyncOAuthSettings]_ - The settings related to Slack app installation flow (OAuth flow) +- `oauth_flow` _Optional[AsyncOAuthFlow]_ - Instantiated `slack_bolt.oauth.AsyncOAuthFlow`. This is always prioritized over oauth_settings. +- `verification_token` _Optional[str]_ - Deprecated verification mechanism. This can be used only for ssl_check requests. +- `assistant_thread_context_store` _Optional[AsyncAssistantThreadContextStore]_ - Custom AssistantThreadContext store (Default: the built-in implementation, + which uses a parent message's metadata to store the latest context) + +#### name + +```python +@property +def name() -> str +``` + +The name of this app (default: the filename) + +#### oauth\_flow + +```python +@property +def oauth_flow() -> Optional[AsyncOAuthFlow] +``` + +Configured `OAuthFlow` object if exists. + +#### client + +```python +@property +def client() -> AsyncWebClient +``` + +The singleton `slack_sdk.web.async_client.AsyncWebClient` instance in this app. + +#### logger + +```python +@property +def logger() -> logging.Logger +``` + +The logger this app uses. + +#### installation\_store + +```python +@property +def installation_store() -> Optional[AsyncInstallationStore] +``` + +The `slack_sdk.oauth.AsyncInstallationStore` that can be used in the `authorize` middleware. + +#### listener\_runner + +```python +@property +def listener_runner() -> AsyncioListenerRunner +``` + +The asyncio-based executor for asynchronously running listeners. + +#### process\_before\_response + +```python +@property +def process_before_response() -> bool +``` + +#### server + +```python +def server( + port: int = 3000, + path: str = '/slack/events', + host: Optional[str] = None) -> AsyncSlackAppServer +``` + +Configure a web server using AIOHTTP. +Refer to https://docs.aiohttp.org/ for more details about AIOHTTP. + +**Arguments**: + +- `port` _int_ - The port to listen on (Default: 3000) +- `path` _str_ - The path to handle request from Slack (Default: `/slack/events`) +- `host` _Optional[str]_ - The hostname to serve the web endpoints. (Default: 0.0.0.0) + +#### web\_app + +```python +def web_app(path: str = '/slack/events', port: int = 3000) -> web.Application +``` + +Returns a `web.Application` instance for aiohttp-devtools users. + +```python +from slack_bolt.async_app import AsyncApp +app = AsyncApp() + +@app.event("app_mention") +async def event_test(body, say, logger): + logger.info(body) + await say("What's up?") + +def app_factory(): + return app.web_app() + +# adev runserver --port 3000 --app-factory app_factory async_app.py +``` + +**Arguments**: + +- `path` _str_ - The path to receive incoming requests from Slack +- `port` _int_ - The port to listen on (Default: 3000) + +#### start + +```python +def start( + port: int = 3000, + path: str = '/slack/events', + host: Optional[str] = None) -> None +``` + +Start a web server using AIOHTTP. +Refer to https://docs.aiohttp.org/ for more details about AIOHTTP. + +**Arguments**: + +- `port` _int_ - The port to listen on (Default: 3000) +- `path` _str_ - The path to handle request from Slack (Default: `/slack/events`) +- `host` _Optional[str]_ - The hostname to serve the web endpoints. (Default: 0.0.0.0) + +#### async\_dispatch + +```python +async def async_dispatch(req: AsyncBoltRequest) -> BoltResponse +``` + +Applies all middleware and dispatches an incoming request from Slack to the right code path. + +**Arguments**: + +- `req` _AsyncBoltRequest_ - An incoming request from Slack. + +**Returns**: + +- `BoltResponse` - The response generated by this Bolt app. + +#### use + +```python +def use(*args) -> Optional[Callable] +``` + +Refer to `AsyncApp#middleware()` method's docstring for details. + +#### middleware + +```python +def middleware(*args) -> Optional[Callable] +``` + +Registers a new middleware to this app. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.middleware +async def middleware_func(logger, body, next): + logger.info(f"request body: {body}") + await next() + +# Pass a function to this method +app.middleware(middleware_func) +``` + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `*args` - A function that works as a global middleware. + +#### assistant + +```python +def assistant(assistant: AsyncAssistant) -> Optional[Callable] +``` + +#### step + +```python +def step( + callback_id: Union[str, Pattern, AsyncWorkflowStep, AsyncWorkflowStepBuilder], + edit: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None, + save: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None, + execute: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +Registers a new step from app listener. + +Unlike others, this method doesn't behave as a decorator. +If you want to register a step from app by a decorator, use `AsyncWorkflowStepBuilder`'s methods. + +```python +# Create a new WorkflowStep instance +from slack_bolt.workflows.async_step import AsyncWorkflowStep +ws = AsyncWorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +# Pass Step to set up listeners +app.step(ws) +``` + +Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. +For further information about AsyncWorkflowStep specific function arguments +such as `configure`, `update`, `complete`, and `fail`, +refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents. + +**Arguments**: + +- `callback_id` _Union[str, Pattern, AsyncWorkflowStep, AsyncWorkflowStepBuilder]_ - The Callback ID for this step from app +- `edit` _Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]]_ - The function for displaying a modal in the Workflow Builder +- `save` _Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]]_ - The function for handling configuration in the Workflow Builder +- `execute` _Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]]_ - The function for handling the step execution + +#### error + +```python +def error( + func: Callable[..., Awaitable[Optional[BoltResponse]]]) -> Callable[..., Awaitable[Optional[BoltResponse]]] +``` + +Updates the global error handler. This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.error +async def custom_error_handler(error, body, logger): + logger.exception(f"Error: {error}") + logger.info(f"Request body: {body}") + +# Pass a function to this method +app.error(custom_error_handler) +``` + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `func` _Callable[..., Awaitable[Optional[BoltResponse]]]_ - The function that is supposed to be executed + when getting an unhandled error in Bolt app. + +#### event + +```python +def event( + event: Union[str, Pattern, Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]]], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new event listener. This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.event("team_join") +async def ask_for_introduction(event, say): + welcome_channel_id = "C12345" + user_id = event["user"] + text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel." + await say(text=text, channel=welcome_channel_id) + +# Pass a function to this method +app.event("team_join")(ask_for_introduction) +``` + +Refer to https://docs.slack.dev/apis/events-api/ for details of Events API. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `event` _Union[str, Pattern, Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]]]_ - The conditions that match a request payload. + If you pass a dict for this, you can have type, subtype in the constraint. +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### message + +```python +def message( + keyword: Union[str, Pattern] = '', + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new message event listener. This method can be used as either a decorator or a method. +Check the `App#event` method's docstring for details. + +```python +# Use this method as a decorator +@app.message(":wave:") +async def say_hello(message, say): + user = message['user'] + await say(f"Hi there, <@{user}>!") + +# Pass a function to this method +app.message(":wave:")(say_hello) +``` + +Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `keyword` _Union[str, Pattern]_ - The keyword to match +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### function + +```python +def function( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None, + auto_acknowledge: bool = True, + ack_timeout: int = 3) -> Callable[..., Optional[Callable[..., Awaitable[BoltResponse]]]] +``` + +Registers a new Function listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.function("reverse") +async def reverse_string(ack: AsyncAck, inputs: dict, complete: AsyncComplete, fail: AsyncFail): + try: + await ack() + string_to_reverse = inputs["stringToReverse"] + await complete({"reverseString": string_to_reverse[::-1]}) + except Exception as e: + await fail(f"Cannot reverse string (error: {e})") + raise e + +# Pass a function to this method +app.function("reverse")(reverse_string) +``` + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `callback_id` _Union[str, Pattern]_ - The callback id to identify the function +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### command + +```python +def command( + command: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new slash command listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.command("/echo") +async def repeat_text(ack, say, command): + # Acknowledge command request + await ack() + await say(f"{command['text']}") + +# Pass a function to this method +app.command("/echo")(repeat_text) +``` + +Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `command` _Union[str, Pattern]_ - The conditions that match a request payload +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### shortcut + +```python +def shortcut( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new shortcut listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.shortcut("open_modal") +async def open_modal(ack, body, client): + # Acknowledge the command request + await ack() + # Call views_open with the built-in client + await client.views_open( + # Pass a valid trigger_id within 3 seconds of receiving it + trigger_id=body["trigger_id"], + # View payload + view={ ... } + ) + +# Pass a function to this method +app.shortcut("open_modal")(open_modal) +``` + +Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `constraints` _Union[str, Pattern, Dict[str, Union[str, Pattern]]]_ - The conditions that match a request payload. +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### global\_shortcut + +```python +def global_shortcut( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new global shortcut listener. + +#### message\_shortcut + +```python +def message_shortcut( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new message shortcut listener. + +#### action + +```python +def action( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new action listener. This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.action("approve_button") +async def update_message(ack): + await ack() + +# Pass a function to this method +app.action("approve_button")(update_message) +``` + +* Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`. +* Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`. +* Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `constraints` _Union[str, Pattern, Dict[str, Union[str, Pattern]]]_ - The conditions that match a request payload +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### block\_action + +```python +def block_action( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `block_actions` action listener. +Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details. + +#### attachment\_action + +```python +def attachment_action( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `interactive_message` action listener. +Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details. + +#### dialog\_submission + +```python +def dialog_submission( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `dialog_submission` listener. +Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details. + +#### dialog\_cancellation + +```python +def dialog_cancellation( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `dialog_submission` listener. +Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details. + +#### view + +```python +def view( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `view_submission`/`view_closed` event listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.view("view_1") +async def handle_submission(ack, body, client, view): + # Assume there's an input block with `block_c` as the block_id and `dreamy_input` + hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"] + user = body["user"]["id"] + # Validate the inputs + errors = {} + if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5: + errors["block_c"] = "The value must be longer than 5 characters" + if len(errors) > 0: + await ack(response_action="errors", errors=errors) + return + # Acknowledge the view_submission event and close the modal + await ack() + # Do whatever you want with the input data - here we're saving it to a DB + +# Pass a function to this method +app.view("view_1")(handle_submission) +``` + +Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads. + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `constraints` _Union[str, Pattern, Dict[str, Union[str, Pattern]]]_ - The conditions that match a request payload +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### view\_submission + +```python +def view_submission( + constraints: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `view_submission` listener. +Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for +details. + +#### view\_closed + +```python +def view_closed( + constraints: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `view_closed` listener. +Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details. + +#### options + +```python +def options( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new options listener. +This method can be used as either a decorator or a method. + +```python +# Use this method as a decorator +@app.options("menu_selection") +async def show_menu_options(ack): + options = [ + { + "text": {"type": "plain_text", "text": "Option 1"}, + "value": "1-1", + }, + { + "text": {"type": "plain_text", "text": "Option 2"}, + "value": "1-2", + }, + ] + await ack(options=options) + +# Pass a function to this method +app.options("menu_selection")(show_menu_options) +``` + +Refer to the following documents for details: + +* https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select +* https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select + +To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. + +**Arguments**: + +- `matchers` _Optional[Sequence[Callable[..., Awaitable[bool]]]]_ - A list of listener matcher functions. + Only when all the matchers return True, the listener function can be invoked. +- `middleware` _Optional[Sequence[Union[Callable, AsyncMiddleware]]]_ - A list of lister middleware functions. + Only when all the middleware call `next()` method, the listener function can be invoked. + +#### block\_suggestion + +```python +def block_suggestion( + action_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `block_suggestion` listener. + +#### dialog\_suggestion + +```python +def dialog_suggestion( + callback_id: Union[str, Pattern], + matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None, + middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]] +``` + +Registers a new `dialog_suggestion` listener. +Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details. + +#### default\_tokens\_revoked\_event\_listener + +```python +def default_tokens_revoked_event_listener( +) -> Callable[..., Awaitable[Optional[BoltResponse]]] +``` + +#### default\_app\_uninstalled\_event\_listener + +```python +def default_app_uninstalled_event_listener( +) -> Callable[..., Awaitable[Optional[BoltResponse]]] +``` + +#### enable\_token\_revocation\_listeners + +```python +def enable_token_revocation_listeners() -> None +``` + +## AsyncAck Objects + +```python +class AsyncAck() +``` + +#### response: `Optional[BoltResponse]` + +#### \_\_init\_\_ + +```python +def __init__() +``` + +## AsyncBoltContext Objects + +```python +class AsyncBoltContext(BaseContext) +``` + +Context object associated with a request from Slack. + +#### to\_copyable + +```python +def to_copyable() -> AsyncBoltContext +``` + +#### listener\_runner + +```python +@property +def listener_runner() -> AsyncioListenerRunner +``` + +The properly configured listener_runner that is available for middleware/listeners. + +#### client + +```python +@property +def client() -> AsyncWebClient +``` + +The `AsyncWebClient` instance available for this request. + +```python +@app.event("app_mention") +async def handle_events(context): + await context.client.chat_postMessage( + channel=context.channel_id, + text="Thanks!", + ) + +# You can access "client" this way too. +@app.event("app_mention") +async def handle_events(client, context): + await client.chat_postMessage( + channel=context.channel_id, + text="Thanks!", + ) +``` + +**Returns**: + +- `AsyncWebClient` - `AsyncWebClient` instance + +#### ack + +```python +@property +def ack() -> AsyncAck +``` + +`ack()` function for this request. + +```python +@app.action("button") +async def handle_button_clicks(context): + await context.ack() + +# You can access "ack" this way too. +@app.action("button") +async def handle_button_clicks(ack): + await ack() +``` + +**Returns**: + +- `AsyncAck` - Callable `ack()` function + +#### say + +```python +@property +def say() -> AsyncSay +``` + +`say()` function for this request. + +```python +@app.action("button") +async def handle_button_clicks(context): + await context.ack() + await context.say("Hi!") + +# You can access "ack" this way too. +@app.action("button") +async def handle_button_clicks(ack, say): + await ack() + await say("Hi!") +``` + +**Returns**: + +- `AsyncSay` - Callable `say()` function + +#### respond + +```python +@property +def respond() -> Optional[AsyncRespond] +``` + +`respond()` function for this request. + +```python +@app.action("button") +async def handle_button_clicks(context): + await context.ack() + await context.respond("Hi!") + +# You can access "ack" this way too. +@app.action("button") +async def handle_button_clicks(ack, respond): + await ack() + await respond("Hi!") +``` + +**Returns**: + +- `Optional[AsyncRespond]` - Callable `respond()` function + +#### complete + +```python +@property +def complete() -> AsyncComplete +``` + +`complete()` function for this request. Once a custom function's state is set to complete, +any outputs the function returns will be passed along to the next step of its housing workflow, +or complete the workflow if the function is the last step in a workflow. Additionally, +any interactivity handlers associated to a function invocation will no longer be invocable. + +```python +@app.function("reverse") +async def handle_button_clicks(ack, complete): + await ack() + await complete(outputs={"stringReverse":"olleh"}) + +@app.function("reverse") +async def handle_button_clicks(context): + await context.ack() + await context.complete(outputs={"stringReverse":"olleh"}) +``` + +**Returns**: + +- `AsyncComplete` - Callable `complete()` function + +#### fail + +```python +@property +def fail() -> AsyncFail +``` + +`fail()` function for this request. Once a custom function's state is set to error, +its housing workflow will be interrupted and any provided error message will be passed +on to the end user through SlackBot. Additionally, any interactivity handlers associated +to a function invocation will no longer be invocable. + +```python +@app.function("reverse") +async def handle_button_clicks(ack, fail): + await ack() + await fail(error="something went wrong") + +@app.function("reverse") +async def handle_button_clicks(context): + await context.ack() + await context.fail(error="something went wrong") +``` + +**Returns**: + +- `AsyncFail` - Callable `fail()` function + +#### set\_title + +```python +@property +def set_title() -> Optional[AsyncSetTitle] +``` + +#### set\_status + +```python +@property +def set_status() -> Optional[AsyncSetStatus] +``` + +#### set\_suggested\_prompts + +```python +@property +def set_suggested_prompts() -> Optional[AsyncSetSuggestedPrompts] +``` + +#### get\_thread\_context + +```python +@property +def get_thread_context() -> Optional[AsyncGetThreadContext] +``` + +#### say\_stream + +```python +@property +def say_stream() -> Optional[AsyncSayStream] +``` + +#### save\_thread\_context + +```python +@property +def save_thread_context() -> Optional[AsyncSaveThreadContext] +``` + +## AsyncRespond Objects + +```python +class AsyncRespond() +``` + +#### response\_url: `Optional[str]` + +#### proxy: `Optional[str]` + +#### ssl: `Optional[SSLContext]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + response_url: Optional[str], + proxy: Optional[str] = None, + ssl: Optional[SSLContext] = None) +``` + +## AsyncSay Objects + +```python +class AsyncSay() +``` + +#### client: `Optional[AsyncWebClient]` + +#### channel: `Optional[str]` + +#### thread\_ts: `Optional[str]` + +#### build\_metadata: `Optional[Callable[[], Awaitable[Union[Dict, Metadata]]]]` + +#### \_\_init\_\_ + +```python +def __init__( + client: Optional[AsyncWebClient], + channel: Optional[str], + thread_ts: Optional[str] = None, + build_metadata: Optional[Callable[[], Awaitable[Union[Dict, Metadata]]]] = None) +``` + +## AsyncListener Objects + +```python +class AsyncListener() +``` + +#### matchers: `Sequence[AsyncListenerMatcher]` + +#### middleware: `Sequence[AsyncMiddleware]` + +#### ack\_function: `Callable[..., Awaitable[BoltResponse]]` + +#### lazy\_functions: `Sequence[Callable[..., Awaitable[None]]]` + +#### auto\_acknowledgement: `bool` + +#### ack\_timeout: `int` + +#### async\_matches + +```python +async def async_matches(*, req: AsyncBoltRequest, resp: BoltResponse) -> bool +``` + +#### run\_async\_middleware + +```python +async def run_async_middleware( + *, + req: AsyncBoltRequest, + resp: BoltResponse) -> Tuple[Optional[BoltResponse], bool] +``` + +Runs an async middleware. + +**Arguments**: + +- `req` _AsyncBoltRequest_ - The incoming request +- `resp` _BoltResponse_ - The current response + +**Returns**: + +- `Tuple[Optional[BoltResponse], bool]` - A tuple of the processed response and a flag indicating termination + +#### run\_ack\_function + +```python +async def run_ack_function( + *, + request: AsyncBoltRequest, + response: BoltResponse) -> Optional[BoltResponse] +``` + +Runs all the registered middleware and then run the listener function. + +**Arguments**: + +- `request` _AsyncBoltRequest_ - The incoming request +- `response` _BoltResponse_ - The current response + +**Returns**: + +- `Optional[BoltResponse]` - The processed response + +## AsyncCustomListenerMatcher Objects + +```python +class AsyncCustomListenerMatcher(AsyncListenerMatcher) +``` + +#### app\_name: `str` + +#### func: `Callable[..., Awaitable[bool]]` + +#### arg\_names: `Sequence[str]` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str, + func: Callable[..., Awaitable[bool]], + base_logger: Optional[Logger] = None) +``` + +#### async\_matches + +```python +async def async_matches(req: AsyncBoltRequest, resp: BoltResponse) -> bool +``` + +## AsyncBoltRequest Objects + +```python +class AsyncBoltRequest() +``` + +#### raw\_body: `str` + +#### body: `Dict[str, Any]` + +#### query: `Dict[str, Sequence[str]]` + +#### headers: `Dict[str, Sequence[str]]` + +#### content\_type: `Optional[str]` + +#### context: `AsyncBoltContext` + +#### lazy\_only: `bool` + +#### lazy\_function\_name: `Optional[str]` + +#### mode: `str` + +#### \_\_init\_\_ + +```python +def __init__( + *, + body: Union[str, dict], + query: Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]] = None, + headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None, + context: Optional[Dict[str, Any]] = None, + mode: str = 'http') +``` + +Request to a Bolt app. + +**Arguments**: + +- `body` _Union[str, dict]_ - The raw request body (only plain text is supported for "http" mode) +- `query` _Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]]_ - The query string data in any data format. +- `headers` _Optional[Dict[str, Union[str, Sequence[str]]]]_ - The request headers. +- `context` _Optional[Dict[str, Any]]_ - The context in this request. +- `mode` _str_ - The mode used for this request. (either "http" or "socket_mode") + +#### to\_copyable + +```python +def to_copyable() -> AsyncBoltRequest +``` + +## AsyncAssistant Objects + +```python +class AsyncAssistant(AsyncMiddleware) +``` + +#### thread\_context\_store: `Optional[AsyncAssistantThreadContextStore]` + +#### base\_logger: `Optional[logging.Logger]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str = 'assistant', + thread_context_store: Optional[AsyncAssistantThreadContextStore] = None, + logger: Optional[logging.Logger] = None) +``` + +#### thread\_started + +```python +def thread_started( + *args, + matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None, + middleware: Optional[Union[Callable, AsyncMiddleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### user\_message + +```python +def user_message( + *args, + matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None, + middleware: Optional[Union[Callable, AsyncMiddleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### bot\_message + +```python +def bot_message( + *args, + matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None, + middleware: Optional[Union[Callable, AsyncMiddleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### thread\_context\_changed + +```python +def thread_context_changed( + *args, + matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None, + middleware: Optional[Union[Callable, AsyncMiddleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### default\_thread\_context\_changed + +```python +async def default_thread_context_changed( + save_thread_context: AsyncSaveThreadContext, + payload: dict) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> Optional[BoltResponse] +``` + +#### build\_listener + +```python +def build_listener( + listener_or_functions: Union[AsyncListener, Callable, List[Callable]], + matchers: Optional[List[Union[AsyncListenerMatcher, Callable[..., Awaitable[bool]]]]] = None, + middleware: Optional[List[AsyncMiddleware]] = None, + base_logger: Optional[Logger] = None) -> AsyncListener +``` + +## AsyncSetStatus Objects + +```python +class AsyncSetStatus() +``` + +#### client: `AsyncWebClient` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### \_\_init\_\_ + +```python +def __init__(client: AsyncWebClient, channel_id: str, thread_ts: str) +``` + +## AsyncSetTitle Objects + +```python +class AsyncSetTitle() +``` + +#### client: `AsyncWebClient` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### \_\_init\_\_ + +```python +def __init__(client: AsyncWebClient, channel_id: str, thread_ts: str) +``` + +## AsyncSetSuggestedPrompts Objects + +```python +class AsyncSetSuggestedPrompts() +``` + +#### client: `AsyncWebClient` + +#### channel\_id: `str` + +#### thread\_ts: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__(client: AsyncWebClient, channel_id: str, thread_ts: Optional[str] = None) +``` + +## AsyncGetThreadContext Objects + +```python +class AsyncGetThreadContext() +``` + +#### thread\_context\_store: `AsyncAssistantThreadContextStore` + +#### payload: `dict` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### thread\_context\_loaded: `bool` + +#### \_\_init\_\_ + +```python +def __init__( + thread_context_store: AsyncAssistantThreadContextStore, + channel_id: str, + thread_ts: str, + payload: dict) +``` + +## AsyncSaveThreadContext Objects + +```python +class AsyncSaveThreadContext() +``` + +#### thread\_context\_store: `AsyncAssistantThreadContextStore` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### \_\_init\_\_ + +```python +def __init__( + thread_context_store: AsyncAssistantThreadContextStore, + channel_id: str, + thread_ts: str) +``` + +## AsyncSayStream Objects + +```python +class AsyncSayStream() +``` + +#### client: `AsyncWebClient` + +#### channel: `Optional[str]` + +#### recipient\_team\_id: `Optional[str]` + +#### recipient\_user\_id: `Optional[str]` + +#### thread\_ts: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + client: AsyncWebClient, + channel: Optional[str] = None, + recipient_team_id: Optional[str] = None, + recipient_user_id: Optional[str] = None, + thread_ts: Optional[str] = None) +``` diff --git a/docs/english/reference/authorization/async_authorize.md b/docs/english/reference/authorization/async_authorize.md new file mode 100644 index 000000000..798e12394 --- /dev/null +++ b/docs/english/reference/authorization/async_authorize.md @@ -0,0 +1,72 @@ +--- +sidebar_label: async_authorize +title: slack_bolt.authorization.async_authorize +--- + +## AsyncAuthorize Objects + +```python +class AsyncAuthorize() +``` + +This provides authorize function that returns AuthorizeResult +for an incoming request from Slack. + +#### \_\_init\_\_ + +```python +def __init__() +``` + +## AsyncCallableAuthorize Objects + +```python +class AsyncCallableAuthorize(AsyncAuthorize) +``` + +When you pass the authorize argument in AsyncApp constructor, +This authorize implementation will be used. + +#### \_\_init\_\_ + +```python +def __init__(*, logger: Logger, func: Callable[..., Awaitable[AuthorizeResult]]) +``` + +## AsyncInstallationStoreAuthorize Objects + +```python +class AsyncInstallationStoreAuthorize(AsyncAuthorize) +``` + +If you use the OAuth flow settings, this authorize implementation will be used. +As long as your own InstallationStore (or the built-in ones) works as you expect, +you can expect that the authorize layer should work for you without any customization. + +#### authorize\_result\_cache: `Dict[str, AuthorizeResult]` + +#### bot\_only: `bool` + +#### user\_token\_resolution: `str` + +#### find\_installation\_available: `Optional[bool]` + +#### find\_bot\_available: `Optional[bool]` + +#### token\_rotator: `Optional[AsyncTokenRotator]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + logger: Logger, + installation_store: AsyncInstallationStore, + client_id: Optional[str] = None, + client_secret: Optional[str] = None, + token_rotation_expiration_minutes: Optional[int] = None, + bot_only: bool = False, + cache_enabled: bool = False, + client: Optional[AsyncWebClient] = None, + user_token_resolution: str = 'authed_user') +``` diff --git a/docs/english/reference/authorization/async_authorize_args.md b/docs/english/reference/authorization/async_authorize_args.md new file mode 100644 index 000000000..df35a1e87 --- /dev/null +++ b/docs/english/reference/authorization/async_authorize_args.md @@ -0,0 +1,42 @@ +--- +sidebar_label: async_authorize_args +title: slack_bolt.authorization.async_authorize_args +--- + +## AsyncAuthorizeArgs Objects + +```python +class AsyncAuthorizeArgs() +``` + +#### context: `AsyncBoltContext` + +#### logger: `Logger` + +#### client: `AsyncWebClient` + +#### enterprise\_id: `Optional[str]` + +#### team\_id: `Optional[str]` + +#### user\_id: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + context: AsyncBoltContext, + enterprise_id: Optional[str], + team_id: Optional[str], + user_id: Optional[str]) +``` + +The full list of the arguments passed to `authorize` function. + +**Arguments**: + +- `context` _AsyncBoltContext_ - The request context +- `enterprise_id` _Optional[str]_ - The Organization ID (Enterprise Grid) +- `team_id` _Optional[str]_ - The workspace ID +- `user_id` _Optional[str]_ - The request user ID diff --git a/docs/english/reference/authorization/authorize.md b/docs/english/reference/authorization/authorize.md new file mode 100644 index 000000000..3965f1f43 --- /dev/null +++ b/docs/english/reference/authorization/authorize.md @@ -0,0 +1,72 @@ +--- +sidebar_label: authorize +title: slack_bolt.authorization.authorize +--- + +## Authorize Objects + +```python +class Authorize() +``` + +This provides authorize function that returns AuthorizeResult +for an incoming request from Slack. + +#### \_\_init\_\_ + +```python +def __init__() +``` + +## CallableAuthorize Objects + +```python +class CallableAuthorize(Authorize) +``` + +When you pass the `authorize` argument in AsyncApp constructor, +This `authorize` implementation will be used. + +#### \_\_init\_\_ + +```python +def __init__(*, logger: Logger, func: Callable[..., AuthorizeResult]) +``` + +## InstallationStoreAuthorize Objects + +```python +class InstallationStoreAuthorize(Authorize) +``` + +If you use the OAuth flow settings, this `authorize` implementation will be used. +As long as your own InstallationStore (or the built-in ones) works as you expect, +you can expect that the `authorize` layer should work for you without any customization. + +#### authorize\_result\_cache: `Dict[str, AuthorizeResult]` + +#### bot\_only: `bool` + +#### user\_token\_resolution: `str` + +#### find\_installation\_available: `bool` + +#### find\_bot\_available: `bool` + +#### token\_rotator: `Optional[TokenRotator]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + logger: Logger, + installation_store: InstallationStore, + client_id: Optional[str] = None, + client_secret: Optional[str] = None, + token_rotation_expiration_minutes: Optional[int] = None, + bot_only: bool = False, + cache_enabled: bool = False, + client: Optional[WebClient] = None, + user_token_resolution: str = 'authed_user') +``` diff --git a/docs/english/reference/authorization/authorize_args.md b/docs/english/reference/authorization/authorize_args.md new file mode 100644 index 000000000..e5ae33a82 --- /dev/null +++ b/docs/english/reference/authorization/authorize_args.md @@ -0,0 +1,42 @@ +--- +sidebar_label: authorize_args +title: slack_bolt.authorization.authorize_args +--- + +## AuthorizeArgs Objects + +```python +class AuthorizeArgs() +``` + +#### context: `BoltContext` + +#### logger: `Logger` + +#### client: `WebClient` + +#### enterprise\_id: `Optional[str]` + +#### team\_id: `Optional[str]` + +#### user\_id: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + context: BoltContext, + enterprise_id: Optional[str], + team_id: Optional[str], + user_id: Optional[str]) +``` + +The full list of the arguments passed to `authorize` function. + +**Arguments**: + +- `context` _BoltContext_ - The request context +- `enterprise_id` _Optional[str]_ - The Organization ID (Enterprise Grid) +- `team_id` _Optional[str]_ - The workspace ID +- `user_id` _Optional[str]_ - The request user ID diff --git a/docs/english/reference/authorization/authorize_result.md b/docs/english/reference/authorization/authorize_result.md new file mode 100644 index 000000000..7042bb666 --- /dev/null +++ b/docs/english/reference/authorization/authorize_result.md @@ -0,0 +1,83 @@ +--- +sidebar_label: authorize_result +title: slack_bolt.authorization.authorize_result +--- + +## AuthorizeResult Objects + +```python +class AuthorizeResult(dict) +``` + +Authorize function call result + +#### enterprise\_id: `Optional[str]` + +#### team\_id: `Optional[str]` + +#### team: `Optional[str]` + +#### url: `Optional[str]` + +#### bot\_id: `Optional[str]` + +#### bot\_user\_id: `Optional[str]` + +#### bot\_token: `Optional[str]` + +#### bot\_scopes: `Optional[Sequence[str]]` + +#### user\_id: `Optional[str]` + +#### user: `Optional[str]` + +#### user\_token: `Optional[str]` + +#### user\_scopes: `Optional[Sequence[str]]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + enterprise_id: Optional[str], + team_id: Optional[str], + team: Optional[str] = None, + url: Optional[str] = None, + bot_user_id: Optional[str] = None, + bot_id: Optional[str] = None, + bot_token: Optional[str] = None, + bot_scopes: Optional[Union[Sequence[str], str]] = None, + user_id: Optional[str] = None, + user: Optional[str] = None, + user_token: Optional[str] = None, + user_scopes: Optional[Union[Sequence[str], str]] = None) +``` + +**Arguments**: + +- `enterprise_id` _Optional[str]_ - Organization ID (Enterprise Grid) starting with `E` +- `team_id` _Optional[str]_ - Workspace ID starting with `T` +- `team` _Optional[str]_ - Workspace name +- `url` _Optional[str]_ - Workspace slack.com URL +- `bot_user_id` _Optional[str]_ - Bot user's User ID starting with either `U` or `W` +- `bot_id` _Optional[str]_ - Bot ID starting with `B` +- `bot_token` _Optional[str]_ - Bot user access token starting with `xoxb-` +- `bot_scopes` _Optional[Union[Sequence[str], str]]_ - The scopes associated with the bot token +- `user_id` _Optional[str]_ - The request user ID +- `user` _Optional[str]_ - The request user's name +- `user_token` _Optional[str]_ - User access token starting with `xoxp-` +- `user_scopes` _Optional[Union[Sequence[str], str]]_ - The scopes associated wth the user token + +#### from\_auth\_test\_response + +```python +def from_auth_test_response( + *, + bot_token: Optional[str] = None, + user_token: Optional[str] = None, + bot_scopes: Optional[Union[Sequence[str], str]] = None, + user_scopes: Optional[Union[Sequence[str], str]] = None, + auth_test_response: Union[SlackResponse, AsyncSlackResponse], + user_auth_test_response: Optional[Union[SlackResponse, AsyncSlackResponse]] = None) -> AuthorizeResult +``` diff --git a/docs/english/reference/authorization/index.md b/docs/english/reference/authorization/index.md new file mode 100644 index 000000000..7f23f96cd --- /dev/null +++ b/docs/english/reference/authorization/index.md @@ -0,0 +1,96 @@ +--- +sidebar_label: authorization +title: slack_bolt.authorization +--- + +Authorization is the process of determining which Slack credentials should be available +while processing an incoming Slack event. + +Refer to https://docs.slack.dev/tools/bolt-python/concepts/authorization for details. + +## Submodules + +- [slack_bolt.authorization.async_authorize](/tools/bolt-python/reference/authorization/async_authorize) +- [slack_bolt.authorization.async_authorize_args](/tools/bolt-python/reference/authorization/async_authorize_args) +- [slack_bolt.authorization.authorize](/tools/bolt-python/reference/authorization/authorize) +- [slack_bolt.authorization.authorize_args](/tools/bolt-python/reference/authorization/authorize_args) +- [slack_bolt.authorization.authorize_result](/tools/bolt-python/reference/authorization/authorize_result) + +## AuthorizeResult Objects + +```python +class AuthorizeResult(dict) +``` + +Authorize function call result + +#### enterprise\_id: `Optional[str]` + +#### team\_id: `Optional[str]` + +#### team: `Optional[str]` + +#### url: `Optional[str]` + +#### bot\_id: `Optional[str]` + +#### bot\_user\_id: `Optional[str]` + +#### bot\_token: `Optional[str]` + +#### bot\_scopes: `Optional[Sequence[str]]` + +#### user\_id: `Optional[str]` + +#### user: `Optional[str]` + +#### user\_token: `Optional[str]` + +#### user\_scopes: `Optional[Sequence[str]]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + enterprise_id: Optional[str], + team_id: Optional[str], + team: Optional[str] = None, + url: Optional[str] = None, + bot_user_id: Optional[str] = None, + bot_id: Optional[str] = None, + bot_token: Optional[str] = None, + bot_scopes: Optional[Union[Sequence[str], str]] = None, + user_id: Optional[str] = None, + user: Optional[str] = None, + user_token: Optional[str] = None, + user_scopes: Optional[Union[Sequence[str], str]] = None) +``` + +**Arguments**: + +- `enterprise_id` _Optional[str]_ - Organization ID (Enterprise Grid) starting with `E` +- `team_id` _Optional[str]_ - Workspace ID starting with `T` +- `team` _Optional[str]_ - Workspace name +- `url` _Optional[str]_ - Workspace slack.com URL +- `bot_user_id` _Optional[str]_ - Bot user's User ID starting with either `U` or `W` +- `bot_id` _Optional[str]_ - Bot ID starting with `B` +- `bot_token` _Optional[str]_ - Bot user access token starting with `xoxb-` +- `bot_scopes` _Optional[Union[Sequence[str], str]]_ - The scopes associated with the bot token +- `user_id` _Optional[str]_ - The request user ID +- `user` _Optional[str]_ - The request user's name +- `user_token` _Optional[str]_ - User access token starting with `xoxp-` +- `user_scopes` _Optional[Union[Sequence[str], str]]_ - The scopes associated wth the user token + +#### from\_auth\_test\_response + +```python +def from_auth_test_response( + *, + bot_token: Optional[str] = None, + user_token: Optional[str] = None, + bot_scopes: Optional[Union[Sequence[str], str]] = None, + user_scopes: Optional[Union[Sequence[str], str]] = None, + auth_test_response: Union[SlackResponse, AsyncSlackResponse], + user_auth_test_response: Optional[Union[SlackResponse, AsyncSlackResponse]] = None) -> AuthorizeResult +``` diff --git a/docs/english/reference/context/ack/ack.md b/docs/english/reference/context/ack/ack.md new file mode 100644 index 000000000..c8ef3f5b9 --- /dev/null +++ b/docs/english/reference/context/ack/ack.md @@ -0,0 +1,19 @@ +--- +sidebar_label: ack +title: slack_bolt.context.ack.ack +slug: ack +--- + +## Ack Objects + +```python +class Ack() +``` + +#### response: `Optional[BoltResponse]` + +#### \_\_init\_\_ + +```python +def __init__() +``` diff --git a/docs/english/reference/context/ack/async_ack.md b/docs/english/reference/context/ack/async_ack.md new file mode 100644 index 000000000..5f8d84fca --- /dev/null +++ b/docs/english/reference/context/ack/async_ack.md @@ -0,0 +1,18 @@ +--- +sidebar_label: async_ack +title: slack_bolt.context.ack.async_ack +--- + +## AsyncAck Objects + +```python +class AsyncAck() +``` + +#### response: `Optional[BoltResponse]` + +#### \_\_init\_\_ + +```python +def __init__() +``` diff --git a/docs/english/reference/context/ack/index.md b/docs/english/reference/context/ack/index.md new file mode 100644 index 000000000..c46e6053c --- /dev/null +++ b/docs/english/reference/context/ack/index.md @@ -0,0 +1,24 @@ +--- +sidebar_label: ack +title: slack_bolt.context.ack +--- + +## Submodules + +- [slack_bolt.context.ack.ack](/tools/bolt-python/reference/context/ack/ack) +- [slack_bolt.context.ack.async_ack](/tools/bolt-python/reference/context/ack/async_ack) +- [slack_bolt.context.ack.internals](/tools/bolt-python/reference/context/ack/internals) + +## Ack Objects + +```python +class Ack() +``` + +#### response: `Optional[BoltResponse]` + +#### \_\_init\_\_ + +```python +def __init__() +``` diff --git a/docs/english/reference/context/ack/internals.md b/docs/english/reference/context/ack/internals.md new file mode 100644 index 000000000..20b3fbef0 --- /dev/null +++ b/docs/english/reference/context/ack/internals.md @@ -0,0 +1,6 @@ +--- +sidebar_label: internals +title: slack_bolt.context.ack.internals +--- + + diff --git a/docs/english/reference/context/assistant/assistant_utilities.md b/docs/english/reference/context/assistant/assistant_utilities.md new file mode 100644 index 000000000..6fb13353e --- /dev/null +++ b/docs/english/reference/context/assistant/assistant_utilities.md @@ -0,0 +1,58 @@ +--- +sidebar_label: assistant_utilities +title: slack_bolt.context.assistant.assistant_utilities +--- + +## AssistantUtilities Objects + +```python +class AssistantUtilities() +``` + +#### payload: `dict` + +#### client: `WebClient` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### thread\_context\_store: `AssistantThreadContextStore` + +#### \_\_init\_\_ + +```python +def __init__( + *, + payload: dict, + context: BoltContext, + thread_context_store: Optional[AssistantThreadContextStore] = None) +``` + +#### set\_title + +```python +@property +def set_title() -> SetTitle +``` + +#### say + +```python +@property +def say() -> Say +``` + +#### get\_thread\_context + +```python +@property +def get_thread_context() -> GetThreadContext +``` + +#### save\_thread\_context + +```python +@property +def save_thread_context() -> SaveThreadContext +``` diff --git a/docs/english/reference/context/assistant/async_assistant_utilities.md b/docs/english/reference/context/assistant/async_assistant_utilities.md new file mode 100644 index 000000000..d5d0bd046 --- /dev/null +++ b/docs/english/reference/context/assistant/async_assistant_utilities.md @@ -0,0 +1,58 @@ +--- +sidebar_label: async_assistant_utilities +title: slack_bolt.context.assistant.async_assistant_utilities +--- + +## AsyncAssistantUtilities Objects + +```python +class AsyncAssistantUtilities() +``` + +#### payload: `dict` + +#### client: `AsyncWebClient` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### thread\_context\_store: `AsyncAssistantThreadContextStore` + +#### \_\_init\_\_ + +```python +def __init__( + *, + payload: dict, + context: AsyncBoltContext, + thread_context_store: Optional[AsyncAssistantThreadContextStore] = None) +``` + +#### set\_title + +```python +@property +def set_title() -> AsyncSetTitle +``` + +#### say + +```python +@property +def say() -> AsyncSay +``` + +#### get\_thread\_context + +```python +@property +def get_thread_context() -> AsyncGetThreadContext +``` + +#### save\_thread\_context + +```python +@property +def save_thread_context() -> AsyncSaveThreadContext +``` diff --git a/docs/english/reference/context/assistant/index.md b/docs/english/reference/context/assistant/index.md new file mode 100644 index 000000000..e65eadcdc --- /dev/null +++ b/docs/english/reference/context/assistant/index.md @@ -0,0 +1,12 @@ +--- +sidebar_label: assistant +title: slack_bolt.context.assistant +--- + +## Submodules + +- [slack_bolt.context.assistant.assistant_utilities](/tools/bolt-python/reference/context/assistant/assistant_utilities) +- [slack_bolt.context.assistant.async_assistant_utilities](/tools/bolt-python/reference/context/assistant/async_assistant_utilities) +- [slack_bolt.context.assistant.internals](/tools/bolt-python/reference/context/assistant/internals) +- [slack_bolt.context.assistant.thread_context](/tools/bolt-python/reference/context/assistant/thread_context) +- [slack_bolt.context.assistant.thread_context_store](/tools/bolt-python/reference/context/assistant/thread_context_store) diff --git a/docs/english/reference/context/assistant/internals.md b/docs/english/reference/context/assistant/internals.md new file mode 100644 index 000000000..732aa0e72 --- /dev/null +++ b/docs/english/reference/context/assistant/internals.md @@ -0,0 +1,13 @@ +--- +sidebar_label: internals +title: slack_bolt.context.assistant.internals +--- + +#### has\_channel\_id\_and\_thread\_ts + +```python +def has_channel_id_and_thread_ts(payload: dict) -> bool +``` + +Verifies if the given payload has both channel_id and thread_ts under assistant_thread property. +This data pattern is available for assistant_* events. diff --git a/docs/english/reference/context/assistant/thread_context/index.md b/docs/english/reference/context/assistant/thread_context/index.md new file mode 100644 index 000000000..9aa64ee48 --- /dev/null +++ b/docs/english/reference/context/assistant/thread_context/index.md @@ -0,0 +1,22 @@ +--- +sidebar_label: thread_context +title: slack_bolt.context.assistant.thread_context +--- + +## AssistantThreadContext Objects + +```python +class AssistantThreadContext(dict) +``` + +#### enterprise\_id: `Optional[str]` + +#### team\_id: `Optional[str]` + +#### channel\_id: `str` + +#### \_\_init\_\_ + +```python +def __init__(payload: dict) +``` diff --git a/docs/english/reference/context/assistant/thread_context_store/async_store.md b/docs/english/reference/context/assistant/thread_context_store/async_store.md new file mode 100644 index 000000000..77ce5c62c --- /dev/null +++ b/docs/english/reference/context/assistant/thread_context_store/async_store.md @@ -0,0 +1,22 @@ +--- +sidebar_label: async_store +title: slack_bolt.context.assistant.thread_context_store.async_store +--- + +## AsyncAssistantThreadContextStore Objects + +```python +class AsyncAssistantThreadContextStore() +``` + +#### save + +```python +async def save(*, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None +``` + +#### find + +```python +async def find(*, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext] +``` diff --git a/docs/english/reference/context/assistant/thread_context_store/default_async_store.md b/docs/english/reference/context/assistant/thread_context_store/default_async_store.md new file mode 100644 index 000000000..a49c34e47 --- /dev/null +++ b/docs/english/reference/context/assistant/thread_context_store/default_async_store.md @@ -0,0 +1,32 @@ +--- +sidebar_label: default_async_store +title: slack_bolt.context.assistant.thread_context_store.default_async_store +--- + +## DefaultAsyncAssistantThreadContextStore Objects + +```python +class DefaultAsyncAssistantThreadContextStore(AsyncAssistantThreadContextStore) +``` + +#### client: `AsyncWebClient` + +#### context: `AsyncBoltContext` + +#### \_\_init\_\_ + +```python +def __init__(context: AsyncBoltContext) +``` + +#### save + +```python +async def save(*, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None +``` + +#### find + +```python +async def find(*, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext] +``` diff --git a/docs/english/reference/context/assistant/thread_context_store/default_store.md b/docs/english/reference/context/assistant/thread_context_store/default_store.md new file mode 100644 index 000000000..107f29805 --- /dev/null +++ b/docs/english/reference/context/assistant/thread_context_store/default_store.md @@ -0,0 +1,32 @@ +--- +sidebar_label: default_store +title: slack_bolt.context.assistant.thread_context_store.default_store +--- + +## DefaultAssistantThreadContextStore Objects + +```python +class DefaultAssistantThreadContextStore(AssistantThreadContextStore) +``` + +#### client: `WebClient` + +#### context: `BoltContext` + +#### \_\_init\_\_ + +```python +def __init__(context: BoltContext) +``` + +#### save + +```python +def save(*, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None +``` + +#### find + +```python +def find(*, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext] +``` diff --git a/docs/english/reference/context/assistant/thread_context_store/file/index.md b/docs/english/reference/context/assistant/thread_context_store/file/index.md new file mode 100644 index 000000000..cb56ee10b --- /dev/null +++ b/docs/english/reference/context/assistant/thread_context_store/file/index.md @@ -0,0 +1,28 @@ +--- +sidebar_label: file +title: slack_bolt.context.assistant.thread_context_store.file +--- + +## FileAssistantThreadContextStore Objects + +```python +class FileAssistantThreadContextStore(AssistantThreadContextStore) +``` + +#### \_\_init\_\_ + +```python +def __init__(base_dir: str = str(Path.home()) + '/.bolt-app-assistant-thread-contexts') +``` + +#### save + +```python +def save(*, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None +``` + +#### find + +```python +def find(*, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext] +``` diff --git a/docs/english/reference/context/assistant/thread_context_store/index.md b/docs/english/reference/context/assistant/thread_context_store/index.md new file mode 100644 index 000000000..afb9de2fa --- /dev/null +++ b/docs/english/reference/context/assistant/thread_context_store/index.md @@ -0,0 +1,12 @@ +--- +sidebar_label: thread_context_store +title: slack_bolt.context.assistant.thread_context_store +--- + +## Submodules + +- [slack_bolt.context.assistant.thread_context_store.async_store](/tools/bolt-python/reference/context/assistant/thread_context_store/async_store) +- [slack_bolt.context.assistant.thread_context_store.default_async_store](/tools/bolt-python/reference/context/assistant/thread_context_store/default_async_store) +- [slack_bolt.context.assistant.thread_context_store.default_store](/tools/bolt-python/reference/context/assistant/thread_context_store/default_store) +- [slack_bolt.context.assistant.thread_context_store.file](/tools/bolt-python/reference/context/assistant/thread_context_store/file) +- [slack_bolt.context.assistant.thread_context_store.store](/tools/bolt-python/reference/context/assistant/thread_context_store/store) diff --git a/docs/english/reference/context/assistant/thread_context_store/store.md b/docs/english/reference/context/assistant/thread_context_store/store.md new file mode 100644 index 000000000..491fbc849 --- /dev/null +++ b/docs/english/reference/context/assistant/thread_context_store/store.md @@ -0,0 +1,22 @@ +--- +sidebar_label: store +title: slack_bolt.context.assistant.thread_context_store.store +--- + +## AssistantThreadContextStore Objects + +```python +class AssistantThreadContextStore() +``` + +#### save + +```python +def save(*, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None +``` + +#### find + +```python +def find(*, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext] +``` diff --git a/docs/english/reference/context/async_context.md b/docs/english/reference/context/async_context.md new file mode 100644 index 000000000..6402c2fbd --- /dev/null +++ b/docs/english/reference/context/async_context.md @@ -0,0 +1,231 @@ +--- +sidebar_label: async_context +title: slack_bolt.context.async_context +--- + +## AsyncBoltContext Objects + +```python +class AsyncBoltContext(BaseContext) +``` + +Context object associated with a request from Slack. + +#### to\_copyable + +```python +def to_copyable() -> AsyncBoltContext +``` + +#### listener\_runner + +```python +@property +def listener_runner() -> AsyncioListenerRunner +``` + +The properly configured listener_runner that is available for middleware/listeners. + +#### client + +```python +@property +def client() -> AsyncWebClient +``` + +The `AsyncWebClient` instance available for this request. + +```python +@app.event("app_mention") +async def handle_events(context): + await context.client.chat_postMessage( + channel=context.channel_id, + text="Thanks!", + ) + +# You can access "client" this way too. +@app.event("app_mention") +async def handle_events(client, context): + await client.chat_postMessage( + channel=context.channel_id, + text="Thanks!", + ) +``` + +**Returns**: + +- `AsyncWebClient` - `AsyncWebClient` instance + +#### ack + +```python +@property +def ack() -> AsyncAck +``` + +`ack()` function for this request. + +```python +@app.action("button") +async def handle_button_clicks(context): + await context.ack() + +# You can access "ack" this way too. +@app.action("button") +async def handle_button_clicks(ack): + await ack() +``` + +**Returns**: + +- `AsyncAck` - Callable `ack()` function + +#### say + +```python +@property +def say() -> AsyncSay +``` + +`say()` function for this request. + +```python +@app.action("button") +async def handle_button_clicks(context): + await context.ack() + await context.say("Hi!") + +# You can access "ack" this way too. +@app.action("button") +async def handle_button_clicks(ack, say): + await ack() + await say("Hi!") +``` + +**Returns**: + +- `AsyncSay` - Callable `say()` function + +#### respond + +```python +@property +def respond() -> Optional[AsyncRespond] +``` + +`respond()` function for this request. + +```python +@app.action("button") +async def handle_button_clicks(context): + await context.ack() + await context.respond("Hi!") + +# You can access "ack" this way too. +@app.action("button") +async def handle_button_clicks(ack, respond): + await ack() + await respond("Hi!") +``` + +**Returns**: + +- `Optional[AsyncRespond]` - Callable `respond()` function + +#### complete + +```python +@property +def complete() -> AsyncComplete +``` + +`complete()` function for this request. Once a custom function's state is set to complete, +any outputs the function returns will be passed along to the next step of its housing workflow, +or complete the workflow if the function is the last step in a workflow. Additionally, +any interactivity handlers associated to a function invocation will no longer be invocable. + +```python +@app.function("reverse") +async def handle_button_clicks(ack, complete): + await ack() + await complete(outputs={"stringReverse":"olleh"}) + +@app.function("reverse") +async def handle_button_clicks(context): + await context.ack() + await context.complete(outputs={"stringReverse":"olleh"}) +``` + +**Returns**: + +- `AsyncComplete` - Callable `complete()` function + +#### fail + +```python +@property +def fail() -> AsyncFail +``` + +`fail()` function for this request. Once a custom function's state is set to error, +its housing workflow will be interrupted and any provided error message will be passed +on to the end user through SlackBot. Additionally, any interactivity handlers associated +to a function invocation will no longer be invocable. + +```python +@app.function("reverse") +async def handle_button_clicks(ack, fail): + await ack() + await fail(error="something went wrong") + +@app.function("reverse") +async def handle_button_clicks(context): + await context.ack() + await context.fail(error="something went wrong") +``` + +**Returns**: + +- `AsyncFail` - Callable `fail()` function + +#### set\_title + +```python +@property +def set_title() -> Optional[AsyncSetTitle] +``` + +#### set\_status + +```python +@property +def set_status() -> Optional[AsyncSetStatus] +``` + +#### set\_suggested\_prompts + +```python +@property +def set_suggested_prompts() -> Optional[AsyncSetSuggestedPrompts] +``` + +#### get\_thread\_context + +```python +@property +def get_thread_context() -> Optional[AsyncGetThreadContext] +``` + +#### say\_stream + +```python +@property +def say_stream() -> Optional[AsyncSayStream] +``` + +#### save\_thread\_context + +```python +@property +def save_thread_context() -> Optional[AsyncSaveThreadContext] +``` diff --git a/docs/english/reference/context/base_context.md b/docs/english/reference/context/base_context.md new file mode 100644 index 000000000..23c9e084c --- /dev/null +++ b/docs/english/reference/context/base_context.md @@ -0,0 +1,222 @@ +--- +sidebar_label: base_context +title: slack_bolt.context.base_context +--- + +## BaseContext Objects + +```python +class BaseContext(dict) +``` + +Context object associated with a request from Slack. + +#### copyable\_standard\_property\_names + +#### non\_copyable\_standard\_property\_names + +#### standard\_property\_names + +#### logger + +```python +@property +def logger() -> Logger +``` + +The properly configured logger that is available for middleware/listeners. + +#### token + +```python +@property +def token() -> Optional[str] +``` + +The (bot/user) token resolved for this request. + +#### enterprise\_id + +```python +@property +def enterprise_id() -> Optional[str] +``` + +The Enterprise Grid Organization ID of this request. + +#### is\_enterprise\_install + +```python +@property +def is_enterprise_install() -> Optional[bool] +``` + +True if the request is associated with an Org-wide installation. + +#### team\_id + +```python +@property +def team_id() -> Optional[str] +``` + +The Workspace ID of this request. + +#### user\_id + +```python +@property +def user_id() -> Optional[str] +``` + +The user ID associated ith this request. + +#### actor\_enterprise\_id + +```python +@property +def actor_enterprise_id() -> Optional[str] +``` + +The action's actor's Enterprise Grid organization ID. +Note that this property is especially useful for handling events in Slack Connect channels. +That being said, it's not guaranteed to have a valid ID for all events due to server-side inconsistency. + +#### actor\_team\_id + +```python +@property +def actor_team_id() -> Optional[str] +``` + +The action's actor's workspace ID. +Note that this property is especially useful for handling events in Slack Connect channels. +That being said, it's not guaranteed to have a valid ID for all events due to server-side inconsistency. + +#### actor\_user\_id + +```python +@property +def actor_user_id() -> Optional[str] +``` + +The action's actor's user ID. +Note that this property is especially useful for handling events in Slack Connect channels. +That being said, it's not guaranteed to have a valid ID for all events due to server-side inconsistency. + +#### channel\_id + +```python +@property +def channel_id() -> Optional[str] +``` + +The conversation ID associated with this request. + +#### thread\_ts + +```python +@property +def thread_ts() -> Optional[str] +``` + +The conversation thread's ID associated with this request. + +#### response\_url + +```python +@property +def response_url() -> Optional[str] +``` + +The `response_url` associated with this request. + +#### matches + +```python +@property +def matches() -> Optional[Tuple] +``` + +Returns all the matched parts in message listener's regexp + +#### function\_execution\_id + +```python +@property +def function_execution_id() -> Optional[str] +``` + +The `function_execution_id` associated with this request. +Only available for `function_executed` and interactivity events scoped to a custom step. + +#### inputs + +```python +@property +def inputs() -> Optional[Dict[str, Any]] +``` + +The `inputs` associated with this request. +Only available for `function_executed` and interactivity events scoped to a custom step. + +#### authorize\_result + +```python +@property +def authorize_result() -> Optional[AuthorizeResult] +``` + +The authorize result resolved for this request. + +#### function\_bot\_access\_token + +```python +@property +def function_bot_access_token() -> Optional[str] +``` + +The bot token resolved for this function request. +Only available for `function_executed` and interactivity events scoped to a custom step. + +#### bot\_token + +```python +@property +def bot_token() -> Optional[str] +``` + +The bot token resolved for this request. + +#### bot\_id + +```python +@property +def bot_id() -> Optional[str] +``` + +The bot ID resolved for this request. + +#### bot\_user\_id + +```python +@property +def bot_user_id() -> Optional[str] +``` + +The bot user ID resolved for this request. + +#### user\_token + +```python +@property +def user_token() -> Optional[str] +``` + +The user token resolved for this request. + +#### set\_authorize\_result + +```python +def set_authorize_result(authorize_result: AuthorizeResult) +``` diff --git a/docs/english/reference/context/complete/async_complete.md b/docs/english/reference/context/complete/async_complete.md new file mode 100644 index 000000000..ee982f1ae --- /dev/null +++ b/docs/english/reference/context/complete/async_complete.md @@ -0,0 +1,32 @@ +--- +sidebar_label: async_complete +title: slack_bolt.context.complete.async_complete +--- + +## AsyncComplete Objects + +```python +class AsyncComplete() +``` + +#### client: `AsyncWebClient` + +#### function\_execution\_id: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__(client: AsyncWebClient, function_execution_id: Optional[str]) +``` + +#### has\_been\_called + +```python +def has_been_called() -> bool +``` + +Check if this complete function has been called. + +**Returns**: + +- `bool` - True if the complete function has been called, False otherwise. diff --git a/docs/english/reference/context/complete/complete.md b/docs/english/reference/context/complete/complete.md new file mode 100644 index 000000000..3660d34f0 --- /dev/null +++ b/docs/english/reference/context/complete/complete.md @@ -0,0 +1,33 @@ +--- +sidebar_label: complete +title: slack_bolt.context.complete.complete +slug: complete +--- + +## Complete Objects + +```python +class Complete() +``` + +#### client: `WebClient` + +#### function\_execution\_id: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__(client: WebClient, function_execution_id: Optional[str]) +``` + +#### has\_been\_called + +```python +def has_been_called() -> bool +``` + +Check if this complete function has been called. + +**Returns**: + +- `bool` - True if the complete function has been called, False otherwise. diff --git a/docs/english/reference/context/complete/index.md b/docs/english/reference/context/complete/index.md new file mode 100644 index 000000000..756072e10 --- /dev/null +++ b/docs/english/reference/context/complete/index.md @@ -0,0 +1,37 @@ +--- +sidebar_label: complete +title: slack_bolt.context.complete +--- + +## Submodules + +- [slack_bolt.context.complete.async_complete](/tools/bolt-python/reference/context/complete/async_complete) +- [slack_bolt.context.complete.complete](/tools/bolt-python/reference/context/complete/complete) + +## Complete Objects + +```python +class Complete() +``` + +#### client: `WebClient` + +#### function\_execution\_id: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__(client: WebClient, function_execution_id: Optional[str]) +``` + +#### has\_been\_called + +```python +def has_been_called() -> bool +``` + +Check if this complete function has been called. + +**Returns**: + +- `bool` - True if the complete function has been called, False otherwise. diff --git a/docs/english/reference/context/context.md b/docs/english/reference/context/context.md new file mode 100644 index 000000000..88807159b --- /dev/null +++ b/docs/english/reference/context/context.md @@ -0,0 +1,232 @@ +--- +sidebar_label: context +title: slack_bolt.context.context +slug: context +--- + +## BoltContext Objects + +```python +class BoltContext(BaseContext) +``` + +Context object associated with a request from Slack. + +#### to\_copyable + +```python +def to_copyable() -> BoltContext +``` + +#### listener\_runner + +```python +@property +def listener_runner() -> ThreadListenerRunner +``` + +The properly configured listener_runner that is available for middleware/listeners. + +#### client + +```python +@property +def client() -> WebClient +``` + +The `WebClient` instance available for this request. + +```python +@app.event("app_mention") +def handle_events(context): + context.client.chat_postMessage( + channel=context.channel_id, + text="Thanks!", + ) + +# You can access "client" this way too. +@app.event("app_mention") +def handle_events(client, context): + client.chat_postMessage( + channel=context.channel_id, + text="Thanks!", + ) +``` + +**Returns**: + +- `WebClient` - `WebClient` instance + +#### ack + +```python +@property +def ack() -> Ack +``` + +`ack()` function for this request. + +```python +@app.action("button") +def handle_button_clicks(context): + context.ack() + +# You can access "ack" this way too. +@app.action("button") +def handle_button_clicks(ack): + ack() +``` + +**Returns**: + +- `Ack` - Callable `ack()` function + +#### say + +```python +@property +def say() -> Say +``` + +`say()` function for this request. + +```python +@app.action("button") +def handle_button_clicks(context): + context.ack() + context.say("Hi!") + +# You can access "ack" this way too. +@app.action("button") +def handle_button_clicks(ack, say): + ack() + say("Hi!") +``` + +**Returns**: + +- `Say` - Callable `say()` function + +#### respond + +```python +@property +def respond() -> Optional[Respond] +``` + +`respond()` function for this request. + +```python +@app.action("button") +def handle_button_clicks(context): + context.ack() + context.respond("Hi!") + +# You can access "ack" this way too. +@app.action("button") +def handle_button_clicks(ack, respond): + ack() + respond("Hi!") +``` + +**Returns**: + +- `Optional[Respond]` - Callable `respond()` function + +#### complete + +```python +@property +def complete() -> Complete +``` + +`complete()` function for this request. Once a custom function's state is set to complete, +any outputs the function returns will be passed along to the next step of its housing workflow, +or complete the workflow if the function is the last step in a workflow. Additionally, +any interactivity handlers associated to a function invocation will no longer be invocable. + +```python +@app.function("reverse") +def handle_button_clicks(ack, complete): + ack() + complete(outputs={"stringReverse":"olleh"}) + +@app.function("reverse") +def handle_button_clicks(context): + context.ack() + context.complete(outputs={"stringReverse":"olleh"}) +``` + +**Returns**: + +- `Complete` - Callable `complete()` function + +#### fail + +```python +@property +def fail() -> Fail +``` + +`fail()` function for this request. Once a custom function's state is set to error, +its housing workflow will be interrupted and any provided error message will be passed +on to the end user through SlackBot. Additionally, any interactivity handlers associated +to a function invocation will no longer be invocable. + +```python +@app.function("reverse") +def handle_button_clicks(ack, fail): + ack() + fail(error="something went wrong") + +@app.function("reverse") +def handle_button_clicks(context): + context.ack() + context.fail(error="something went wrong") +``` + +**Returns**: + +- `Fail` - Callable `fail()` function + +#### set\_title + +```python +@property +def set_title() -> Optional[SetTitle] +``` + +#### set\_status + +```python +@property +def set_status() -> Optional[SetStatus] +``` + +#### set\_suggested\_prompts + +```python +@property +def set_suggested_prompts() -> Optional[SetSuggestedPrompts] +``` + +#### get\_thread\_context + +```python +@property +def get_thread_context() -> Optional[GetThreadContext] +``` + +#### say\_stream + +```python +@property +def say_stream() -> Optional[SayStream] +``` + +#### save\_thread\_context + +```python +@property +def save_thread_context() -> Optional[SaveThreadContext] +``` diff --git a/docs/english/reference/context/fail/async_fail.md b/docs/english/reference/context/fail/async_fail.md new file mode 100644 index 000000000..8924e0a45 --- /dev/null +++ b/docs/english/reference/context/fail/async_fail.md @@ -0,0 +1,32 @@ +--- +sidebar_label: async_fail +title: slack_bolt.context.fail.async_fail +--- + +## AsyncFail Objects + +```python +class AsyncFail() +``` + +#### client: `AsyncWebClient` + +#### function\_execution\_id: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__(client: AsyncWebClient, function_execution_id: Optional[str]) +``` + +#### has\_been\_called + +```python +def has_been_called() -> bool +``` + +Check if this fail function has been called. + +**Returns**: + +- `bool` - True if the fail function has been called, False otherwise. diff --git a/docs/english/reference/context/fail/fail.md b/docs/english/reference/context/fail/fail.md new file mode 100644 index 000000000..6d0dcd169 --- /dev/null +++ b/docs/english/reference/context/fail/fail.md @@ -0,0 +1,33 @@ +--- +sidebar_label: fail +title: slack_bolt.context.fail.fail +slug: fail +--- + +## Fail Objects + +```python +class Fail() +``` + +#### client: `WebClient` + +#### function\_execution\_id: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__(client: WebClient, function_execution_id: Optional[str]) +``` + +#### has\_been\_called + +```python +def has_been_called() -> bool +``` + +Check if this fail function has been called. + +**Returns**: + +- `bool` - True if the fail function has been called, False otherwise. diff --git a/docs/english/reference/context/fail/index.md b/docs/english/reference/context/fail/index.md new file mode 100644 index 000000000..b09e7a710 --- /dev/null +++ b/docs/english/reference/context/fail/index.md @@ -0,0 +1,37 @@ +--- +sidebar_label: fail +title: slack_bolt.context.fail +--- + +## Submodules + +- [slack_bolt.context.fail.async_fail](/tools/bolt-python/reference/context/fail/async_fail) +- [slack_bolt.context.fail.fail](/tools/bolt-python/reference/context/fail/fail) + +## Fail Objects + +```python +class Fail() +``` + +#### client: `WebClient` + +#### function\_execution\_id: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__(client: WebClient, function_execution_id: Optional[str]) +``` + +#### has\_been\_called + +```python +def has_been_called() -> bool +``` + +Check if this fail function has been called. + +**Returns**: + +- `bool` - True if the fail function has been called, False otherwise. diff --git a/docs/english/reference/context/get_thread_context/async_get_thread_context.md b/docs/english/reference/context/get_thread_context/async_get_thread_context.md new file mode 100644 index 000000000..bcdf17dd6 --- /dev/null +++ b/docs/english/reference/context/get_thread_context/async_get_thread_context.md @@ -0,0 +1,30 @@ +--- +sidebar_label: async_get_thread_context +title: slack_bolt.context.get_thread_context.async_get_thread_context +--- + +## AsyncGetThreadContext Objects + +```python +class AsyncGetThreadContext() +``` + +#### thread\_context\_store: `AsyncAssistantThreadContextStore` + +#### payload: `dict` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### thread\_context\_loaded: `bool` + +#### \_\_init\_\_ + +```python +def __init__( + thread_context_store: AsyncAssistantThreadContextStore, + channel_id: str, + thread_ts: str, + payload: dict) +``` diff --git a/docs/english/reference/context/get_thread_context/get_thread_context.md b/docs/english/reference/context/get_thread_context/get_thread_context.md new file mode 100644 index 000000000..40c64f686 --- /dev/null +++ b/docs/english/reference/context/get_thread_context/get_thread_context.md @@ -0,0 +1,31 @@ +--- +sidebar_label: get_thread_context +title: slack_bolt.context.get_thread_context.get_thread_context +slug: get_thread_context +--- + +## GetThreadContext Objects + +```python +class GetThreadContext() +``` + +#### thread\_context\_store: `AssistantThreadContextStore` + +#### payload: `dict` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### thread\_context\_loaded: `bool` + +#### \_\_init\_\_ + +```python +def __init__( + thread_context_store: AssistantThreadContextStore, + channel_id: str, + thread_ts: str, + payload: dict) +``` diff --git a/docs/english/reference/context/get_thread_context/index.md b/docs/english/reference/context/get_thread_context/index.md new file mode 100644 index 000000000..8d5f92375 --- /dev/null +++ b/docs/english/reference/context/get_thread_context/index.md @@ -0,0 +1,35 @@ +--- +sidebar_label: get_thread_context +title: slack_bolt.context.get_thread_context +--- + +## Submodules + +- [slack_bolt.context.get_thread_context.async_get_thread_context](/tools/bolt-python/reference/context/get_thread_context/async_get_thread_context) +- [slack_bolt.context.get_thread_context.get_thread_context](/tools/bolt-python/reference/context/get_thread_context/get_thread_context) + +## GetThreadContext Objects + +```python +class GetThreadContext() +``` + +#### thread\_context\_store: `AssistantThreadContextStore` + +#### payload: `dict` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### thread\_context\_loaded: `bool` + +#### \_\_init\_\_ + +```python +def __init__( + thread_context_store: AssistantThreadContextStore, + channel_id: str, + thread_ts: str, + payload: dict) +``` diff --git a/docs/english/reference/context/index.md b/docs/english/reference/context/index.md new file mode 100644 index 000000000..40903b390 --- /dev/null +++ b/docs/english/reference/context/index.md @@ -0,0 +1,255 @@ +--- +sidebar_label: context +title: slack_bolt.context +--- + +All listeners have access to a context dictionary, which can be used to enrich events with additional information. +Bolt automatically attaches information that is included in the incoming event, +like `user_id`, `team_id`, `channel_id`, and `enterprise_id`. + +Refer to https://docs.slack.dev/tools/bolt-python/concepts/context for details. + +## Submodules + +- [slack_bolt.context.ack](/tools/bolt-python/reference/context/ack) +- [slack_bolt.context.assistant](/tools/bolt-python/reference/context/assistant) +- [slack_bolt.context.async_context](/tools/bolt-python/reference/context/async_context) +- [slack_bolt.context.base_context](/tools/bolt-python/reference/context/base_context) +- [slack_bolt.context.complete](/tools/bolt-python/reference/context/complete) +- [slack_bolt.context.context](/tools/bolt-python/reference/context/context) +- [slack_bolt.context.fail](/tools/bolt-python/reference/context/fail) +- [slack_bolt.context.get_thread_context](/tools/bolt-python/reference/context/get_thread_context) +- [slack_bolt.context.respond](/tools/bolt-python/reference/context/respond) +- [slack_bolt.context.save_thread_context](/tools/bolt-python/reference/context/save_thread_context) +- [slack_bolt.context.say](/tools/bolt-python/reference/context/say) +- [slack_bolt.context.say_stream](/tools/bolt-python/reference/context/say_stream) +- [slack_bolt.context.set_status](/tools/bolt-python/reference/context/set_status) +- [slack_bolt.context.set_suggested_prompts](/tools/bolt-python/reference/context/set_suggested_prompts) +- [slack_bolt.context.set_title](/tools/bolt-python/reference/context/set_title) + +## BoltContext Objects + +```python +class BoltContext(BaseContext) +``` + +Context object associated with a request from Slack. + +#### to\_copyable + +```python +def to_copyable() -> BoltContext +``` + +#### listener\_runner + +```python +@property +def listener_runner() -> ThreadListenerRunner +``` + +The properly configured listener_runner that is available for middleware/listeners. + +#### client + +```python +@property +def client() -> WebClient +``` + +The `WebClient` instance available for this request. + +```python +@app.event("app_mention") +def handle_events(context): + context.client.chat_postMessage( + channel=context.channel_id, + text="Thanks!", + ) + +# You can access "client" this way too. +@app.event("app_mention") +def handle_events(client, context): + client.chat_postMessage( + channel=context.channel_id, + text="Thanks!", + ) +``` + +**Returns**: + +- `WebClient` - `WebClient` instance + +#### ack + +```python +@property +def ack() -> Ack +``` + +`ack()` function for this request. + +```python +@app.action("button") +def handle_button_clicks(context): + context.ack() + +# You can access "ack" this way too. +@app.action("button") +def handle_button_clicks(ack): + ack() +``` + +**Returns**: + +- `Ack` - Callable `ack()` function + +#### say + +```python +@property +def say() -> Say +``` + +`say()` function for this request. + +```python +@app.action("button") +def handle_button_clicks(context): + context.ack() + context.say("Hi!") + +# You can access "ack" this way too. +@app.action("button") +def handle_button_clicks(ack, say): + ack() + say("Hi!") +``` + +**Returns**: + +- `Say` - Callable `say()` function + +#### respond + +```python +@property +def respond() -> Optional[Respond] +``` + +`respond()` function for this request. + +```python +@app.action("button") +def handle_button_clicks(context): + context.ack() + context.respond("Hi!") + +# You can access "ack" this way too. +@app.action("button") +def handle_button_clicks(ack, respond): + ack() + respond("Hi!") +``` + +**Returns**: + +- `Optional[Respond]` - Callable `respond()` function + +#### complete + +```python +@property +def complete() -> Complete +``` + +`complete()` function for this request. Once a custom function's state is set to complete, +any outputs the function returns will be passed along to the next step of its housing workflow, +or complete the workflow if the function is the last step in a workflow. Additionally, +any interactivity handlers associated to a function invocation will no longer be invocable. + +```python +@app.function("reverse") +def handle_button_clicks(ack, complete): + ack() + complete(outputs={"stringReverse":"olleh"}) + +@app.function("reverse") +def handle_button_clicks(context): + context.ack() + context.complete(outputs={"stringReverse":"olleh"}) +``` + +**Returns**: + +- `Complete` - Callable `complete()` function + +#### fail + +```python +@property +def fail() -> Fail +``` + +`fail()` function for this request. Once a custom function's state is set to error, +its housing workflow will be interrupted and any provided error message will be passed +on to the end user through SlackBot. Additionally, any interactivity handlers associated +to a function invocation will no longer be invocable. + +```python +@app.function("reverse") +def handle_button_clicks(ack, fail): + ack() + fail(error="something went wrong") + +@app.function("reverse") +def handle_button_clicks(context): + context.ack() + context.fail(error="something went wrong") +``` + +**Returns**: + +- `Fail` - Callable `fail()` function + +#### set\_title + +```python +@property +def set_title() -> Optional[SetTitle] +``` + +#### set\_status + +```python +@property +def set_status() -> Optional[SetStatus] +``` + +#### set\_suggested\_prompts + +```python +@property +def set_suggested_prompts() -> Optional[SetSuggestedPrompts] +``` + +#### get\_thread\_context + +```python +@property +def get_thread_context() -> Optional[GetThreadContext] +``` + +#### say\_stream + +```python +@property +def say_stream() -> Optional[SayStream] +``` + +#### save\_thread\_context + +```python +@property +def save_thread_context() -> Optional[SaveThreadContext] +``` diff --git a/docs/english/reference/context/respond/async_respond.md b/docs/english/reference/context/respond/async_respond.md new file mode 100644 index 000000000..606e33495 --- /dev/null +++ b/docs/english/reference/context/respond/async_respond.md @@ -0,0 +1,26 @@ +--- +sidebar_label: async_respond +title: slack_bolt.context.respond.async_respond +--- + +## AsyncRespond Objects + +```python +class AsyncRespond() +``` + +#### response\_url: `Optional[str]` + +#### proxy: `Optional[str]` + +#### ssl: `Optional[SSLContext]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + response_url: Optional[str], + proxy: Optional[str] = None, + ssl: Optional[SSLContext] = None) +``` diff --git a/docs/english/reference/context/respond/index.md b/docs/english/reference/context/respond/index.md new file mode 100644 index 000000000..e6d911a31 --- /dev/null +++ b/docs/english/reference/context/respond/index.md @@ -0,0 +1,32 @@ +--- +sidebar_label: respond +title: slack_bolt.context.respond +--- + +## Submodules + +- [slack_bolt.context.respond.async_respond](/tools/bolt-python/reference/context/respond/async_respond) +- [slack_bolt.context.respond.internals](/tools/bolt-python/reference/context/respond/internals) +- [slack_bolt.context.respond.respond](/tools/bolt-python/reference/context/respond/respond) + +## Respond Objects + +```python +class Respond() +``` + +#### response\_url: `Optional[str]` + +#### proxy: `Optional[str]` + +#### ssl: `Optional[SSLContext]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + response_url: Optional[str], + proxy: Optional[str] = None, + ssl: Optional[SSLContext] = None) +``` diff --git a/docs/english/reference/context/respond/internals.md b/docs/english/reference/context/respond/internals.md new file mode 100644 index 000000000..eaa36e4cc --- /dev/null +++ b/docs/english/reference/context/respond/internals.md @@ -0,0 +1,6 @@ +--- +sidebar_label: internals +title: slack_bolt.context.respond.internals +--- + + diff --git a/docs/english/reference/context/respond/respond.md b/docs/english/reference/context/respond/respond.md new file mode 100644 index 000000000..b210c12a2 --- /dev/null +++ b/docs/english/reference/context/respond/respond.md @@ -0,0 +1,27 @@ +--- +sidebar_label: respond +title: slack_bolt.context.respond.respond +slug: respond +--- + +## Respond Objects + +```python +class Respond() +``` + +#### response\_url: `Optional[str]` + +#### proxy: `Optional[str]` + +#### ssl: `Optional[SSLContext]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + response_url: Optional[str], + proxy: Optional[str] = None, + ssl: Optional[SSLContext] = None) +``` diff --git a/docs/english/reference/context/save_thread_context/async_save_thread_context.md b/docs/english/reference/context/save_thread_context/async_save_thread_context.md new file mode 100644 index 000000000..43694625e --- /dev/null +++ b/docs/english/reference/context/save_thread_context/async_save_thread_context.md @@ -0,0 +1,25 @@ +--- +sidebar_label: async_save_thread_context +title: slack_bolt.context.save_thread_context.async_save_thread_context +--- + +## AsyncSaveThreadContext Objects + +```python +class AsyncSaveThreadContext() +``` + +#### thread\_context\_store: `AsyncAssistantThreadContextStore` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### \_\_init\_\_ + +```python +def __init__( + thread_context_store: AsyncAssistantThreadContextStore, + channel_id: str, + thread_ts: str) +``` diff --git a/docs/english/reference/context/save_thread_context/index.md b/docs/english/reference/context/save_thread_context/index.md new file mode 100644 index 000000000..8410a7db8 --- /dev/null +++ b/docs/english/reference/context/save_thread_context/index.md @@ -0,0 +1,30 @@ +--- +sidebar_label: save_thread_context +title: slack_bolt.context.save_thread_context +--- + +## Submodules + +- [slack_bolt.context.save_thread_context.async_save_thread_context](/tools/bolt-python/reference/context/save_thread_context/async_save_thread_context) +- [slack_bolt.context.save_thread_context.save_thread_context](/tools/bolt-python/reference/context/save_thread_context/save_thread_context) + +## SaveThreadContext Objects + +```python +class SaveThreadContext() +``` + +#### thread\_context\_store: `AssistantThreadContextStore` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### \_\_init\_\_ + +```python +def __init__( + thread_context_store: AssistantThreadContextStore, + channel_id: str, + thread_ts: str) +``` diff --git a/docs/english/reference/context/save_thread_context/save_thread_context.md b/docs/english/reference/context/save_thread_context/save_thread_context.md new file mode 100644 index 000000000..3223b355a --- /dev/null +++ b/docs/english/reference/context/save_thread_context/save_thread_context.md @@ -0,0 +1,26 @@ +--- +sidebar_label: save_thread_context +title: slack_bolt.context.save_thread_context.save_thread_context +slug: save_thread_context +--- + +## SaveThreadContext Objects + +```python +class SaveThreadContext() +``` + +#### thread\_context\_store: `AssistantThreadContextStore` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### \_\_init\_\_ + +```python +def __init__( + thread_context_store: AssistantThreadContextStore, + channel_id: str, + thread_ts: str) +``` diff --git a/docs/english/reference/context/say/async_say.md b/docs/english/reference/context/say/async_say.md new file mode 100644 index 000000000..9d461bcb8 --- /dev/null +++ b/docs/english/reference/context/say/async_say.md @@ -0,0 +1,28 @@ +--- +sidebar_label: async_say +title: slack_bolt.context.say.async_say +--- + +## AsyncSay Objects + +```python +class AsyncSay() +``` + +#### client: `Optional[AsyncWebClient]` + +#### channel: `Optional[str]` + +#### thread\_ts: `Optional[str]` + +#### build\_metadata: `Optional[Callable[[], Awaitable[Union[Dict, Metadata]]]]` + +#### \_\_init\_\_ + +```python +def __init__( + client: Optional[AsyncWebClient], + channel: Optional[str], + thread_ts: Optional[str] = None, + build_metadata: Optional[Callable[[], Awaitable[Union[Dict, Metadata]]]] = None) +``` diff --git a/docs/english/reference/context/say/index.md b/docs/english/reference/context/say/index.md new file mode 100644 index 000000000..ee6f647d8 --- /dev/null +++ b/docs/english/reference/context/say/index.md @@ -0,0 +1,37 @@ +--- +sidebar_label: say +title: slack_bolt.context.say +--- + +## Submodules + +- [slack_bolt.context.say.async_say](/tools/bolt-python/reference/context/say/async_say) +- [slack_bolt.context.say.internals](/tools/bolt-python/reference/context/say/internals) +- [slack_bolt.context.say.say](/tools/bolt-python/reference/context/say/say) + +## Say Objects + +```python +class Say() +``` + +#### client: `Optional[WebClient]` + +#### channel: `Optional[str]` + +#### thread\_ts: `Optional[str]` + +#### metadata: `Optional[Union[Dict, Metadata]]` + +#### build\_metadata: `Optional[Callable[[], Optional[Union[Dict, Metadata]]]]` + +#### \_\_init\_\_ + +```python +def __init__( + client: Optional[WebClient], + channel: Optional[str], + thread_ts: Optional[str] = None, + metadata: Optional[Union[Dict, Metadata]] = None, + build_metadata: Optional[Callable[[], Optional[Union[Dict, Metadata]]]] = None) +``` diff --git a/docs/english/reference/context/say/internals.md b/docs/english/reference/context/say/internals.md new file mode 100644 index 000000000..e24d49447 --- /dev/null +++ b/docs/english/reference/context/say/internals.md @@ -0,0 +1,6 @@ +--- +sidebar_label: internals +title: slack_bolt.context.say.internals +--- + + diff --git a/docs/english/reference/context/say/say.md b/docs/english/reference/context/say/say.md new file mode 100644 index 000000000..8bbaddd9b --- /dev/null +++ b/docs/english/reference/context/say/say.md @@ -0,0 +1,32 @@ +--- +sidebar_label: say +title: slack_bolt.context.say.say +slug: say +--- + +## Say Objects + +```python +class Say() +``` + +#### client: `Optional[WebClient]` + +#### channel: `Optional[str]` + +#### thread\_ts: `Optional[str]` + +#### metadata: `Optional[Union[Dict, Metadata]]` + +#### build\_metadata: `Optional[Callable[[], Optional[Union[Dict, Metadata]]]]` + +#### \_\_init\_\_ + +```python +def __init__( + client: Optional[WebClient], + channel: Optional[str], + thread_ts: Optional[str] = None, + metadata: Optional[Union[Dict, Metadata]] = None, + build_metadata: Optional[Callable[[], Optional[Union[Dict, Metadata]]]] = None) +``` diff --git a/docs/english/reference/context/say_stream/async_say_stream.md b/docs/english/reference/context/say_stream/async_say_stream.md new file mode 100644 index 000000000..f6c4954b6 --- /dev/null +++ b/docs/english/reference/context/say_stream/async_say_stream.md @@ -0,0 +1,32 @@ +--- +sidebar_label: async_say_stream +title: slack_bolt.context.say_stream.async_say_stream +--- + +## AsyncSayStream Objects + +```python +class AsyncSayStream() +``` + +#### client: `AsyncWebClient` + +#### channel: `Optional[str]` + +#### recipient\_team\_id: `Optional[str]` + +#### recipient\_user\_id: `Optional[str]` + +#### thread\_ts: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + client: AsyncWebClient, + channel: Optional[str] = None, + recipient_team_id: Optional[str] = None, + recipient_user_id: Optional[str] = None, + thread_ts: Optional[str] = None) +``` diff --git a/docs/english/reference/context/say_stream/index.md b/docs/english/reference/context/say_stream/index.md new file mode 100644 index 000000000..aed711da9 --- /dev/null +++ b/docs/english/reference/context/say_stream/index.md @@ -0,0 +1,37 @@ +--- +sidebar_label: say_stream +title: slack_bolt.context.say_stream +--- + +## Submodules + +- [slack_bolt.context.say_stream.async_say_stream](/tools/bolt-python/reference/context/say_stream/async_say_stream) +- [slack_bolt.context.say_stream.say_stream](/tools/bolt-python/reference/context/say_stream/say_stream) + +## SayStream Objects + +```python +class SayStream() +``` + +#### client: `WebClient` + +#### channel: `Optional[str]` + +#### recipient\_team\_id: `Optional[str]` + +#### recipient\_user\_id: `Optional[str]` + +#### thread\_ts: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + client: WebClient, + channel: Optional[str] = None, + recipient_team_id: Optional[str] = None, + recipient_user_id: Optional[str] = None, + thread_ts: Optional[str] = None) +``` diff --git a/docs/english/reference/context/say_stream/say_stream.md b/docs/english/reference/context/say_stream/say_stream.md new file mode 100644 index 000000000..e78c8394f --- /dev/null +++ b/docs/english/reference/context/say_stream/say_stream.md @@ -0,0 +1,33 @@ +--- +sidebar_label: say_stream +title: slack_bolt.context.say_stream.say_stream +slug: say_stream +--- + +## SayStream Objects + +```python +class SayStream() +``` + +#### client: `WebClient` + +#### channel: `Optional[str]` + +#### recipient\_team\_id: `Optional[str]` + +#### recipient\_user\_id: `Optional[str]` + +#### thread\_ts: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + client: WebClient, + channel: Optional[str] = None, + recipient_team_id: Optional[str] = None, + recipient_user_id: Optional[str] = None, + thread_ts: Optional[str] = None) +``` diff --git a/docs/english/reference/context/set_status/async_set_status.md b/docs/english/reference/context/set_status/async_set_status.md new file mode 100644 index 000000000..5886090d5 --- /dev/null +++ b/docs/english/reference/context/set_status/async_set_status.md @@ -0,0 +1,22 @@ +--- +sidebar_label: async_set_status +title: slack_bolt.context.set_status.async_set_status +--- + +## AsyncSetStatus Objects + +```python +class AsyncSetStatus() +``` + +#### client: `AsyncWebClient` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### \_\_init\_\_ + +```python +def __init__(client: AsyncWebClient, channel_id: str, thread_ts: str) +``` diff --git a/docs/english/reference/context/set_status/index.md b/docs/english/reference/context/set_status/index.md new file mode 100644 index 000000000..e6df8ffee --- /dev/null +++ b/docs/english/reference/context/set_status/index.md @@ -0,0 +1,27 @@ +--- +sidebar_label: set_status +title: slack_bolt.context.set_status +--- + +## Submodules + +- [slack_bolt.context.set_status.async_set_status](/tools/bolt-python/reference/context/set_status/async_set_status) +- [slack_bolt.context.set_status.set_status](/tools/bolt-python/reference/context/set_status/set_status) + +## SetStatus Objects + +```python +class SetStatus() +``` + +#### client: `WebClient` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### \_\_init\_\_ + +```python +def __init__(client: WebClient, channel_id: str, thread_ts: str) +``` diff --git a/docs/english/reference/context/set_status/set_status.md b/docs/english/reference/context/set_status/set_status.md new file mode 100644 index 000000000..70308efbd --- /dev/null +++ b/docs/english/reference/context/set_status/set_status.md @@ -0,0 +1,23 @@ +--- +sidebar_label: set_status +title: slack_bolt.context.set_status.set_status +slug: set_status +--- + +## SetStatus Objects + +```python +class SetStatus() +``` + +#### client: `WebClient` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### \_\_init\_\_ + +```python +def __init__(client: WebClient, channel_id: str, thread_ts: str) +``` diff --git a/docs/english/reference/context/set_suggested_prompts/async_set_suggested_prompts.md b/docs/english/reference/context/set_suggested_prompts/async_set_suggested_prompts.md new file mode 100644 index 000000000..061926f3c --- /dev/null +++ b/docs/english/reference/context/set_suggested_prompts/async_set_suggested_prompts.md @@ -0,0 +1,22 @@ +--- +sidebar_label: async_set_suggested_prompts +title: slack_bolt.context.set_suggested_prompts.async_set_suggested_prompts +--- + +## AsyncSetSuggestedPrompts Objects + +```python +class AsyncSetSuggestedPrompts() +``` + +#### client: `AsyncWebClient` + +#### channel\_id: `str` + +#### thread\_ts: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__(client: AsyncWebClient, channel_id: str, thread_ts: Optional[str] = None) +``` diff --git a/docs/english/reference/context/set_suggested_prompts/index.md b/docs/english/reference/context/set_suggested_prompts/index.md new file mode 100644 index 000000000..860d92c11 --- /dev/null +++ b/docs/english/reference/context/set_suggested_prompts/index.md @@ -0,0 +1,27 @@ +--- +sidebar_label: set_suggested_prompts +title: slack_bolt.context.set_suggested_prompts +--- + +## Submodules + +- [slack_bolt.context.set_suggested_prompts.async_set_suggested_prompts](/tools/bolt-python/reference/context/set_suggested_prompts/async_set_suggested_prompts) +- [slack_bolt.context.set_suggested_prompts.set_suggested_prompts](/tools/bolt-python/reference/context/set_suggested_prompts/set_suggested_prompts) + +## SetSuggestedPrompts Objects + +```python +class SetSuggestedPrompts() +``` + +#### client: `WebClient` + +#### channel\_id: `str` + +#### thread\_ts: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__(client: WebClient, channel_id: str, thread_ts: Optional[str] = None) +``` diff --git a/docs/english/reference/context/set_suggested_prompts/set_suggested_prompts.md b/docs/english/reference/context/set_suggested_prompts/set_suggested_prompts.md new file mode 100644 index 000000000..d8ea84fea --- /dev/null +++ b/docs/english/reference/context/set_suggested_prompts/set_suggested_prompts.md @@ -0,0 +1,23 @@ +--- +sidebar_label: set_suggested_prompts +title: slack_bolt.context.set_suggested_prompts.set_suggested_prompts +slug: set_suggested_prompts +--- + +## SetSuggestedPrompts Objects + +```python +class SetSuggestedPrompts() +``` + +#### client: `WebClient` + +#### channel\_id: `str` + +#### thread\_ts: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__(client: WebClient, channel_id: str, thread_ts: Optional[str] = None) +``` diff --git a/docs/english/reference/context/set_title/async_set_title.md b/docs/english/reference/context/set_title/async_set_title.md new file mode 100644 index 000000000..2b3fa124a --- /dev/null +++ b/docs/english/reference/context/set_title/async_set_title.md @@ -0,0 +1,22 @@ +--- +sidebar_label: async_set_title +title: slack_bolt.context.set_title.async_set_title +--- + +## AsyncSetTitle Objects + +```python +class AsyncSetTitle() +``` + +#### client: `AsyncWebClient` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### \_\_init\_\_ + +```python +def __init__(client: AsyncWebClient, channel_id: str, thread_ts: str) +``` diff --git a/docs/english/reference/context/set_title/index.md b/docs/english/reference/context/set_title/index.md new file mode 100644 index 000000000..56b593c75 --- /dev/null +++ b/docs/english/reference/context/set_title/index.md @@ -0,0 +1,27 @@ +--- +sidebar_label: set_title +title: slack_bolt.context.set_title +--- + +## Submodules + +- [slack_bolt.context.set_title.async_set_title](/tools/bolt-python/reference/context/set_title/async_set_title) +- [slack_bolt.context.set_title.set_title](/tools/bolt-python/reference/context/set_title/set_title) + +## SetTitle Objects + +```python +class SetTitle() +``` + +#### client: `WebClient` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### \_\_init\_\_ + +```python +def __init__(client: WebClient, channel_id: str, thread_ts: str) +``` diff --git a/docs/english/reference/context/set_title/set_title.md b/docs/english/reference/context/set_title/set_title.md new file mode 100644 index 000000000..a749267b2 --- /dev/null +++ b/docs/english/reference/context/set_title/set_title.md @@ -0,0 +1,23 @@ +--- +sidebar_label: set_title +title: slack_bolt.context.set_title.set_title +slug: set_title +--- + +## SetTitle Objects + +```python +class SetTitle() +``` + +#### client: `WebClient` + +#### channel\_id: `str` + +#### thread\_ts: `str` + +#### \_\_init\_\_ + +```python +def __init__(client: WebClient, channel_id: str, thread_ts: str) +``` diff --git a/docs/english/reference/error/index.md b/docs/english/reference/error/index.md new file mode 100644 index 000000000..b3e61790b --- /dev/null +++ b/docs/english/reference/error/index.md @@ -0,0 +1,38 @@ +--- +sidebar_label: error +title: slack_bolt.error +--- + +Bolt specific error types. + +## BoltError Objects + +```python +class BoltError(Exception) +``` + +General class in a Bolt app + +## BoltUnhandledRequestError Objects + +```python +class BoltUnhandledRequestError(BoltError) +``` + +#### request: `BoltRequest` + +#### body: `dict` + +#### current\_response: `Optional[BoltResponse]` + +#### last\_global\_middleware\_name: `Optional[str]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + request: Union[BoltRequest, AsyncBoltRequest], + current_response: Optional[BoltResponse], + last_global_middleware_name: Optional[str] = None) +``` diff --git a/docs/english/reference/index.md b/docs/english/reference/index.md new file mode 100644 index 000000000..457e88573 --- /dev/null +++ b/docs/english/reference/index.md @@ -0,0 +1,314 @@ +--- +sidebar_label: slack_bolt +title: slack_bolt +--- + +A Python framework to build Slack apps in a flash with the latest platform features. Read the [getting started guide](https://docs.slack.dev/tools/bolt-python/creating-an-app) and look at our [code examples](https://github.com/slackapi/bolt-python/tree/main/examples) to learn how to build apps using Bolt. + +* Website: https://docs.slack.dev/tools/bolt-python/ +* GitHub repository: https://github.com/slackapi/bolt-python +* The class representing a Bolt app: `slack_bolt.app.app` + +## Submodules + +- [slack_bolt.adapter](/tools/bolt-python/reference/adapter) +- [slack_bolt.app](/tools/bolt-python/reference/app) +- [slack_bolt.async_app](/tools/bolt-python/reference/async_app) +- [slack_bolt.authorization](/tools/bolt-python/reference/authorization) +- [slack_bolt.context](/tools/bolt-python/reference/context) +- [slack_bolt.error](/tools/bolt-python/reference/error) +- [slack_bolt.kwargs_injection](/tools/bolt-python/reference/kwargs_injection) +- [slack_bolt.lazy_listener](/tools/bolt-python/reference/lazy_listener) +- [slack_bolt.listener](/tools/bolt-python/reference/listener) +- [slack_bolt.listener_matcher](/tools/bolt-python/reference/listener_matcher) +- [slack_bolt.logger](/tools/bolt-python/reference/logger) +- [slack_bolt.middleware](/tools/bolt-python/reference/middleware) +- [slack_bolt.oauth](/tools/bolt-python/reference/oauth) +- [slack_bolt.request](/tools/bolt-python/reference/request) +- [slack_bolt.response](/tools/bolt-python/reference/response) +- [slack_bolt.util](/tools/bolt-python/reference/util) +- [slack_bolt.version](/tools/bolt-python/reference/version) +- [slack_bolt.workflows](/tools/bolt-python/reference/workflows) + +## App Objects + +```python +class App() +``` + +## BoltContext Objects + +```python +class BoltContext(BaseContext) +``` + +Context object associated with a request from Slack. + +## Ack Objects + +```python +class Ack() +``` + +## Complete Objects + +```python +class Complete() +``` + +## Fail Objects + +```python +class Fail() +``` + +## Respond Objects + +```python +class Respond() +``` + +## Say Objects + +```python +class Say() +``` + +## SayStream Objects + +```python +class SayStream() +``` + +## Args Objects + +```python +class Args() +``` + +All the arguments in this class are available in any middleware / listeners. +You can inject the named variables in the argument list in arbitrary order. + +```python +@app.action("link_button") +def handle_buttons(ack, respond, logger, context, body, client): + logger.info(f"request body: {body}") + ack() + if context.channel_id is not None: + respond("Hi!") + client.views_open( + trigger_id=body["trigger_id"], + view={ ... } + ) +``` + +Alternatively, you can include a parameter named `args` and it will be injected with an instance of this class. + +```python +@app.action("link_button") +def handle_buttons(args): + args.logger.info(f"request body: {args.body}") + args.ack() + if args.context.channel_id is not None: + args.respond("Hi!") + args.client.views_open( + trigger_id=args.body["trigger_id"], + view={ ... } + ) +``` + +## Listener Objects + +```python +class Listener() +``` + +## CustomListenerMatcher Objects + +```python +class CustomListenerMatcher(ListenerMatcher) +``` + +## BoltRequest Objects + +```python +class BoltRequest() +``` + +## BoltResponse Objects + +```python +class BoltResponse() +``` + +## Assistant Objects + +```python +class Assistant(Middleware) +``` + +#### thread\_context\_store: `Optional[AssistantThreadContextStore]` + +#### base\_logger: `Optional[logging.Logger]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str = 'assistant', + thread_context_store: Optional[AssistantThreadContextStore] = None, + logger: Optional[logging.Logger] = None) +``` + +#### thread\_started + +```python +def thread_started( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### user\_message + +```python +def user_message( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### bot\_message + +```python +def bot_message( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### thread\_context\_changed + +```python +def thread_context_changed( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### default\_thread\_context\_changed + +```python +def default_thread_context_changed( + save_thread_context: SaveThreadContext, + payload: dict) +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> Optional[BoltResponse] +``` + +#### build\_listener + +```python +def build_listener( + listener_or_functions: Union[Listener, Callable, List[Callable]], + matchers: Optional[List[Union[ListenerMatcher, Callable[..., bool]]]] = None, + middleware: Optional[List[Middleware]] = None, + base_logger: Optional[Logger] = None) -> Listener +``` + +## AssistantThreadContext Objects + +```python +class AssistantThreadContext(dict) +``` + +#### enterprise\_id: `Optional[str]` + +#### team\_id: `Optional[str]` + +#### channel\_id: `str` + +#### \_\_init\_\_ + +```python +def __init__(payload: dict) +``` + +## AssistantThreadContextStore Objects + +```python +class AssistantThreadContextStore() +``` + +#### save + +```python +def save(*, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None +``` + +#### find + +```python +def find(*, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext] +``` + +## FileAssistantThreadContextStore Objects + +```python +class FileAssistantThreadContextStore(AssistantThreadContextStore) +``` + +#### \_\_init\_\_ + +```python +def __init__(base_dir: str = str(Path.home()) + '/.bolt-app-assistant-thread-contexts') +``` + +#### save + +```python +def save(*, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None +``` + +#### find + +```python +def find(*, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext] +``` + +## SetStatus Objects + +```python +class SetStatus() +``` + +## SetTitle Objects + +```python +class SetTitle() +``` + +## SetSuggestedPrompts Objects + +```python +class SetSuggestedPrompts() +``` + +## SaveThreadContext Objects + +```python +class SaveThreadContext() +``` diff --git a/docs/english/reference/kwargs_injection/args.md b/docs/english/reference/kwargs_injection/args.md new file mode 100644 index 000000000..d846c62de --- /dev/null +++ b/docs/english/reference/kwargs_injection/args.md @@ -0,0 +1,191 @@ +--- +sidebar_label: args +title: slack_bolt.kwargs_injection.args +--- + +## Args Objects + +```python +class Args() +``` + +All the arguments in this class are available in any middleware / listeners. +You can inject the named variables in the argument list in arbitrary order. + +```python +@app.action("link_button") +def handle_buttons(ack, respond, logger, context, body, client): + logger.info(f"request body: {body}") + ack() + if context.channel_id is not None: + respond("Hi!") + client.views_open( + trigger_id=body["trigger_id"], + view={ ... } + ) +``` + +Alternatively, you can include a parameter named `args` and it will be injected with an instance of this class. + +```python +@app.action("link_button") +def handle_buttons(args): + args.logger.info(f"request body: {args.body}") + args.ack() + if args.context.channel_id is not None: + args.respond("Hi!") + args.client.views_open( + trigger_id=args.body["trigger_id"], + view={ ... } + ) +``` + +#### client: `WebClient` + +`slack_sdk.web.WebClient` instance with a valid token + +#### logger: `logging.Logger` + +Logger instance + +#### req: `BoltRequest` + +Incoming request from Slack + +#### resp: `BoltResponse` + +Response representation + +#### request: `BoltRequest` + +Incoming request from Slack + +#### response: `BoltResponse` + +Response representation + +#### context: `BoltContext` + +Context data associated with the incoming request + +#### body: `Dict[str, Any]` + +Parsed request body data + +#### payload: `Dict[str, Any]` + +The unwrapped core data in the request body + +#### options: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.options` listener + +#### shortcut: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.shortcut` listener + +#### action: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.action` listener + +#### view: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.view` listener + +#### command: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.command` listener + +#### event: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.event` listener + +#### message: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.message` listener + +#### ack: `Ack` + +`ack()` utility function, which returns acknowledgement to the Slack servers + +#### say: `Say` + +`say()` utility function, which calls `chat.postMessage` API with the associated channel ID + +#### respond: `Respond` + +`respond()` utility function, which utilizes the associated `response_url` + +#### complete: `Complete` + +`complete()` utility function, signals a successful completion of the custom function + +#### fail: `Fail` + +`fail()` utility function, signal that the custom function failed to complete + +#### set\_status: `Optional[SetStatus]` + +`set_status()` utility function for AI Agents & Assistants + +#### set\_title: `Optional[SetTitle]` + +`set_title()` utility function for AI Agents & Assistants + +#### set\_suggested\_prompts: `Optional[SetSuggestedPrompts]` + +`set_suggested_prompts()` utility function for AI Agents & Assistants + +#### get\_thread\_context: `Optional[GetThreadContext]` + +`get_thread_context()` utility function for AI Agents & Assistants + +#### save\_thread\_context: `Optional[SaveThreadContext]` + +`save_thread_context()` utility function for AI Agents & Assistants + +#### say\_stream: `Optional[SayStream]` + +`say_stream()` utility function for conversations, AI Agents & Assistants + +#### next: `Callable[[], None]` + +`next()` utility function, which tells the middleware chain that it can continue with the next one + +#### next\_: `Callable[[], None]` + +An alias of `next()` for avoiding the Python built-in method overrides in middleware functions + +#### \_\_init\_\_ + +```python +def __init__( + *, + logger: logging.Logger, + client: WebClient, + req: BoltRequest, + resp: BoltResponse, + context: BoltContext, + body: Dict[str, Any], + payload: Dict[str, Any], + options: Optional[Dict[str, Any]] = None, + shortcut: Optional[Dict[str, Any]] = None, + action: Optional[Dict[str, Any]] = None, + view: Optional[Dict[str, Any]] = None, + command: Optional[Dict[str, Any]] = None, + event: Optional[Dict[str, Any]] = None, + message: Optional[Dict[str, Any]] = None, + ack: Ack, + say: Say, + respond: Respond, + complete: Complete, + fail: Fail, + set_status: Optional[SetStatus] = None, + set_title: Optional[SetTitle] = None, + set_suggested_prompts: Optional[SetSuggestedPrompts] = None, + get_thread_context: Optional[GetThreadContext] = None, + save_thread_context: Optional[SaveThreadContext] = None, + say_stream: Optional[SayStream] = None, + next: Callable[[], None], + **kwargs) +``` diff --git a/docs/english/reference/kwargs_injection/async_args.md b/docs/english/reference/kwargs_injection/async_args.md new file mode 100644 index 000000000..db51e72da --- /dev/null +++ b/docs/english/reference/kwargs_injection/async_args.md @@ -0,0 +1,191 @@ +--- +sidebar_label: async_args +title: slack_bolt.kwargs_injection.async_args +--- + +## AsyncArgs Objects + +```python +class AsyncArgs() +``` + +All the arguments in this class are available in any middleware / listeners. +You can inject the named variables in the argument list in arbitrary order. + +```python +@app.action("link_button") +async def handle_buttons(ack, respond, logger, context, body, client): + logger.info(f"request body: {body}") + await ack() + if context.channel_id is not None: + await respond("Hi!") + await client.views_open( + trigger_id=body["trigger_id"], + view={ ... } + ) +``` + +Alternatively, you can include a parameter named `args` and it will be injected with an instance of this class. + +```python +@app.action("link_button") +async def handle_buttons(args): + args.logger.info(f"request body: {args.body}") + await args.ack() + if args.context.channel_id is not None: + await args.respond("Hi!") + await args.client.views_open( + trigger_id=args.body["trigger_id"], + view={ ... } + ) +``` + +#### logger: `Logger` + +Logger instance + +#### client: `AsyncWebClient` + +`slack_sdk.web.async_client.AsyncWebClient` instance with a valid token + +#### req: `AsyncBoltRequest` + +Incoming request from Slack + +#### resp: `BoltResponse` + +Response representation + +#### request: `AsyncBoltRequest` + +Incoming request from Slack + +#### response: `BoltResponse` + +Response representation + +#### context: `AsyncBoltContext` + +Context data associated with the incoming request + +#### body: `Dict[str, Any]` + +Parsed request body data + +#### payload: `Dict[str, Any]` + +The unwrapped core data in the request body + +#### options: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.options` listener + +#### shortcut: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.shortcut` listener + +#### action: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.action` listener + +#### view: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.view` listener + +#### command: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.command` listener + +#### event: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.event` listener + +#### message: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.message` listener + +#### ack: `AsyncAck` + +`ack()` utility function, which returns acknowledgement to the Slack servers + +#### say: `AsyncSay` + +`say()` utility function, which calls chat.postMessage API with the associated channel ID + +#### respond: `AsyncRespond` + +`respond()` utility function, which utilizes the associated `response_url` + +#### complete: `AsyncComplete` + +`complete()` utility function, signals a successful completion of the custom function + +#### fail: `AsyncFail` + +`fail()` utility function, signal that the custom function failed to complete + +#### set\_status: `Optional[AsyncSetStatus]` + +`set_status()` utility function for AI Agents & Assistants + +#### set\_title: `Optional[AsyncSetTitle]` + +`set_title()` utility function for AI Agents & Assistants + +#### set\_suggested\_prompts: `Optional[AsyncSetSuggestedPrompts]` + +`set_suggested_prompts()` utility function for AI Agents & Assistants + +#### get\_thread\_context: `Optional[AsyncGetThreadContext]` + +`get_thread_context()` utility function for AI Agents & Assistants + +#### save\_thread\_context: `Optional[AsyncSaveThreadContext]` + +`save_thread_context()` utility function for AI Agents & Assistants + +#### say\_stream: `Optional[AsyncSayStream]` + +`say_stream()` utility function for AI Agents & Assistants + +#### next: `Callable[[], Awaitable[None]]` + +`next()` utility function, which tells the middleware chain that it can continue with the next one + +#### next\_: `Callable[[], Awaitable[None]]` + +An alias of `next()` for avoiding the Python built-in method overrides in middleware functions + +#### \_\_init\_\_ + +```python +def __init__( + *, + logger: Logger, + client: AsyncWebClient, + req: AsyncBoltRequest, + resp: BoltResponse, + context: AsyncBoltContext, + body: Dict[str, Any], + payload: Dict[str, Any], + options: Optional[Dict[str, Any]] = None, + shortcut: Optional[Dict[str, Any]] = None, + action: Optional[Dict[str, Any]] = None, + view: Optional[Dict[str, Any]] = None, + command: Optional[Dict[str, Any]] = None, + event: Optional[Dict[str, Any]] = None, + message: Optional[Dict[str, Any]] = None, + ack: AsyncAck, + say: AsyncSay, + respond: AsyncRespond, + complete: AsyncComplete, + fail: AsyncFail, + set_status: Optional[AsyncSetStatus] = None, + set_title: Optional[AsyncSetTitle] = None, + set_suggested_prompts: Optional[AsyncSetSuggestedPrompts] = None, + get_thread_context: Optional[AsyncGetThreadContext] = None, + save_thread_context: Optional[AsyncSaveThreadContext] = None, + say_stream: Optional[AsyncSayStream] = None, + next: Callable[[], Awaitable[None]], + **kwargs) +``` diff --git a/docs/english/reference/kwargs_injection/async_utils.md b/docs/english/reference/kwargs_injection/async_utils.md new file mode 100644 index 000000000..a1a772abf --- /dev/null +++ b/docs/english/reference/kwargs_injection/async_utils.md @@ -0,0 +1,19 @@ +--- +sidebar_label: async_utils +title: slack_bolt.kwargs_injection.async_utils +--- + +#### build\_async\_required\_kwargs + +```python +def build_async_required_kwargs( + *, + logger: logging.Logger, + required_arg_names: MutableSequence[str], + request: AsyncBoltRequest, + response: Optional[BoltResponse], + next_func: Optional[Callable[[], None]] = None, + this_func: Optional[Callable] = None, + error: Optional[Exception] = None, + next_keys_required: bool = True) -> Dict[str, Any] +``` diff --git a/docs/english/reference/kwargs_injection/index.md b/docs/english/reference/kwargs_injection/index.md new file mode 100644 index 000000000..b8ada463c --- /dev/null +++ b/docs/english/reference/kwargs_injection/index.md @@ -0,0 +1,218 @@ +--- +sidebar_label: kwargs_injection +title: slack_bolt.kwargs_injection +--- + +For middleware/listener arguments, Bolt does flexible data injection in accordance with their names. + +To learn the available arguments, check `slack_bolt.kwargs_injection.args`'s API document. +For steps from apps, checking `slack_bolt.workflows.step.utilities` as well should be helpful. + +## Submodules + +- [slack_bolt.kwargs_injection.args](/tools/bolt-python/reference/kwargs_injection/args) +- [slack_bolt.kwargs_injection.async_args](/tools/bolt-python/reference/kwargs_injection/async_args) +- [slack_bolt.kwargs_injection.async_utils](/tools/bolt-python/reference/kwargs_injection/async_utils) +- [slack_bolt.kwargs_injection.utils](/tools/bolt-python/reference/kwargs_injection/utils) + +## Args Objects + +```python +class Args() +``` + +All the arguments in this class are available in any middleware / listeners. +You can inject the named variables in the argument list in arbitrary order. + +```python +@app.action("link_button") +def handle_buttons(ack, respond, logger, context, body, client): + logger.info(f"request body: {body}") + ack() + if context.channel_id is not None: + respond("Hi!") + client.views_open( + trigger_id=body["trigger_id"], + view={ ... } + ) +``` + +Alternatively, you can include a parameter named `args` and it will be injected with an instance of this class. + +```python +@app.action("link_button") +def handle_buttons(args): + args.logger.info(f"request body: {args.body}") + args.ack() + if args.context.channel_id is not None: + args.respond("Hi!") + args.client.views_open( + trigger_id=args.body["trigger_id"], + view={ ... } + ) +``` + +#### client: `WebClient` + +`slack_sdk.web.WebClient` instance with a valid token + +#### logger: `logging.Logger` + +Logger instance + +#### req: `BoltRequest` + +Incoming request from Slack + +#### resp: `BoltResponse` + +Response representation + +#### request: `BoltRequest` + +Incoming request from Slack + +#### response: `BoltResponse` + +Response representation + +#### context: `BoltContext` + +Context data associated with the incoming request + +#### body: `Dict[str, Any]` + +Parsed request body data + +#### payload: `Dict[str, Any]` + +The unwrapped core data in the request body + +#### options: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.options` listener + +#### shortcut: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.shortcut` listener + +#### action: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.action` listener + +#### view: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.view` listener + +#### command: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.command` listener + +#### event: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.event` listener + +#### message: `Optional[Dict[str, Any]]` + +An alias for payload in an `@app.message` listener + +#### ack: `Ack` + +`ack()` utility function, which returns acknowledgement to the Slack servers + +#### say: `Say` + +`say()` utility function, which calls `chat.postMessage` API with the associated channel ID + +#### respond: `Respond` + +`respond()` utility function, which utilizes the associated `response_url` + +#### complete: `Complete` + +`complete()` utility function, signals a successful completion of the custom function + +#### fail: `Fail` + +`fail()` utility function, signal that the custom function failed to complete + +#### set\_status: `Optional[SetStatus]` + +`set_status()` utility function for AI Agents & Assistants + +#### set\_title: `Optional[SetTitle]` + +`set_title()` utility function for AI Agents & Assistants + +#### set\_suggested\_prompts: `Optional[SetSuggestedPrompts]` + +`set_suggested_prompts()` utility function for AI Agents & Assistants + +#### get\_thread\_context: `Optional[GetThreadContext]` + +`get_thread_context()` utility function for AI Agents & Assistants + +#### save\_thread\_context: `Optional[SaveThreadContext]` + +`save_thread_context()` utility function for AI Agents & Assistants + +#### say\_stream: `Optional[SayStream]` + +`say_stream()` utility function for conversations, AI Agents & Assistants + +#### next: `Callable[[], None]` + +`next()` utility function, which tells the middleware chain that it can continue with the next one + +#### next\_: `Callable[[], None]` + +An alias of `next()` for avoiding the Python built-in method overrides in middleware functions + +#### \_\_init\_\_ + +```python +def __init__( + *, + logger: logging.Logger, + client: WebClient, + req: BoltRequest, + resp: BoltResponse, + context: BoltContext, + body: Dict[str, Any], + payload: Dict[str, Any], + options: Optional[Dict[str, Any]] = None, + shortcut: Optional[Dict[str, Any]] = None, + action: Optional[Dict[str, Any]] = None, + view: Optional[Dict[str, Any]] = None, + command: Optional[Dict[str, Any]] = None, + event: Optional[Dict[str, Any]] = None, + message: Optional[Dict[str, Any]] = None, + ack: Ack, + say: Say, + respond: Respond, + complete: Complete, + fail: Fail, + set_status: Optional[SetStatus] = None, + set_title: Optional[SetTitle] = None, + set_suggested_prompts: Optional[SetSuggestedPrompts] = None, + get_thread_context: Optional[GetThreadContext] = None, + save_thread_context: Optional[SaveThreadContext] = None, + say_stream: Optional[SayStream] = None, + next: Callable[[], None], + **kwargs) +``` + +#### build\_required\_kwargs + +```python +def build_required_kwargs( + *, + logger: logging.Logger, + required_arg_names: MutableSequence[str], + request: BoltRequest, + response: Optional[BoltResponse], + next_func: Optional[Callable[[], None]] = None, + this_func: Optional[Callable] = None, + error: Optional[Exception] = None, + next_keys_required: bool = True) -> Dict[str, Any] +``` diff --git a/docs/english/reference/kwargs_injection/utils.md b/docs/english/reference/kwargs_injection/utils.md new file mode 100644 index 000000000..359c27274 --- /dev/null +++ b/docs/english/reference/kwargs_injection/utils.md @@ -0,0 +1,19 @@ +--- +sidebar_label: utils +title: slack_bolt.kwargs_injection.utils +--- + +#### build\_required\_kwargs + +```python +def build_required_kwargs( + *, + logger: logging.Logger, + required_arg_names: MutableSequence[str], + request: BoltRequest, + response: Optional[BoltResponse], + next_func: Optional[Callable[[], None]] = None, + this_func: Optional[Callable] = None, + error: Optional[Exception] = None, + next_keys_required: bool = True) -> Dict[str, Any] +``` diff --git a/docs/english/reference/lazy_listener/async_internals.md b/docs/english/reference/lazy_listener/async_internals.md new file mode 100644 index 000000000..c3e827f57 --- /dev/null +++ b/docs/english/reference/lazy_listener/async_internals.md @@ -0,0 +1,13 @@ +--- +sidebar_label: async_internals +title: slack_bolt.lazy_listener.async_internals +--- + +#### to\_runnable\_function + +```python +async def to_runnable_function( + internal_func: Callable[..., Awaitable[None]], + logger: Logger, + request: AsyncBoltRequest) +``` diff --git a/docs/english/reference/lazy_listener/async_runner.md b/docs/english/reference/lazy_listener/async_runner.md new file mode 100644 index 000000000..d0fe904c8 --- /dev/null +++ b/docs/english/reference/lazy_listener/async_runner.md @@ -0,0 +1,40 @@ +--- +sidebar_label: async_runner +title: slack_bolt.lazy_listener.async_runner +--- + +## AsyncLazyListenerRunner Objects + +```python +class AsyncLazyListenerRunner() +``` + +#### logger: `Logger` + +#### start + +```python +def start(function: Callable[..., Awaitable[None]], request: AsyncBoltRequest) -> None +``` + +Starts a new lazy listener execution. + +**Arguments**: + +- `function` _Callable[..., Awaitable[None]]_ - The function to run. +- `request` _AsyncBoltRequest_ - The request to pass to the function. The object must be thread-safe. + +#### run + +```python +async def run( + function: Callable[..., Awaitable[None]], + request: AsyncBoltRequest) -> None +``` + +Synchronously run the function with a given request data. + +**Arguments**: + +- `function` _Callable[..., Awaitable[None]]_ - The function to run. +- `request` _AsyncBoltRequest_ - The request to pass to the function. The object must be thread-safe. diff --git a/docs/english/reference/lazy_listener/asyncio_runner.md b/docs/english/reference/lazy_listener/asyncio_runner.md new file mode 100644 index 000000000..71f586c56 --- /dev/null +++ b/docs/english/reference/lazy_listener/asyncio_runner.md @@ -0,0 +1,24 @@ +--- +sidebar_label: asyncio_runner +title: slack_bolt.lazy_listener.asyncio_runner +--- + +## AsyncioLazyListenerRunner Objects + +```python +class AsyncioLazyListenerRunner(AsyncLazyListenerRunner) +``` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger) +``` + +#### start + +```python +def start(function: Callable[..., Awaitable[None]], request: AsyncBoltRequest) -> None +``` diff --git a/docs/english/reference/lazy_listener/index.md b/docs/english/reference/lazy_listener/index.md new file mode 100644 index 000000000..16bba61b6 --- /dev/null +++ b/docs/english/reference/lazy_listener/index.md @@ -0,0 +1,92 @@ +--- +sidebar_label: lazy_listener +title: slack_bolt.lazy_listener +--- + +Lazy listener runner is a beta feature for the apps running on Function-as-a-Service platforms. + +```python +def respond_to_slack_within_3_seconds(body, ack): + text = body.get("text") + if text is None or len(text) == 0: + ack(f":x: Usage: /start-process (description here)") + else: + ack(f"Accepted! (task: {body['text']})") + +import time +def run_long_process(respond, body): + time.sleep(5) # longer than 3 seconds + respond(f"Completed! (task: {body['text']})") + +app.command("/start-process")( + # ack() is still called within 3 seconds + ack=respond_to_slack_within_3_seconds, + # Lazy function is responsible for processing the event + lazy=[run_long_process] +) +``` + +Refer to https://docs.slack.dev/tools/bolt-python/concepts/lazy-listeners for more details. + +## Submodules + +- [slack_bolt.lazy_listener.async_internals](/tools/bolt-python/reference/lazy_listener/async_internals) +- [slack_bolt.lazy_listener.async_runner](/tools/bolt-python/reference/lazy_listener/async_runner) +- [slack_bolt.lazy_listener.asyncio_runner](/tools/bolt-python/reference/lazy_listener/asyncio_runner) +- [slack_bolt.lazy_listener.internals](/tools/bolt-python/reference/lazy_listener/internals) +- [slack_bolt.lazy_listener.runner](/tools/bolt-python/reference/lazy_listener/runner) +- [slack_bolt.lazy_listener.thread_runner](/tools/bolt-python/reference/lazy_listener/thread_runner) + +## LazyListenerRunner Objects + +```python +class LazyListenerRunner() +``` + +#### logger: `Logger` + +#### start + +```python +def start(function: Callable[..., None], request: BoltRequest) -> None +``` + +Starts a new lazy listener execution. + +**Arguments**: + +- `function` _Callable[..., None]_ - The function to run. +- `request` _BoltRequest_ - The request to pass to the function. The object must be thread-safe. + +#### run + +```python +def run(function: Callable[..., None], request: BoltRequest) -> None +``` + +Synchronously runs the function with a given request data. + +**Arguments**: + +- `function` _Callable[..., None]_ - The function to run. +- `request` _BoltRequest_ - The request to pass to the function. The object must be thread-safe. + +## ThreadLazyListenerRunner Objects + +```python +class ThreadLazyListenerRunner(LazyListenerRunner) +``` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger, executor: Executor) +``` + +#### start + +```python +def start(function: Callable[..., None], request: BoltRequest) -> None +``` diff --git a/docs/english/reference/lazy_listener/internals.md b/docs/english/reference/lazy_listener/internals.md new file mode 100644 index 000000000..0c6399765 --- /dev/null +++ b/docs/english/reference/lazy_listener/internals.md @@ -0,0 +1,13 @@ +--- +sidebar_label: internals +title: slack_bolt.lazy_listener.internals +--- + +#### build\_runnable\_function + +```python +def build_runnable_function( + func: Callable[..., None], + logger: Logger, + request: BoltRequest) -> Callable[[], None] +``` diff --git a/docs/english/reference/lazy_listener/runner.md b/docs/english/reference/lazy_listener/runner.md new file mode 100644 index 000000000..132251b21 --- /dev/null +++ b/docs/english/reference/lazy_listener/runner.md @@ -0,0 +1,38 @@ +--- +sidebar_label: runner +title: slack_bolt.lazy_listener.runner +--- + +## LazyListenerRunner Objects + +```python +class LazyListenerRunner() +``` + +#### logger: `Logger` + +#### start + +```python +def start(function: Callable[..., None], request: BoltRequest) -> None +``` + +Starts a new lazy listener execution. + +**Arguments**: + +- `function` _Callable[..., None]_ - The function to run. +- `request` _BoltRequest_ - The request to pass to the function. The object must be thread-safe. + +#### run + +```python +def run(function: Callable[..., None], request: BoltRequest) -> None +``` + +Synchronously runs the function with a given request data. + +**Arguments**: + +- `function` _Callable[..., None]_ - The function to run. +- `request` _BoltRequest_ - The request to pass to the function. The object must be thread-safe. diff --git a/docs/english/reference/lazy_listener/thread_runner.md b/docs/english/reference/lazy_listener/thread_runner.md new file mode 100644 index 000000000..0b8e2e8af --- /dev/null +++ b/docs/english/reference/lazy_listener/thread_runner.md @@ -0,0 +1,24 @@ +--- +sidebar_label: thread_runner +title: slack_bolt.lazy_listener.thread_runner +--- + +## ThreadLazyListenerRunner Objects + +```python +class ThreadLazyListenerRunner(LazyListenerRunner) +``` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger, executor: Executor) +``` + +#### start + +```python +def start(function: Callable[..., None], request: BoltRequest) -> None +``` diff --git a/docs/english/reference/listener/async_builtins.md b/docs/english/reference/listener/async_builtins.md new file mode 100644 index 000000000..3b37d8ca9 --- /dev/null +++ b/docs/english/reference/listener/async_builtins.md @@ -0,0 +1,32 @@ +--- +sidebar_label: async_builtins +title: slack_bolt.listener.async_builtins +--- + +## AsyncTokenRevocationListeners Objects + +```python +class AsyncTokenRevocationListeners() +``` + +Listener functions to handle token revocation / uninstallation events + +#### installation\_store: `AsyncInstallationStore` + +#### \_\_init\_\_ + +```python +def __init__(installation_store: AsyncInstallationStore) +``` + +#### handle\_tokens\_revoked\_events + +```python +async def handle_tokens_revoked_events(event: dict, context: AsyncBoltContext) -> None +``` + +#### handle\_app\_uninstalled\_events + +```python +async def handle_app_uninstalled_events(context: AsyncBoltContext) -> None +``` diff --git a/docs/english/reference/listener/async_listener.md b/docs/english/reference/listener/async_listener.md new file mode 100644 index 000000000..3971da968 --- /dev/null +++ b/docs/english/reference/listener/async_listener.md @@ -0,0 +1,118 @@ +--- +sidebar_label: async_listener +title: slack_bolt.listener.async_listener +--- + +## AsyncListener Objects + +```python +class AsyncListener() +``` + +#### matchers: `Sequence[AsyncListenerMatcher]` + +#### middleware: `Sequence[AsyncMiddleware]` + +#### ack\_function: `Callable[..., Awaitable[BoltResponse]]` + +#### lazy\_functions: `Sequence[Callable[..., Awaitable[None]]]` + +#### auto\_acknowledgement: `bool` + +#### ack\_timeout: `int` + +#### async\_matches + +```python +async def async_matches(*, req: AsyncBoltRequest, resp: BoltResponse) -> bool +``` + +#### run\_async\_middleware + +```python +async def run_async_middleware( + *, + req: AsyncBoltRequest, + resp: BoltResponse) -> Tuple[Optional[BoltResponse], bool] +``` + +Runs an async middleware. + +**Arguments**: + +- `req` _AsyncBoltRequest_ - The incoming request +- `resp` _BoltResponse_ - The current response + +**Returns**: + +- `Tuple[Optional[BoltResponse], bool]` - A tuple of the processed response and a flag indicating termination + +#### run\_ack\_function + +```python +async def run_ack_function( + *, + request: AsyncBoltRequest, + response: BoltResponse) -> Optional[BoltResponse] +``` + +Runs all the registered middleware and then run the listener function. + +**Arguments**: + +- `request` _AsyncBoltRequest_ - The incoming request +- `response` _BoltResponse_ - The current response + +**Returns**: + +- `Optional[BoltResponse]` - The processed response + +## AsyncCustomListener Objects + +```python +class AsyncCustomListener(AsyncListener) +``` + +#### app\_name: `str` + +#### ack\_function: `Callable[..., Awaitable[Optional[BoltResponse]]]` + +#### lazy\_functions: `Sequence[Callable[..., Awaitable[None]]]` + +#### matchers: `Sequence[AsyncListenerMatcher]` + +#### middleware: `Sequence[AsyncMiddleware]` + +#### auto\_acknowledgement: `bool` + +#### ack\_timeout: `int` + +#### arg\_names: `MutableSequence[str]` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str, + ack_function: Callable[..., Awaitable[Optional[BoltResponse]]], + lazy_functions: Sequence[Callable[..., Awaitable[None]]], + matchers: Sequence[AsyncListenerMatcher], + middleware: Sequence[AsyncMiddleware], + auto_acknowledgement: bool = False, + ack_timeout: int = 3, + base_logger: Optional[Logger] = None) +``` + +#### run\_ack\_function + +```python +async def run_ack_function( + *, + request: AsyncBoltRequest, + response: BoltResponse) -> Optional[BoltResponse] +``` + +#### builtin\_async\_listener\_classes diff --git a/docs/english/reference/listener/async_listener_completion_handler.md b/docs/english/reference/listener/async_listener_completion_handler.md new file mode 100644 index 000000000..9b7dafba8 --- /dev/null +++ b/docs/english/reference/listener/async_listener_completion_handler.md @@ -0,0 +1,59 @@ +--- +sidebar_label: async_listener_completion_handler +title: slack_bolt.listener.async_listener_completion_handler +--- + +## AsyncListenerCompletionHandler Objects + +```python +class AsyncListenerCompletionHandler() +``` + +#### handle + +```python +async def handle(request: AsyncBoltRequest, response: Optional[BoltResponse]) -> None +``` + +Do something extra after the listener execution + +**Arguments**: + +- `request` _AsyncBoltRequest_ - The request. +- `response` _Optional[BoltResponse]_ - The response. + +## AsyncCustomListenerCompletionHandler Objects + +```python +class AsyncCustomListenerCompletionHandler(AsyncListenerCompletionHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger, func: Callable[..., Awaitable[None]]) +``` + +#### handle + +```python +async def handle(request: AsyncBoltRequest, response: Optional[BoltResponse]) -> None +``` + +## AsyncDefaultListenerCompletionHandler Objects + +```python +class AsyncDefaultListenerCompletionHandler(AsyncListenerCompletionHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger) +``` + +#### handle + +```python +async def handle(request: AsyncBoltRequest, response: Optional[BoltResponse]) +``` diff --git a/docs/english/reference/listener/async_listener_error_handler.md b/docs/english/reference/listener/async_listener_error_handler.md new file mode 100644 index 000000000..f42137530 --- /dev/null +++ b/docs/english/reference/listener/async_listener_error_handler.md @@ -0,0 +1,69 @@ +--- +sidebar_label: async_listener_error_handler +title: slack_bolt.listener.async_listener_error_handler +--- + +## AsyncListenerErrorHandler Objects + +```python +class AsyncListenerErrorHandler() +``` + +#### handle + +```python +async def handle( + error: Exception, + request: AsyncBoltRequest, + response: Optional[BoltResponse]) -> None +``` + +Handles an unhandled exception. + +**Arguments**: + +- `error` _Exception_ - The raised exception. +- `request` _AsyncBoltRequest_ - The request. +- `response` _Optional[BoltResponse]_ - The response. + +## AsyncCustomListenerErrorHandler Objects + +```python +class AsyncCustomListenerErrorHandler(AsyncListenerErrorHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger, func: Callable[..., Awaitable[Optional[BoltResponse]]]) +``` + +#### handle + +```python +async def handle( + error: Exception, + request: AsyncBoltRequest, + response: Optional[BoltResponse]) -> None +``` + +## AsyncDefaultListenerErrorHandler Objects + +```python +class AsyncDefaultListenerErrorHandler(AsyncListenerErrorHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger) +``` + +#### handle + +```python +async def handle( + error: Exception, + request: AsyncBoltRequest, + response: Optional[BoltResponse]) +``` diff --git a/docs/english/reference/listener/async_listener_start_handler.md b/docs/english/reference/listener/async_listener_start_handler.md new file mode 100644 index 000000000..443701591 --- /dev/null +++ b/docs/english/reference/listener/async_listener_start_handler.md @@ -0,0 +1,59 @@ +--- +sidebar_label: async_listener_start_handler +title: slack_bolt.listener.async_listener_start_handler +--- + +## AsyncListenerStartHandler Objects + +```python +class AsyncListenerStartHandler() +``` + +#### handle + +```python +async def handle(request: AsyncBoltRequest, response: Optional[BoltResponse]) -> None +``` + +Do something extra before the listener execution + +**Arguments**: + +- `request` _AsyncBoltRequest_ - The request. +- `response` _Optional[BoltResponse]_ - The response. + +## AsyncCustomListenerStartHandler Objects + +```python +class AsyncCustomListenerStartHandler(AsyncListenerStartHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger, func: Callable[..., Awaitable[None]]) +``` + +#### handle + +```python +async def handle(request: AsyncBoltRequest, response: Optional[BoltResponse]) -> None +``` + +## AsyncDefaultListenerStartHandler Objects + +```python +class AsyncDefaultListenerStartHandler(AsyncListenerStartHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger) +``` + +#### handle + +```python +async def handle(request: AsyncBoltRequest, response: Optional[BoltResponse]) +``` diff --git a/docs/english/reference/listener/asyncio_runner.md b/docs/english/reference/listener/asyncio_runner.md new file mode 100644 index 000000000..4abcd0711 --- /dev/null +++ b/docs/english/reference/listener/asyncio_runner.md @@ -0,0 +1,45 @@ +--- +sidebar_label: asyncio_runner +title: slack_bolt.listener.asyncio_runner +--- + +## AsyncioListenerRunner Objects + +```python +class AsyncioListenerRunner() +``` + +#### logger: `Logger` + +#### process\_before\_response: `bool` + +#### listener\_error\_handler: `AsyncListenerErrorHandler` + +#### listener\_start\_handler: `AsyncListenerStartHandler` + +#### listener\_completion\_handler: `AsyncListenerCompletionHandler` + +#### lazy\_listener\_runner: `AsyncLazyListenerRunner` + +#### \_\_init\_\_ + +```python +def __init__( + logger: Logger, + process_before_response: bool, + listener_error_handler: AsyncListenerErrorHandler, + listener_start_handler: AsyncListenerStartHandler, + listener_completion_handler: AsyncListenerCompletionHandler, + lazy_listener_runner: AsyncLazyListenerRunner) +``` + +#### run + +```python +async def run( + request: AsyncBoltRequest, + response: BoltResponse, + listener_name: str, + listener: AsyncListener, + starting_time: Optional[float] = None) -> Optional[BoltResponse] +``` diff --git a/docs/english/reference/listener/builtins.md b/docs/english/reference/listener/builtins.md new file mode 100644 index 000000000..e38de8b8e --- /dev/null +++ b/docs/english/reference/listener/builtins.md @@ -0,0 +1,32 @@ +--- +sidebar_label: builtins +title: slack_bolt.listener.builtins +--- + +## TokenRevocationListeners Objects + +```python +class TokenRevocationListeners() +``` + +Listener functions to handle token revocation / uninstallation events + +#### installation\_store: `InstallationStore` + +#### \_\_init\_\_ + +```python +def __init__(installation_store: InstallationStore) +``` + +#### handle\_tokens\_revoked\_events + +```python +def handle_tokens_revoked_events(event: dict, context: BoltContext) -> None +``` + +#### handle\_app\_uninstalled\_events + +```python +def handle_app_uninstalled_events(context: BoltContext) -> None +``` diff --git a/docs/english/reference/listener/custom_listener.md b/docs/english/reference/listener/custom_listener.md new file mode 100644 index 000000000..30504b959 --- /dev/null +++ b/docs/english/reference/listener/custom_listener.md @@ -0,0 +1,52 @@ +--- +sidebar_label: custom_listener +title: slack_bolt.listener.custom_listener +--- + +## CustomListener Objects + +```python +class CustomListener(Listener) +``` + +#### app\_name: `str` + +#### ack\_function: `Callable[..., Optional[BoltResponse]]` + +#### lazy\_functions: `Sequence[Callable[..., None]]` + +#### matchers: `Sequence[ListenerMatcher]` + +#### middleware: `Sequence[Middleware]` + +#### auto\_acknowledgement: `bool` + +#### ack\_timeout: `int` + +#### arg\_names: `MutableSequence[str]` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str, + ack_function: Callable[..., Optional[BoltResponse]], + lazy_functions: Sequence[Callable[..., None]], + matchers: Sequence[ListenerMatcher], + middleware: Sequence[Middleware], + auto_acknowledgement: bool = False, + ack_timeout: int = 3, + base_logger: Optional[Logger] = None) +``` + +#### run\_ack\_function + +```python +def run_ack_function( + *, + request: BoltRequest, + response: BoltResponse) -> Optional[BoltResponse] +``` diff --git a/docs/english/reference/listener/index.md b/docs/english/reference/listener/index.md new file mode 100644 index 000000000..91e2b16b1 --- /dev/null +++ b/docs/english/reference/listener/index.md @@ -0,0 +1,138 @@ +--- +sidebar_label: listener +title: slack_bolt.listener +--- + +Listeners process an incoming request from Slack if the request's type or data structure matches +the predefined conditions of the listener. Typically, a listener acknowledge requests from Slack, +process the request data, and may send response back to Slack. + +## Submodules + +- [slack_bolt.listener.async_builtins](/tools/bolt-python/reference/listener/async_builtins) +- [slack_bolt.listener.async_listener](/tools/bolt-python/reference/listener/async_listener) +- [slack_bolt.listener.async_listener_completion_handler](/tools/bolt-python/reference/listener/async_listener_completion_handler) +- [slack_bolt.listener.async_listener_error_handler](/tools/bolt-python/reference/listener/async_listener_error_handler) +- [slack_bolt.listener.async_listener_start_handler](/tools/bolt-python/reference/listener/async_listener_start_handler) +- [slack_bolt.listener.asyncio_runner](/tools/bolt-python/reference/listener/asyncio_runner) +- [slack_bolt.listener.builtins](/tools/bolt-python/reference/listener/builtins) +- [slack_bolt.listener.custom_listener](/tools/bolt-python/reference/listener/custom_listener) +- [slack_bolt.listener.listener](/tools/bolt-python/reference/listener/listener) +- [slack_bolt.listener.listener_completion_handler](/tools/bolt-python/reference/listener/listener_completion_handler) +- [slack_bolt.listener.listener_error_handler](/tools/bolt-python/reference/listener/listener_error_handler) +- [slack_bolt.listener.listener_start_handler](/tools/bolt-python/reference/listener/listener_start_handler) +- [slack_bolt.listener.thread_runner](/tools/bolt-python/reference/listener/thread_runner) + +## CustomListener Objects + +```python +class CustomListener(Listener) +``` + +#### app\_name: `str` + +#### ack\_function: `Callable[..., Optional[BoltResponse]]` + +#### lazy\_functions: `Sequence[Callable[..., None]]` + +#### matchers: `Sequence[ListenerMatcher]` + +#### middleware: `Sequence[Middleware]` + +#### auto\_acknowledgement: `bool` + +#### ack\_timeout: `int` + +#### arg\_names: `MutableSequence[str]` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str, + ack_function: Callable[..., Optional[BoltResponse]], + lazy_functions: Sequence[Callable[..., None]], + matchers: Sequence[ListenerMatcher], + middleware: Sequence[Middleware], + auto_acknowledgement: bool = False, + ack_timeout: int = 3, + base_logger: Optional[Logger] = None) +``` + +#### run\_ack\_function + +```python +def run_ack_function( + *, + request: BoltRequest, + response: BoltResponse) -> Optional[BoltResponse] +``` + +## Listener Objects + +```python +class Listener() +``` + +#### matchers: `Sequence[ListenerMatcher]` + +#### middleware: `Sequence[Middleware]` + +#### ack\_function: `Callable[..., BoltResponse]` + +#### lazy\_functions: `Sequence[Callable[..., None]]` + +#### auto\_acknowledgement: `bool` + +#### ack\_timeout: `int` + +#### matches + +```python +def matches(*, req: BoltRequest, resp: BoltResponse) -> bool +``` + +#### run\_middleware + +```python +def run_middleware( + *, + req: BoltRequest, + resp: BoltResponse) -> Tuple[Optional[BoltResponse], bool] +``` + +Runs a middleware. + +**Arguments**: + +- `req` _BoltRequest_ - The incoming request +- `resp` _BoltResponse_ - The current response + +**Returns**: + +- `Tuple[Optional[BoltResponse], bool]` - A tuple of the processed response and a flag indicating termination + +#### run\_ack\_function + +```python +def run_ack_function( + *, + request: BoltRequest, + response: BoltResponse) -> Optional[BoltResponse] +``` + +Runs all the registered middleware and then run the listener function. + +**Arguments**: + +- `request` _BoltRequest_ - The incoming request +- `response` _BoltResponse_ - The current response + +**Returns**: + +- `Optional[BoltResponse]` - The processed response + +#### builtin\_listener\_classes diff --git a/docs/english/reference/listener/listener.md b/docs/english/reference/listener/listener.md new file mode 100644 index 000000000..f868d7bf6 --- /dev/null +++ b/docs/english/reference/listener/listener.md @@ -0,0 +1,69 @@ +--- +sidebar_label: listener +title: slack_bolt.listener.listener +slug: listener +--- + +## Listener Objects + +```python +class Listener() +``` + +#### matchers: `Sequence[ListenerMatcher]` + +#### middleware: `Sequence[Middleware]` + +#### ack\_function: `Callable[..., BoltResponse]` + +#### lazy\_functions: `Sequence[Callable[..., None]]` + +#### auto\_acknowledgement: `bool` + +#### ack\_timeout: `int` + +#### matches + +```python +def matches(*, req: BoltRequest, resp: BoltResponse) -> bool +``` + +#### run\_middleware + +```python +def run_middleware( + *, + req: BoltRequest, + resp: BoltResponse) -> Tuple[Optional[BoltResponse], bool] +``` + +Runs a middleware. + +**Arguments**: + +- `req` _BoltRequest_ - The incoming request +- `resp` _BoltResponse_ - The current response + +**Returns**: + +- `Tuple[Optional[BoltResponse], bool]` - A tuple of the processed response and a flag indicating termination + +#### run\_ack\_function + +```python +def run_ack_function( + *, + request: BoltRequest, + response: BoltResponse) -> Optional[BoltResponse] +``` + +Runs all the registered middleware and then run the listener function. + +**Arguments**: + +- `request` _BoltRequest_ - The incoming request +- `response` _BoltResponse_ - The current response + +**Returns**: + +- `Optional[BoltResponse]` - The processed response diff --git a/docs/english/reference/listener/listener_completion_handler.md b/docs/english/reference/listener/listener_completion_handler.md new file mode 100644 index 000000000..f4b4fcec5 --- /dev/null +++ b/docs/english/reference/listener/listener_completion_handler.md @@ -0,0 +1,59 @@ +--- +sidebar_label: listener_completion_handler +title: slack_bolt.listener.listener_completion_handler +--- + +## ListenerCompletionHandler Objects + +```python +class ListenerCompletionHandler() +``` + +#### handle + +```python +def handle(request: BoltRequest, response: Optional[BoltResponse]) -> None +``` + +Do something extra after the listener execution + +**Arguments**: + +- `request` _BoltRequest_ - The request. +- `response` _Optional[BoltResponse]_ - The response. + +## CustomListenerCompletionHandler Objects + +```python +class CustomListenerCompletionHandler(ListenerCompletionHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger, func: Callable[..., None]) +``` + +#### handle + +```python +def handle(request: BoltRequest, response: Optional[BoltResponse]) +``` + +## DefaultListenerCompletionHandler Objects + +```python +class DefaultListenerCompletionHandler(ListenerCompletionHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger) +``` + +#### handle + +```python +def handle(request: BoltRequest, response: Optional[BoltResponse]) +``` diff --git a/docs/english/reference/listener/listener_error_handler.md b/docs/english/reference/listener/listener_error_handler.md new file mode 100644 index 000000000..1f846b1f0 --- /dev/null +++ b/docs/english/reference/listener/listener_error_handler.md @@ -0,0 +1,63 @@ +--- +sidebar_label: listener_error_handler +title: slack_bolt.listener.listener_error_handler +--- + +## ListenerErrorHandler Objects + +```python +class ListenerErrorHandler() +``` + +#### handle + +```python +def handle( + error: Exception, + request: BoltRequest, + response: Optional[BoltResponse]) -> None +``` + +Handles an unhandled exception. + +**Arguments**: + +- `error` _Exception_ - The raised exception. +- `request` _BoltRequest_ - The request. +- `response` _Optional[BoltResponse]_ - The response. + +## CustomListenerErrorHandler Objects + +```python +class CustomListenerErrorHandler(ListenerErrorHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger, func: Callable[..., Optional[BoltResponse]]) +``` + +#### handle + +```python +def handle(error: Exception, request: BoltRequest, response: Optional[BoltResponse]) +``` + +## DefaultListenerErrorHandler Objects + +```python +class DefaultListenerErrorHandler(ListenerErrorHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger) +``` + +#### handle + +```python +def handle(error: Exception, request: BoltRequest, response: Optional[BoltResponse]) +``` diff --git a/docs/english/reference/listener/listener_start_handler.md b/docs/english/reference/listener/listener_start_handler.md new file mode 100644 index 000000000..fc4844fca --- /dev/null +++ b/docs/english/reference/listener/listener_start_handler.md @@ -0,0 +1,63 @@ +--- +sidebar_label: listener_start_handler +title: slack_bolt.listener.listener_start_handler +--- + +## ListenerStartHandler Objects + +```python +class ListenerStartHandler() +``` + +#### handle + +```python +def handle(request: BoltRequest, response: Optional[BoltResponse]) -> None +``` + +Do something extra before the listener execution. + +This handler is useful if a developer needs to maintain/clean up +thread-local resources such as Django ORM database connections +before a listener execution starts. + +**Arguments**: + +- `request` _BoltRequest_ - The request. +- `response` _Optional[BoltResponse]_ - The response. + +## CustomListenerStartHandler Objects + +```python +class CustomListenerStartHandler(ListenerStartHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger, func: Callable[..., None]) +``` + +#### handle + +```python +def handle(request: BoltRequest, response: Optional[BoltResponse]) +``` + +## DefaultListenerStartHandler Objects + +```python +class DefaultListenerStartHandler(ListenerStartHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger) +``` + +#### handle + +```python +def handle(request: BoltRequest, response: Optional[BoltResponse]) +``` diff --git a/docs/english/reference/listener/thread_runner.md b/docs/english/reference/listener/thread_runner.md new file mode 100644 index 000000000..105f81260 --- /dev/null +++ b/docs/english/reference/listener/thread_runner.md @@ -0,0 +1,48 @@ +--- +sidebar_label: thread_runner +title: slack_bolt.listener.thread_runner +--- + +## ThreadListenerRunner Objects + +```python +class ThreadListenerRunner() +``` + +#### logger: `Logger` + +#### process\_before\_response: `bool` + +#### listener\_error\_handler: `ListenerErrorHandler` + +#### listener\_start\_handler: `ListenerStartHandler` + +#### listener\_completion\_handler: `ListenerCompletionHandler` + +#### listener\_executor: `Executor` + +#### lazy\_listener\_runner: `LazyListenerRunner` + +#### \_\_init\_\_ + +```python +def __init__( + logger: Logger, + process_before_response: bool, + listener_error_handler: ListenerErrorHandler, + listener_start_handler: ListenerStartHandler, + listener_completion_handler: ListenerCompletionHandler, + listener_executor: Executor, + lazy_listener_runner: LazyListenerRunner) +``` + +#### run + +```python +def run( + request: BoltRequest, + response: BoltResponse, + listener_name: str, + listener: Listener, + starting_time: Optional[float] = None) -> Optional[BoltResponse] +``` diff --git a/docs/english/reference/listener_matcher/async_builtins.md b/docs/english/reference/listener_matcher/async_builtins.md new file mode 100644 index 000000000..0f1c9d444 --- /dev/null +++ b/docs/english/reference/listener_matcher/async_builtins.md @@ -0,0 +1,16 @@ +--- +sidebar_label: async_builtins +title: slack_bolt.listener_matcher.async_builtins +--- + +## AsyncBuiltinListenerMatcher Objects + +```python +class AsyncBuiltinListenerMatcher(BuiltinListenerMatcher, AsyncListenerMatcher) +``` + +#### async\_matches + +```python +async def async_matches(req: AsyncBoltRequest, resp: BoltResponse) -> bool +``` diff --git a/docs/english/reference/listener_matcher/async_listener_matcher.md b/docs/english/reference/listener_matcher/async_listener_matcher.md new file mode 100644 index 000000000..9dab3172a --- /dev/null +++ b/docs/english/reference/listener_matcher/async_listener_matcher.md @@ -0,0 +1,59 @@ +--- +sidebar_label: async_listener_matcher +title: slack_bolt.listener_matcher.async_listener_matcher +--- + +## AsyncListenerMatcher Objects + +```python +class AsyncListenerMatcher() +``` + +#### async\_matches + +```python +async def async_matches(req: AsyncBoltRequest, resp: BoltResponse) -> bool +``` + +Matches against the request and returns True if matched. + +**Arguments**: + +- `req` _AsyncBoltRequest_ - The request +- `resp` _BoltResponse_ - The response + +**Returns**: + +- `bool` - True if matched + +## AsyncCustomListenerMatcher Objects + +```python +class AsyncCustomListenerMatcher(AsyncListenerMatcher) +``` + +#### app\_name: `str` + +#### func: `Callable[..., Awaitable[bool]]` + +#### arg\_names: `Sequence[str]` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str, + func: Callable[..., Awaitable[bool]], + base_logger: Optional[Logger] = None) +``` + +#### async\_matches + +```python +async def async_matches(req: AsyncBoltRequest, resp: BoltResponse) -> bool +``` + +#### builtin\_async\_listener\_matcher\_classes diff --git a/docs/english/reference/listener_matcher/builtins.md b/docs/english/reference/listener_matcher/builtins.md new file mode 100644 index 000000000..571b4476f --- /dev/null +++ b/docs/english/reference/listener_matcher/builtins.md @@ -0,0 +1,224 @@ +--- +sidebar_label: builtins +title: slack_bolt.listener_matcher.builtins +--- + +## BuiltinListenerMatcher Objects + +```python +class BuiltinListenerMatcher(ListenerMatcher) +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + func: Callable[..., Union[bool, Awaitable[bool]]], + base_logger: Optional[Logger] = None) +``` + +#### matches + +```python +def matches(req: BoltRequest, resp: BoltResponse) -> bool +``` + +#### build\_listener\_matcher + +```python +def build_listener_matcher( + func: Callable[..., bool], + asyncio: bool, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### event + +```python +def event( + constraints: Union[str, Pattern, Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]]], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### message\_event + +```python +def message_event( + constraints: Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]], + keyword: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### function\_executed + +```python +def function_executed( + callback_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### workflow\_step\_execute + +```python +def workflow_step_execute( + callback_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### command + +```python +def command( + command: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### shortcut + +```python +def shortcut( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### global\_shortcut + +```python +def global_shortcut( + callback_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### message\_shortcut + +```python +def message_shortcut( + callback_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### action + +```python +def action( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### block\_action + +```python +def block_action( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### attachment\_action + +```python +def attachment_action( + callback_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### dialog\_submission + +```python +def dialog_submission( + callback_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### dialog\_cancellation + +```python +def dialog_cancellation( + callback_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### workflow\_step\_edit + +```python +def workflow_step_edit( + callback_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### view + +```python +def view( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### view\_submission + +```python +def view_submission( + callback_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### view\_closed + +```python +def view_closed( + callback_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### workflow\_step\_save + +```python +def workflow_step_save( + callback_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### options + +```python +def options( + constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### block\_suggestion + +```python +def block_suggestion( + action_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` + +#### dialog\_suggestion + +```python +def dialog_suggestion( + callback_id: Union[str, Pattern], + asyncio: bool = False, + base_logger: Optional[Logger] = None) -> Union[ListenerMatcher, AsyncListenerMatcher] +``` diff --git a/docs/english/reference/listener_matcher/custom_listener_matcher.md b/docs/english/reference/listener_matcher/custom_listener_matcher.md new file mode 100644 index 000000000..1b38b6460 --- /dev/null +++ b/docs/english/reference/listener_matcher/custom_listener_matcher.md @@ -0,0 +1,34 @@ +--- +sidebar_label: custom_listener_matcher +title: slack_bolt.listener_matcher.custom_listener_matcher +--- + +## CustomListenerMatcher Objects + +```python +class CustomListenerMatcher(ListenerMatcher) +``` + +#### app\_name: `str` + +#### func: `Callable[..., bool]` + +#### arg\_names: `MutableSequence[str]` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str, + func: Callable[..., bool], + base_logger: Optional[Logger] = None) +``` + +#### matches + +```python +def matches(req: BoltRequest, resp: BoltResponse) -> bool +``` diff --git a/docs/english/reference/listener_matcher/index.md b/docs/english/reference/listener_matcher/index.md new file mode 100644 index 000000000..6f54417b8 --- /dev/null +++ b/docs/english/reference/listener_matcher/index.md @@ -0,0 +1,71 @@ +--- +sidebar_label: listener_matcher +title: slack_bolt.listener_matcher +--- + +A listener matcher is a simplified version of listener middleware. +A listener matcher function returns bool value instead of `next()` method invocation inside. +This interface enables developers to utilize simple predicate functions for additional listener conditions. + +## Submodules + +- [slack_bolt.listener_matcher.async_builtins](/tools/bolt-python/reference/listener_matcher/async_builtins) +- [slack_bolt.listener_matcher.async_listener_matcher](/tools/bolt-python/reference/listener_matcher/async_listener_matcher) +- [slack_bolt.listener_matcher.builtins](/tools/bolt-python/reference/listener_matcher/builtins) +- [slack_bolt.listener_matcher.custom_listener_matcher](/tools/bolt-python/reference/listener_matcher/custom_listener_matcher) +- [slack_bolt.listener_matcher.listener_matcher](/tools/bolt-python/reference/listener_matcher/listener_matcher) + +## CustomListenerMatcher Objects + +```python +class CustomListenerMatcher(ListenerMatcher) +``` + +#### app\_name: `str` + +#### func: `Callable[..., bool]` + +#### arg\_names: `MutableSequence[str]` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str, + func: Callable[..., bool], + base_logger: Optional[Logger] = None) +``` + +#### matches + +```python +def matches(req: BoltRequest, resp: BoltResponse) -> bool +``` + +## ListenerMatcher Objects + +```python +class ListenerMatcher() +``` + +#### matches + +```python +def matches(req: BoltRequest, resp: BoltResponse) -> bool +``` + +Matches against the request and returns True if matched. + +**Arguments**: + +- `req` _BoltRequest_ - The request +- `resp` _BoltResponse_ - The response + +**Returns**: + +- `bool` - True if matched. + +#### builtin\_listener\_matcher\_classes diff --git a/docs/english/reference/listener_matcher/listener_matcher.md b/docs/english/reference/listener_matcher/listener_matcher.md new file mode 100644 index 000000000..5827a6b03 --- /dev/null +++ b/docs/english/reference/listener_matcher/listener_matcher.md @@ -0,0 +1,28 @@ +--- +sidebar_label: listener_matcher +title: slack_bolt.listener_matcher.listener_matcher +slug: listener_matcher +--- + +## ListenerMatcher Objects + +```python +class ListenerMatcher() +``` + +#### matches + +```python +def matches(req: BoltRequest, resp: BoltResponse) -> bool +``` + +Matches against the request and returns True if matched. + +**Arguments**: + +- `req` _BoltRequest_ - The request +- `resp` _BoltResponse_ - The response + +**Returns**: + +- `bool` - True if matched. diff --git a/docs/english/reference/logger/index.md b/docs/english/reference/logger/index.md new file mode 100644 index 000000000..c1d106177 --- /dev/null +++ b/docs/english/reference/logger/index.md @@ -0,0 +1,25 @@ +--- +sidebar_label: logger +title: slack_bolt.logger +--- + +Bolt for Python relies on the standard `logging` module. + +## Submodules + +- [slack_bolt.logger.messages](/tools/bolt-python/reference/logger/messages) + +#### get\_bolt\_logger + +```python +def get_bolt_logger(cls: Any, base_logger: Optional[Logger] = None) -> Logger +``` + +#### get\_bolt\_app\_logger + +```python +def get_bolt_app_logger( + app_name: str, + cls: object = None, + base_logger: Optional[Logger] = None) -> Logger +``` diff --git a/docs/english/reference/logger/messages.md b/docs/english/reference/logger/messages.md new file mode 100644 index 000000000..367dc6c3a --- /dev/null +++ b/docs/english/reference/logger/messages.md @@ -0,0 +1,180 @@ +--- +sidebar_label: messages +title: slack_bolt.logger.messages +--- + +#### error\_client\_invalid\_type + +```python +def error_client_invalid_type() -> str +``` + +#### error\_client\_invalid\_type\_async + +```python +def error_client_invalid_type_async() -> str +``` + +#### error\_oauth\_flow\_invalid\_type\_async + +```python +def error_oauth_flow_invalid_type_async() -> str +``` + +#### error\_oauth\_settings\_invalid\_type\_async + +```python +def error_oauth_settings_invalid_type_async() -> str +``` + +#### error\_auth\_test\_failure + +```python +def error_auth_test_failure(error_response: SlackResponse) -> str +``` + +#### error\_token\_required + +```python +def error_token_required() -> str +``` + +#### error\_unexpected\_listener\_middleware + +```python +def error_unexpected_listener_middleware(middleware_type) -> str +``` + +#### error\_listener\_function\_must\_be\_coro\_func + +```python +def error_listener_function_must_be_coro_func(func_name: str) -> str +``` + +#### error\_authorize\_conflicts + +```python +def error_authorize_conflicts() -> str +``` + +#### error\_message\_event\_type + +```python +def error_message_event_type(event_type: Union[str, Pattern]) -> str +``` + +#### error\_installation\_store\_required\_for\_builtin\_listeners + +```python +def error_installation_store_required_for_builtin_listeners() -> str +``` + +#### error\_oauth\_flow\_or\_authorize\_required + +```python +def error_oauth_flow_or_authorize_required() -> str +``` + +#### warning\_client\_prioritized\_and\_token\_skipped + +```python +def warning_client_prioritized_and_token_skipped() -> str +``` + +#### warning\_token\_skipped + +```python +def warning_token_skipped() -> str +``` + +#### warning\_installation\_store\_conflicts + +```python +def warning_installation_store_conflicts() -> str +``` + +#### warning\_unhandled\_by\_global\_middleware + +```python +def warning_unhandled_by_global_middleware( + name: str, + req: Union[BoltRequest, AsyncBoltRequest]) -> str +``` + +#### warning\_unhandled\_request + +```python +def warning_unhandled_request(req: Union[BoltRequest, AsyncBoltRequest]) -> str +``` + +#### warning\_did\_not\_call\_ack + +```python +def warning_did_not_call_ack(listener_name: str) -> str +``` + +#### warning\_bot\_only\_conflicts + +```python +def warning_bot_only_conflicts() -> str +``` + +#### warning\_skip\_uncommon\_arg\_name + +```python +def warning_skip_uncommon_arg_name(arg_name: str) -> str +``` + +#### warning\_ack\_timeout\_has\_no\_effect + +```python +def warning_ack_timeout_has_no_effect( + identifier: Union[str, Pattern], + ack_timeout: int) -> str +``` + +#### info\_default\_oauth\_settings\_loaded + +```python +def info_default_oauth_settings_loaded() -> str +``` + +#### debug\_applying\_middleware + +```python +def debug_applying_middleware(middleware_name: str) -> str +``` + +#### debug\_checking\_listener + +```python +def debug_checking_listener(listener_name: str) -> str +``` + +#### debug\_running\_listener + +```python +def debug_running_listener(listener_name: str) -> str +``` + +#### debug\_running\_lazy\_listener + +```python +def debug_running_lazy_listener(func_name: str) -> str +``` + +#### debug\_responding + +```python +def debug_responding(status: int, body: str, millis: int) -> str +``` + +#### debug\_return\_listener\_middleware\_response + +```python +def debug_return_listener_middleware_response( + listener_name: str, + status: int, + body: str, + starting_time: float) -> str +``` diff --git a/docs/english/reference/middleware/assistant/assistant.md b/docs/english/reference/middleware/assistant/assistant.md new file mode 100644 index 000000000..0d67911e2 --- /dev/null +++ b/docs/english/reference/middleware/assistant/assistant.md @@ -0,0 +1,93 @@ +--- +sidebar_label: assistant +title: slack_bolt.middleware.assistant.assistant +slug: assistant +--- + +## Assistant Objects + +```python +class Assistant(Middleware) +``` + +#### thread\_context\_store: `Optional[AssistantThreadContextStore]` + +#### base\_logger: `Optional[logging.Logger]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str = 'assistant', + thread_context_store: Optional[AssistantThreadContextStore] = None, + logger: Optional[logging.Logger] = None) +``` + +#### thread\_started + +```python +def thread_started( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### user\_message + +```python +def user_message( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### bot\_message + +```python +def bot_message( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### thread\_context\_changed + +```python +def thread_context_changed( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### default\_thread\_context\_changed + +```python +def default_thread_context_changed( + save_thread_context: SaveThreadContext, + payload: dict) +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> Optional[BoltResponse] +``` + +#### build\_listener + +```python +def build_listener( + listener_or_functions: Union[Listener, Callable, List[Callable]], + matchers: Optional[List[Union[ListenerMatcher, Callable[..., bool]]]] = None, + middleware: Optional[List[Middleware]] = None, + base_logger: Optional[Logger] = None) -> Listener +``` diff --git a/docs/english/reference/middleware/assistant/async_assistant.md b/docs/english/reference/middleware/assistant/async_assistant.md new file mode 100644 index 000000000..1b4fa1f8e --- /dev/null +++ b/docs/english/reference/middleware/assistant/async_assistant.md @@ -0,0 +1,92 @@ +--- +sidebar_label: async_assistant +title: slack_bolt.middleware.assistant.async_assistant +--- + +## AsyncAssistant Objects + +```python +class AsyncAssistant(AsyncMiddleware) +``` + +#### thread\_context\_store: `Optional[AsyncAssistantThreadContextStore]` + +#### base\_logger: `Optional[logging.Logger]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str = 'assistant', + thread_context_store: Optional[AsyncAssistantThreadContextStore] = None, + logger: Optional[logging.Logger] = None) +``` + +#### thread\_started + +```python +def thread_started( + *args, + matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None, + middleware: Optional[Union[Callable, AsyncMiddleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### user\_message + +```python +def user_message( + *args, + matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None, + middleware: Optional[Union[Callable, AsyncMiddleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### bot\_message + +```python +def bot_message( + *args, + matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None, + middleware: Optional[Union[Callable, AsyncMiddleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### thread\_context\_changed + +```python +def thread_context_changed( + *args, + matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None, + middleware: Optional[Union[Callable, AsyncMiddleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### default\_thread\_context\_changed + +```python +async def default_thread_context_changed( + save_thread_context: AsyncSaveThreadContext, + payload: dict) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> Optional[BoltResponse] +``` + +#### build\_listener + +```python +def build_listener( + listener_or_functions: Union[AsyncListener, Callable, List[Callable]], + matchers: Optional[List[Union[AsyncListenerMatcher, Callable[..., Awaitable[bool]]]]] = None, + middleware: Optional[List[AsyncMiddleware]] = None, + base_logger: Optional[Logger] = None) -> AsyncListener +``` diff --git a/docs/english/reference/middleware/assistant/index.md b/docs/english/reference/middleware/assistant/index.md new file mode 100644 index 000000000..5d94bc94f --- /dev/null +++ b/docs/english/reference/middleware/assistant/index.md @@ -0,0 +1,97 @@ +--- +sidebar_label: assistant +title: slack_bolt.middleware.assistant +--- + +## Submodules + +- [slack_bolt.middleware.assistant.assistant](/tools/bolt-python/reference/middleware/assistant/assistant) +- [slack_bolt.middleware.assistant.async_assistant](/tools/bolt-python/reference/middleware/assistant/async_assistant) + +## Assistant Objects + +```python +class Assistant(Middleware) +``` + +#### thread\_context\_store: `Optional[AssistantThreadContextStore]` + +#### base\_logger: `Optional[logging.Logger]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str = 'assistant', + thread_context_store: Optional[AssistantThreadContextStore] = None, + logger: Optional[logging.Logger] = None) +``` + +#### thread\_started + +```python +def thread_started( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### user\_message + +```python +def user_message( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### bot\_message + +```python +def bot_message( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### thread\_context\_changed + +```python +def thread_context_changed( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +#### default\_thread\_context\_changed + +```python +def default_thread_context_changed( + save_thread_context: SaveThreadContext, + payload: dict) +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> Optional[BoltResponse] +``` + +#### build\_listener + +```python +def build_listener( + listener_or_functions: Union[Listener, Callable, List[Callable]], + matchers: Optional[List[Union[ListenerMatcher, Callable[..., bool]]]] = None, + middleware: Optional[List[Middleware]] = None, + base_logger: Optional[Logger] = None) -> Listener +``` diff --git a/docs/english/reference/middleware/async_builtins.md b/docs/english/reference/middleware/async_builtins.md new file mode 100644 index 000000000..a0551284f --- /dev/null +++ b/docs/english/reference/middleware/async_builtins.md @@ -0,0 +1,143 @@ +--- +sidebar_label: async_builtins +title: slack_bolt.middleware.async_builtins +--- + +## AsyncIgnoringSelfEvents Objects + +```python +class AsyncIgnoringSelfEvents(IgnoringSelfEvents, AsyncMiddleware) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` + +## AsyncRequestVerification Objects + +```python +class AsyncRequestVerification(RequestVerification, AsyncMiddleware) +``` + +Verifies an incoming request by checking the validity of +`x-slack-signature`, `x-slack-request-timestamp`, and its body data. + +Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details. + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` + +## AsyncSslCheck Objects + +```python +class AsyncSslCheck(SslCheck, AsyncMiddleware) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` + +## AsyncUrlVerification Objects + +```python +class AsyncUrlVerification(UrlVerification, AsyncMiddleware) +``` + +#### \_\_init\_\_ + +```python +def __init__(base_logger: Optional[Logger] = None) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` + +## AsyncMessageListenerMatches Objects + +```python +class AsyncMessageListenerMatches(AsyncMiddleware) +``` + +#### \_\_init\_\_ + +```python +def __init__(keyword: Union[str, Pattern]) +``` + +Captures matched keywords and saves the values in context. + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` + +## AsyncAttachingFunctionToken Objects + +```python +class AsyncAttachingFunctionToken(AsyncMiddleware) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` + +## AsyncAttachingConversationKwargs Objects + +```python +class AsyncAttachingConversationKwargs(AsyncMiddleware) +``` + +#### thread\_context\_store: `Optional[AsyncAssistantThreadContextStore]` + +#### \_\_init\_\_ + +```python +def __init__(thread_context_store: Optional[AsyncAssistantThreadContextStore] = None) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> Optional[BoltResponse] +``` diff --git a/docs/english/reference/middleware/async_custom_middleware.md b/docs/english/reference/middleware/async_custom_middleware.md new file mode 100644 index 000000000..825532aef --- /dev/null +++ b/docs/english/reference/middleware/async_custom_middleware.md @@ -0,0 +1,45 @@ +--- +sidebar_label: async_custom_middleware +title: slack_bolt.middleware.async_custom_middleware +--- + +## AsyncCustomMiddleware Objects + +```python +class AsyncCustomMiddleware(AsyncMiddleware) +``` + +#### app\_name: `str` + +#### func: `Callable[..., Awaitable[Any]]` + +#### arg\_names: `MutableSequence[str]` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__( + *, + app_name: str, + func: Callable[..., Awaitable[Any]], + base_logger: Optional[Logger] = None) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` + +#### name + +```python +@property +def name() -> str +``` diff --git a/docs/english/reference/middleware/async_middleware.md b/docs/english/reference/middleware/async_middleware.md new file mode 100644 index 000000000..e8b729daa --- /dev/null +++ b/docs/english/reference/middleware/async_middleware.md @@ -0,0 +1,61 @@ +--- +sidebar_label: async_middleware +title: slack_bolt.middleware.async_middleware +--- + +## AsyncMiddleware Objects + +```python +class AsyncMiddleware() +``` + +A middleware can process request data before other middleware and listener functions. + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> Optional[BoltResponse] +``` + +Processes a request data before other middleware and listeners. +A middleware calls `next()` function if the chain should continue. + +```python +@app.middleware +async def simple_middleware(req, resp, next): + # do something here + await next() +``` + +This `async_process(req, resp, next)` method is supposed to be invoked only inside bolt-python. +If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead. + +```python +@app.middleware +async def simple_middleware(req, resp, next_): + # do something here + await next_() +``` + +**Arguments**: + +- `req` _AsyncBoltRequest_ - The incoming request +- `resp` _BoltResponse_ - The response +- `next` _Callable[[], Awaitable[BoltResponse]]_ - The function to tell the chain that it can continue + +**Returns**: + +- `Optional[BoltResponse]` - Processed response (optional) + +#### name + +```python +@property +def name() -> str +``` + +The name of this middleware diff --git a/docs/english/reference/middleware/async_middleware_error_handler.md b/docs/english/reference/middleware/async_middleware_error_handler.md new file mode 100644 index 000000000..acbe7b4e4 --- /dev/null +++ b/docs/english/reference/middleware/async_middleware_error_handler.md @@ -0,0 +1,69 @@ +--- +sidebar_label: async_middleware_error_handler +title: slack_bolt.middleware.async_middleware_error_handler +--- + +## AsyncMiddlewareErrorHandler Objects + +```python +class AsyncMiddlewareErrorHandler() +``` + +#### handle + +```python +async def handle( + error: Exception, + request: AsyncBoltRequest, + response: Optional[BoltResponse]) -> None +``` + +Handles an unhandled exception. + +**Arguments**: + +- `error` _Exception_ - The raised exception. +- `request` _AsyncBoltRequest_ - The request. +- `response` _Optional[BoltResponse]_ - The response. + +## AsyncCustomMiddlewareErrorHandler Objects + +```python +class AsyncCustomMiddlewareErrorHandler(AsyncMiddlewareErrorHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger, func: Callable[..., Awaitable[Optional[BoltResponse]]]) +``` + +#### handle + +```python +async def handle( + error: Exception, + request: AsyncBoltRequest, + response: Optional[BoltResponse]) -> None +``` + +## AsyncDefaultMiddlewareErrorHandler Objects + +```python +class AsyncDefaultMiddlewareErrorHandler(AsyncMiddlewareErrorHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger) +``` + +#### handle + +```python +async def handle( + error: Exception, + request: AsyncBoltRequest, + response: Optional[BoltResponse]) +``` diff --git a/docs/english/reference/middleware/attaching_conversation_kwargs/async_attaching_conversation_kwargs.md b/docs/english/reference/middleware/attaching_conversation_kwargs/async_attaching_conversation_kwargs.md new file mode 100644 index 000000000..e209ed415 --- /dev/null +++ b/docs/english/reference/middleware/attaching_conversation_kwargs/async_attaching_conversation_kwargs.md @@ -0,0 +1,28 @@ +--- +sidebar_label: async_attaching_conversation_kwargs +title: slack_bolt.middleware.attaching_conversation_kwargs.async_attaching_conversation_kwargs +--- + +## AsyncAttachingConversationKwargs Objects + +```python +class AsyncAttachingConversationKwargs(AsyncMiddleware) +``` + +#### thread\_context\_store: `Optional[AsyncAssistantThreadContextStore]` + +#### \_\_init\_\_ + +```python +def __init__(thread_context_store: Optional[AsyncAssistantThreadContextStore] = None) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> Optional[BoltResponse] +``` diff --git a/docs/english/reference/middleware/attaching_conversation_kwargs/attaching_conversation_kwargs.md b/docs/english/reference/middleware/attaching_conversation_kwargs/attaching_conversation_kwargs.md new file mode 100644 index 000000000..c3e38e7eb --- /dev/null +++ b/docs/english/reference/middleware/attaching_conversation_kwargs/attaching_conversation_kwargs.md @@ -0,0 +1,29 @@ +--- +sidebar_label: attaching_conversation_kwargs +title: slack_bolt.middleware.attaching_conversation_kwargs.attaching_conversation_kwargs +slug: attaching_conversation_kwargs +--- + +## AttachingConversationKwargs Objects + +```python +class AttachingConversationKwargs(Middleware) +``` + +#### thread\_context\_store: `Optional[AssistantThreadContextStore]` + +#### \_\_init\_\_ + +```python +def __init__(thread_context_store: Optional[AssistantThreadContextStore] = None) +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> Optional[BoltResponse] +``` diff --git a/docs/english/reference/middleware/attaching_conversation_kwargs/index.md b/docs/english/reference/middleware/attaching_conversation_kwargs/index.md new file mode 100644 index 000000000..3fa0850c1 --- /dev/null +++ b/docs/english/reference/middleware/attaching_conversation_kwargs/index.md @@ -0,0 +1,33 @@ +--- +sidebar_label: attaching_conversation_kwargs +title: slack_bolt.middleware.attaching_conversation_kwargs +--- + +## Submodules + +- [slack_bolt.middleware.attaching_conversation_kwargs.async_attaching_conversation_kwargs](/tools/bolt-python/reference/middleware/attaching_conversation_kwargs/async_attaching_conversation_kwargs) +- [slack_bolt.middleware.attaching_conversation_kwargs.attaching_conversation_kwargs](/tools/bolt-python/reference/middleware/attaching_conversation_kwargs/attaching_conversation_kwargs) + +## AttachingConversationKwargs Objects + +```python +class AttachingConversationKwargs(Middleware) +``` + +#### thread\_context\_store: `Optional[AssistantThreadContextStore]` + +#### \_\_init\_\_ + +```python +def __init__(thread_context_store: Optional[AssistantThreadContextStore] = None) +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> Optional[BoltResponse] +``` diff --git a/docs/english/reference/middleware/attaching_function_token/async_attaching_function_token.md b/docs/english/reference/middleware/attaching_function_token/async_attaching_function_token.md new file mode 100644 index 000000000..98f90a3f3 --- /dev/null +++ b/docs/english/reference/middleware/attaching_function_token/async_attaching_function_token.md @@ -0,0 +1,20 @@ +--- +sidebar_label: async_attaching_function_token +title: slack_bolt.middleware.attaching_function_token.async_attaching_function_token +--- + +## AsyncAttachingFunctionToken Objects + +```python +class AsyncAttachingFunctionToken(AsyncMiddleware) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/attaching_function_token/attaching_function_token.md b/docs/english/reference/middleware/attaching_function_token/attaching_function_token.md new file mode 100644 index 000000000..1670e92ae --- /dev/null +++ b/docs/english/reference/middleware/attaching_function_token/attaching_function_token.md @@ -0,0 +1,21 @@ +--- +sidebar_label: attaching_function_token +title: slack_bolt.middleware.attaching_function_token.attaching_function_token +slug: attaching_function_token +--- + +## AttachingFunctionToken Objects + +```python +class AttachingFunctionToken(Middleware) +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/attaching_function_token/index.md b/docs/english/reference/middleware/attaching_function_token/index.md new file mode 100644 index 000000000..48b531ef2 --- /dev/null +++ b/docs/english/reference/middleware/attaching_function_token/index.md @@ -0,0 +1,25 @@ +--- +sidebar_label: attaching_function_token +title: slack_bolt.middleware.attaching_function_token +--- + +## Submodules + +- [slack_bolt.middleware.attaching_function_token.async_attaching_function_token](/tools/bolt-python/reference/middleware/attaching_function_token/async_attaching_function_token) +- [slack_bolt.middleware.attaching_function_token.attaching_function_token](/tools/bolt-python/reference/middleware/attaching_function_token/attaching_function_token) + +## AttachingFunctionToken Objects + +```python +class AttachingFunctionToken(Middleware) +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/authorization/async_authorization.md b/docs/english/reference/middleware/authorization/async_authorization.md new file mode 100644 index 000000000..c583ddedc --- /dev/null +++ b/docs/english/reference/middleware/authorization/async_authorization.md @@ -0,0 +1,10 @@ +--- +sidebar_label: async_authorization +title: slack_bolt.middleware.authorization.async_authorization +--- + +## AsyncAuthorization Objects + +```python +class AsyncAuthorization(AsyncMiddleware, ABC) +``` diff --git a/docs/english/reference/middleware/authorization/async_internals.md b/docs/english/reference/middleware/authorization/async_internals.md new file mode 100644 index 000000000..c4ece204c --- /dev/null +++ b/docs/english/reference/middleware/authorization/async_internals.md @@ -0,0 +1,6 @@ +--- +sidebar_label: async_internals +title: slack_bolt.middleware.authorization.async_internals +--- + + diff --git a/docs/english/reference/middleware/authorization/async_multi_teams_authorization.md b/docs/english/reference/middleware/authorization/async_multi_teams_authorization.md new file mode 100644 index 000000000..4a9bf9c86 --- /dev/null +++ b/docs/english/reference/middleware/authorization/async_multi_teams_authorization.md @@ -0,0 +1,43 @@ +--- +sidebar_label: async_multi_teams_authorization +title: slack_bolt.middleware.authorization.async_multi_teams_authorization +--- + +## AsyncMultiTeamsAuthorization Objects + +```python +class AsyncMultiTeamsAuthorization(AsyncAuthorization) +``` + +#### authorize: `AsyncAuthorize` + +#### user\_token\_resolution: `str` + +#### \_\_init\_\_ + +```python +def __init__( + authorize: AsyncAuthorize, + base_logger: Optional[Logger] = None, + user_token_resolution: str = 'authed_user', + user_facing_authorize_error_message: Optional[str] = None) +``` + +Multi-workspace authorization. + +**Arguments**: + +- `authorize` _AsyncAuthorize_ - The function to authorize incoming requests from Slack. +- `base_logger` _Optional[Logger]_ - The base logger +- `user_token_resolution` _str_ - "authed_user" or "actor" +- `user_facing_authorize_error_message` _Optional[str]_ - The user-facing error message when installation is not found + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/authorization/async_single_team_authorization.md b/docs/english/reference/middleware/authorization/async_single_team_authorization.md new file mode 100644 index 000000000..0ab9b05f5 --- /dev/null +++ b/docs/english/reference/middleware/authorization/async_single_team_authorization.md @@ -0,0 +1,32 @@ +--- +sidebar_label: async_single_team_authorization +title: slack_bolt.middleware.authorization.async_single_team_authorization +--- + +## AsyncSingleTeamAuthorization Objects + +```python +class AsyncSingleTeamAuthorization(AsyncAuthorization) +``` + +#### \_\_init\_\_ + +```python +def __init__( + base_logger: Optional[Logger] = None, + user_facing_authorize_error_message: Optional[str] = None) +``` + +Single-workspace authorization. + +#### auth\_test\_result: `Optional[AsyncSlackResponse]` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/authorization/authorization.md b/docs/english/reference/middleware/authorization/authorization.md new file mode 100644 index 000000000..421f49eb5 --- /dev/null +++ b/docs/english/reference/middleware/authorization/authorization.md @@ -0,0 +1,11 @@ +--- +sidebar_label: authorization +title: slack_bolt.middleware.authorization.authorization +slug: authorization +--- + +## Authorization Objects + +```python +class Authorization(Middleware) +``` diff --git a/docs/english/reference/middleware/authorization/index.md b/docs/english/reference/middleware/authorization/index.md new file mode 100644 index 000000000..b85640618 --- /dev/null +++ b/docs/english/reference/middleware/authorization/index.md @@ -0,0 +1,94 @@ +--- +sidebar_label: authorization +title: slack_bolt.middleware.authorization +--- + +## Submodules + +- [slack_bolt.middleware.authorization.async_authorization](/tools/bolt-python/reference/middleware/authorization/async_authorization) +- [slack_bolt.middleware.authorization.async_internals](/tools/bolt-python/reference/middleware/authorization/async_internals) +- [slack_bolt.middleware.authorization.async_multi_teams_authorization](/tools/bolt-python/reference/middleware/authorization/async_multi_teams_authorization) +- [slack_bolt.middleware.authorization.async_single_team_authorization](/tools/bolt-python/reference/middleware/authorization/async_single_team_authorization) +- [slack_bolt.middleware.authorization.authorization](/tools/bolt-python/reference/middleware/authorization/authorization) +- [slack_bolt.middleware.authorization.internals](/tools/bolt-python/reference/middleware/authorization/internals) +- [slack_bolt.middleware.authorization.multi_teams_authorization](/tools/bolt-python/reference/middleware/authorization/multi_teams_authorization) +- [slack_bolt.middleware.authorization.single_team_authorization](/tools/bolt-python/reference/middleware/authorization/single_team_authorization) + +## Authorization Objects + +```python +class Authorization(Middleware) +``` + +## MultiTeamsAuthorization Objects + +```python +class MultiTeamsAuthorization(Authorization) +``` + +#### authorize: `Authorize` + +#### user\_token\_resolution: `str` + +#### \_\_init\_\_ + +```python +def __init__( + *, + authorize: Authorize, + base_logger: Optional[Logger] = None, + user_token_resolution: str = 'authed_user', + user_facing_authorize_error_message: Optional[str] = None) +``` + +Multi-workspace authorization. + +**Arguments**: + +- `authorize` _Authorize_ - The function to authorize incoming requests from Slack. +- `base_logger` _Optional[Logger]_ - The base logger +- `user_token_resolution` _str_ - "authed_user" or "actor" +- `user_facing_authorize_error_message` _Optional[str]_ - The user-facing error message when installation is not found + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` + +## SingleTeamAuthorization Objects + +```python +class SingleTeamAuthorization(Authorization) +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + auth_test_result: Optional[SlackResponse] = None, + base_logger: Optional[Logger] = None, + user_facing_authorize_error_message: Optional[str] = None) +``` + +Single-workspace authorization. + +**Arguments**: + +- `auth_test_result` _Optional[SlackResponse]_ - The initial `auth.test` API call result. +- `base_logger` _Optional[Logger]_ - The base logger + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/authorization/internals.md b/docs/english/reference/middleware/authorization/internals.md new file mode 100644 index 000000000..7309240da --- /dev/null +++ b/docs/english/reference/middleware/authorization/internals.md @@ -0,0 +1,6 @@ +--- +sidebar_label: internals +title: slack_bolt.middleware.authorization.internals +--- + +#### no\_auth\_test\_events diff --git a/docs/english/reference/middleware/authorization/multi_teams_authorization.md b/docs/english/reference/middleware/authorization/multi_teams_authorization.md new file mode 100644 index 000000000..ae8865577 --- /dev/null +++ b/docs/english/reference/middleware/authorization/multi_teams_authorization.md @@ -0,0 +1,44 @@ +--- +sidebar_label: multi_teams_authorization +title: slack_bolt.middleware.authorization.multi_teams_authorization +--- + +## MultiTeamsAuthorization Objects + +```python +class MultiTeamsAuthorization(Authorization) +``` + +#### authorize: `Authorize` + +#### user\_token\_resolution: `str` + +#### \_\_init\_\_ + +```python +def __init__( + *, + authorize: Authorize, + base_logger: Optional[Logger] = None, + user_token_resolution: str = 'authed_user', + user_facing_authorize_error_message: Optional[str] = None) +``` + +Multi-workspace authorization. + +**Arguments**: + +- `authorize` _Authorize_ - The function to authorize incoming requests from Slack. +- `base_logger` _Optional[Logger]_ - The base logger +- `user_token_resolution` _str_ - "authed_user" or "actor" +- `user_facing_authorize_error_message` _Optional[str]_ - The user-facing error message when installation is not found + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/authorization/single_team_authorization.md b/docs/english/reference/middleware/authorization/single_team_authorization.md new file mode 100644 index 000000000..99aadf51e --- /dev/null +++ b/docs/english/reference/middleware/authorization/single_team_authorization.md @@ -0,0 +1,37 @@ +--- +sidebar_label: single_team_authorization +title: slack_bolt.middleware.authorization.single_team_authorization +--- + +## SingleTeamAuthorization Objects + +```python +class SingleTeamAuthorization(Authorization) +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + auth_test_result: Optional[SlackResponse] = None, + base_logger: Optional[Logger] = None, + user_facing_authorize_error_message: Optional[str] = None) +``` + +Single-workspace authorization. + +**Arguments**: + +- `auth_test_result` _Optional[SlackResponse]_ - The initial `auth.test` API call result. +- `base_logger` _Optional[Logger]_ - The base logger + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/custom_middleware.md b/docs/english/reference/middleware/custom_middleware.md new file mode 100644 index 000000000..b65b9ee44 --- /dev/null +++ b/docs/english/reference/middleware/custom_middleware.md @@ -0,0 +1,41 @@ +--- +sidebar_label: custom_middleware +title: slack_bolt.middleware.custom_middleware +--- + +## CustomMiddleware Objects + +```python +class CustomMiddleware(Middleware) +``` + +#### app\_name: `str` + +#### func: `Callable[..., Any]` + +#### arg\_names: `MutableSequence[str]` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__(*, app_name: str, func: Callable, base_logger: Optional[Logger] = None) +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` + +#### name + +```python +@property +def name() -> str +``` diff --git a/docs/english/reference/middleware/ignoring_self_events/async_ignoring_self_events.md b/docs/english/reference/middleware/ignoring_self_events/async_ignoring_self_events.md new file mode 100644 index 000000000..a3eb92dc3 --- /dev/null +++ b/docs/english/reference/middleware/ignoring_self_events/async_ignoring_self_events.md @@ -0,0 +1,20 @@ +--- +sidebar_label: async_ignoring_self_events +title: slack_bolt.middleware.ignoring_self_events.async_ignoring_self_events +--- + +## AsyncIgnoringSelfEvents Objects + +```python +class AsyncIgnoringSelfEvents(IgnoringSelfEvents, AsyncMiddleware) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/ignoring_self_events/ignoring_self_events.md b/docs/english/reference/middleware/ignoring_self_events/ignoring_self_events.md new file mode 100644 index 000000000..816a153bb --- /dev/null +++ b/docs/english/reference/middleware/ignoring_self_events/ignoring_self_events.md @@ -0,0 +1,33 @@ +--- +sidebar_label: ignoring_self_events +title: slack_bolt.middleware.ignoring_self_events.ignoring_self_events +slug: ignoring_self_events +--- + +## IgnoringSelfEvents Objects + +```python +class IgnoringSelfEvents(Middleware) +``` + +#### \_\_init\_\_ + +```python +def __init__( + base_logger: Optional[logging.Logger] = None, + ignoring_self_assistant_message_events_enabled: bool = True) +``` + +Ignores the events generated by this bot user itself. + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` + +#### events\_that\_should\_be\_kept diff --git a/docs/english/reference/middleware/ignoring_self_events/index.md b/docs/english/reference/middleware/ignoring_self_events/index.md new file mode 100644 index 000000000..3d9badbbc --- /dev/null +++ b/docs/english/reference/middleware/ignoring_self_events/index.md @@ -0,0 +1,37 @@ +--- +sidebar_label: ignoring_self_events +title: slack_bolt.middleware.ignoring_self_events +--- + +## Submodules + +- [slack_bolt.middleware.ignoring_self_events.async_ignoring_self_events](/tools/bolt-python/reference/middleware/ignoring_self_events/async_ignoring_self_events) +- [slack_bolt.middleware.ignoring_self_events.ignoring_self_events](/tools/bolt-python/reference/middleware/ignoring_self_events/ignoring_self_events) + +## IgnoringSelfEvents Objects + +```python +class IgnoringSelfEvents(Middleware) +``` + +#### \_\_init\_\_ + +```python +def __init__( + base_logger: Optional[logging.Logger] = None, + ignoring_self_assistant_message_events_enabled: bool = True) +``` + +Ignores the events generated by this bot user itself. + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` + +#### events\_that\_should\_be\_kept diff --git a/docs/english/reference/middleware/index.md b/docs/english/reference/middleware/index.md new file mode 100644 index 000000000..2bd8d44b3 --- /dev/null +++ b/docs/english/reference/middleware/index.md @@ -0,0 +1,173 @@ +--- +sidebar_label: middleware +title: slack_bolt.middleware +--- + +A middleware processes request data and calls `next()` method +if the execution chain should continue running the following middleware. + +Middleware can be used globally before all listener executions. +It's also possible to run a middleware only for a particular listener. + +## Submodules + +- [slack_bolt.middleware.assistant](/tools/bolt-python/reference/middleware/assistant) +- [slack_bolt.middleware.async_builtins](/tools/bolt-python/reference/middleware/async_builtins) +- [slack_bolt.middleware.async_custom_middleware](/tools/bolt-python/reference/middleware/async_custom_middleware) +- [slack_bolt.middleware.async_middleware](/tools/bolt-python/reference/middleware/async_middleware) +- [slack_bolt.middleware.async_middleware_error_handler](/tools/bolt-python/reference/middleware/async_middleware_error_handler) +- [slack_bolt.middleware.attaching_conversation_kwargs](/tools/bolt-python/reference/middleware/attaching_conversation_kwargs) +- [slack_bolt.middleware.attaching_function_token](/tools/bolt-python/reference/middleware/attaching_function_token) +- [slack_bolt.middleware.authorization](/tools/bolt-python/reference/middleware/authorization) +- [slack_bolt.middleware.custom_middleware](/tools/bolt-python/reference/middleware/custom_middleware) +- [slack_bolt.middleware.ignoring_self_events](/tools/bolt-python/reference/middleware/ignoring_self_events) +- [slack_bolt.middleware.message_listener_matches](/tools/bolt-python/reference/middleware/message_listener_matches) +- [slack_bolt.middleware.middleware](/tools/bolt-python/reference/middleware/middleware) +- [slack_bolt.middleware.middleware_error_handler](/tools/bolt-python/reference/middleware/middleware_error_handler) +- [slack_bolt.middleware.request_verification](/tools/bolt-python/reference/middleware/request_verification) +- [slack_bolt.middleware.ssl_check](/tools/bolt-python/reference/middleware/ssl_check) +- [slack_bolt.middleware.url_verification](/tools/bolt-python/reference/middleware/url_verification) + +## SingleTeamAuthorization Objects + +```python +class SingleTeamAuthorization(Authorization) +``` + +## MultiTeamsAuthorization Objects + +```python +class MultiTeamsAuthorization(Authorization) +``` + +## CustomMiddleware Objects + +```python +class CustomMiddleware(Middleware) +``` + +#### app\_name: `str` + +#### func: `Callable[..., Any]` + +#### arg\_names: `MutableSequence[str]` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__(*, app_name: str, func: Callable, base_logger: Optional[Logger] = None) +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` + +#### name + +```python +@property +def name() -> str +``` + +## IgnoringSelfEvents Objects + +```python +class IgnoringSelfEvents(Middleware) +``` + +## Middleware Objects + +```python +class Middleware() +``` + +A middleware can process request data before other middleware and listener functions. + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> Optional[BoltResponse] +``` + +Processes a request data before other middleware and listeners. +A middleware calls `next()` function if the chain should continue. + +```python +@app.middleware +def simple_middleware(req, resp, next): + # do something here + next() +``` + +This `process(req, resp, next)` method is supposed to be invoked only inside bolt-python. +If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead. + +```python +@app.middleware +def simple_middleware(req, resp, next_): + # do something here + next_() +``` + +**Arguments**: + +- `req` _BoltRequest_ - The incoming request +- `resp` _BoltResponse_ - The response +- `next` _Callable[[], BoltResponse]_ - The function to tell the chain that it can continue + +**Returns**: + +- `Optional[BoltResponse]` - Processed response (optional) + +#### name + +```python +@property +def name() -> str +``` + +The name of this middleware + +## RequestVerification Objects + +```python +class RequestVerification(Middleware) +``` + +## SslCheck Objects + +```python +class SslCheck(Middleware) +``` + +## UrlVerification Objects + +```python +class UrlVerification(Middleware) +``` + +## AttachingFunctionToken Objects + +```python +class AttachingFunctionToken(Middleware) +``` + +## AttachingConversationKwargs Objects + +```python +class AttachingConversationKwargs(Middleware) +``` + +#### builtin\_middleware\_classes diff --git a/docs/english/reference/middleware/message_listener_matches/async_message_listener_matches.md b/docs/english/reference/middleware/message_listener_matches/async_message_listener_matches.md new file mode 100644 index 000000000..48a06af5e --- /dev/null +++ b/docs/english/reference/middleware/message_listener_matches/async_message_listener_matches.md @@ -0,0 +1,28 @@ +--- +sidebar_label: async_message_listener_matches +title: slack_bolt.middleware.message_listener_matches.async_message_listener_matches +--- + +## AsyncMessageListenerMatches Objects + +```python +class AsyncMessageListenerMatches(AsyncMiddleware) +``` + +#### \_\_init\_\_ + +```python +def __init__(keyword: Union[str, Pattern]) +``` + +Captures matched keywords and saves the values in context. + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/message_listener_matches/index.md b/docs/english/reference/middleware/message_listener_matches/index.md new file mode 100644 index 000000000..5e61fb235 --- /dev/null +++ b/docs/english/reference/middleware/message_listener_matches/index.md @@ -0,0 +1,33 @@ +--- +sidebar_label: message_listener_matches +title: slack_bolt.middleware.message_listener_matches +--- + +## Submodules + +- [slack_bolt.middleware.message_listener_matches.async_message_listener_matches](/tools/bolt-python/reference/middleware/message_listener_matches/async_message_listener_matches) +- [slack_bolt.middleware.message_listener_matches.message_listener_matches](/tools/bolt-python/reference/middleware/message_listener_matches/message_listener_matches) + +## MessageListenerMatches Objects + +```python +class MessageListenerMatches(Middleware) +``` + +#### \_\_init\_\_ + +```python +def __init__(keyword: Union[str, Pattern]) +``` + +Captures matched keywords and saves the values in context. + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/message_listener_matches/message_listener_matches.md b/docs/english/reference/middleware/message_listener_matches/message_listener_matches.md new file mode 100644 index 000000000..04536976d --- /dev/null +++ b/docs/english/reference/middleware/message_listener_matches/message_listener_matches.md @@ -0,0 +1,29 @@ +--- +sidebar_label: message_listener_matches +title: slack_bolt.middleware.message_listener_matches.message_listener_matches +slug: message_listener_matches +--- + +## MessageListenerMatches Objects + +```python +class MessageListenerMatches(Middleware) +``` + +#### \_\_init\_\_ + +```python +def __init__(keyword: Union[str, Pattern]) +``` + +Captures matched keywords and saves the values in context. + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/middleware.md b/docs/english/reference/middleware/middleware.md new file mode 100644 index 000000000..882f58492 --- /dev/null +++ b/docs/english/reference/middleware/middleware.md @@ -0,0 +1,62 @@ +--- +sidebar_label: middleware +title: slack_bolt.middleware.middleware +slug: middleware +--- + +## Middleware Objects + +```python +class Middleware() +``` + +A middleware can process request data before other middleware and listener functions. + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> Optional[BoltResponse] +``` + +Processes a request data before other middleware and listeners. +A middleware calls `next()` function if the chain should continue. + +```python +@app.middleware +def simple_middleware(req, resp, next): + # do something here + next() +``` + +This `process(req, resp, next)` method is supposed to be invoked only inside bolt-python. +If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead. + +```python +@app.middleware +def simple_middleware(req, resp, next_): + # do something here + next_() +``` + +**Arguments**: + +- `req` _BoltRequest_ - The incoming request +- `resp` _BoltResponse_ - The response +- `next` _Callable[[], BoltResponse]_ - The function to tell the chain that it can continue + +**Returns**: + +- `Optional[BoltResponse]` - Processed response (optional) + +#### name + +```python +@property +def name() -> str +``` + +The name of this middleware diff --git a/docs/english/reference/middleware/middleware_error_handler.md b/docs/english/reference/middleware/middleware_error_handler.md new file mode 100644 index 000000000..2cde0622b --- /dev/null +++ b/docs/english/reference/middleware/middleware_error_handler.md @@ -0,0 +1,63 @@ +--- +sidebar_label: middleware_error_handler +title: slack_bolt.middleware.middleware_error_handler +--- + +## MiddlewareErrorHandler Objects + +```python +class MiddlewareErrorHandler() +``` + +#### handle + +```python +def handle( + error: Exception, + request: BoltRequest, + response: Optional[BoltResponse]) -> None +``` + +Handles an unhandled exception. + +**Arguments**: + +- `error` _Exception_ - The raised exception. +- `request` _BoltRequest_ - The request. +- `response` _Optional[BoltResponse]_ - The response. + +## CustomMiddlewareErrorHandler Objects + +```python +class CustomMiddlewareErrorHandler(MiddlewareErrorHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger, func: Callable[..., Optional[BoltResponse]]) +``` + +#### handle + +```python +def handle(error: Exception, request: BoltRequest, response: Optional[BoltResponse]) +``` + +## DefaultMiddlewareErrorHandler Objects + +```python +class DefaultMiddlewareErrorHandler(MiddlewareErrorHandler) +``` + +#### \_\_init\_\_ + +```python +def __init__(logger: Logger) +``` + +#### handle + +```python +def handle(error: Exception, request: BoltRequest, response: Optional[BoltResponse]) +``` diff --git a/docs/english/reference/middleware/request_verification/async_request_verification.md b/docs/english/reference/middleware/request_verification/async_request_verification.md new file mode 100644 index 000000000..973e585a5 --- /dev/null +++ b/docs/english/reference/middleware/request_verification/async_request_verification.md @@ -0,0 +1,25 @@ +--- +sidebar_label: async_request_verification +title: slack_bolt.middleware.request_verification.async_request_verification +--- + +## AsyncRequestVerification Objects + +```python +class AsyncRequestVerification(RequestVerification, AsyncMiddleware) +``` + +Verifies an incoming request by checking the validity of +`x-slack-signature`, `x-slack-request-timestamp`, and its body data. + +Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details. + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/request_verification/index.md b/docs/english/reference/middleware/request_verification/index.md new file mode 100644 index 000000000..eb3da596f --- /dev/null +++ b/docs/english/reference/middleware/request_verification/index.md @@ -0,0 +1,48 @@ +--- +sidebar_label: request_verification +title: slack_bolt.middleware.request_verification +--- + +## Submodules + +- [slack_bolt.middleware.request_verification.async_request_verification](/tools/bolt-python/reference/middleware/request_verification/async_request_verification) +- [slack_bolt.middleware.request_verification.request_verification](/tools/bolt-python/reference/middleware/request_verification/request_verification) + +## RequestVerification Objects + +```python +class RequestVerification(Middleware) +``` + +#### \_\_init\_\_ + +```python +def __init__(signing_secret: str, base_logger: Optional[Logger] = None) +``` + +Verifies an incoming request by checking the validity of +`x-slack-signature`, `x-slack-request-timestamp`, and its body data. + +Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details. + +**Arguments**: + +- `signing_secret` _str_ - The signing secret +- `base_logger` _Optional[Logger]_ - The base logger + +#### verifier + +```python +@property +def verifier() -> SignatureVerifier +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/request_verification/request_verification.md b/docs/english/reference/middleware/request_verification/request_verification.md new file mode 100644 index 000000000..6c7b05ae9 --- /dev/null +++ b/docs/english/reference/middleware/request_verification/request_verification.md @@ -0,0 +1,44 @@ +--- +sidebar_label: request_verification +title: slack_bolt.middleware.request_verification.request_verification +slug: request_verification +--- + +## RequestVerification Objects + +```python +class RequestVerification(Middleware) +``` + +#### \_\_init\_\_ + +```python +def __init__(signing_secret: str, base_logger: Optional[Logger] = None) +``` + +Verifies an incoming request by checking the validity of +`x-slack-signature`, `x-slack-request-timestamp`, and its body data. + +Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details. + +**Arguments**: + +- `signing_secret` _str_ - The signing secret +- `base_logger` _Optional[Logger]_ - The base logger + +#### verifier + +```python +@property +def verifier() -> SignatureVerifier +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/ssl_check/async_ssl_check.md b/docs/english/reference/middleware/ssl_check/async_ssl_check.md new file mode 100644 index 000000000..c6b1ad56a --- /dev/null +++ b/docs/english/reference/middleware/ssl_check/async_ssl_check.md @@ -0,0 +1,20 @@ +--- +sidebar_label: async_ssl_check +title: slack_bolt.middleware.ssl_check.async_ssl_check +--- + +## AsyncSslCheck Objects + +```python +class AsyncSslCheck(SslCheck, AsyncMiddleware) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/ssl_check/index.md b/docs/english/reference/middleware/ssl_check/index.md new file mode 100644 index 000000000..f5aae567d --- /dev/null +++ b/docs/english/reference/middleware/ssl_check/index.md @@ -0,0 +1,46 @@ +--- +sidebar_label: ssl_check +title: slack_bolt.middleware.ssl_check +--- + +## Submodules + +- [slack_bolt.middleware.ssl_check.async_ssl_check](/tools/bolt-python/reference/middleware/ssl_check/async_ssl_check) +- [slack_bolt.middleware.ssl_check.ssl_check](/tools/bolt-python/reference/middleware/ssl_check/ssl_check) + +## SslCheck Objects + +```python +class SslCheck(Middleware) +``` + +#### verification\_token: `Optional[str]` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__( + verification_token: Optional[str] = None, + base_logger: Optional[Logger] = None) +``` + +Handles `ssl_check` requests. +Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details. + +**Arguments**: + +- `verification_token` _Optional[str]_ - The verification token to check + (optional as it's already deprecated - https://docs.slack.dev/authentication/verifying-requests-from-slack/#deprecation) +- `base_logger` _Optional[Logger]_ - The base logger + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/ssl_check/ssl_check.md b/docs/english/reference/middleware/ssl_check/ssl_check.md new file mode 100644 index 000000000..2c2ecc096 --- /dev/null +++ b/docs/english/reference/middleware/ssl_check/ssl_check.md @@ -0,0 +1,42 @@ +--- +sidebar_label: ssl_check +title: slack_bolt.middleware.ssl_check.ssl_check +slug: ssl_check +--- + +## SslCheck Objects + +```python +class SslCheck(Middleware) +``` + +#### verification\_token: `Optional[str]` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__( + verification_token: Optional[str] = None, + base_logger: Optional[Logger] = None) +``` + +Handles `ssl_check` requests. +Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details. + +**Arguments**: + +- `verification_token` _Optional[str]_ - The verification token to check + (optional as it's already deprecated - https://docs.slack.dev/authentication/verifying-requests-from-slack/#deprecation) +- `base_logger` _Optional[Logger]_ - The base logger + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/url_verification/async_url_verification.md b/docs/english/reference/middleware/url_verification/async_url_verification.md new file mode 100644 index 000000000..f74152f77 --- /dev/null +++ b/docs/english/reference/middleware/url_verification/async_url_verification.md @@ -0,0 +1,26 @@ +--- +sidebar_label: async_url_verification +title: slack_bolt.middleware.url_verification.async_url_verification +--- + +## AsyncUrlVerification Objects + +```python +class AsyncUrlVerification(UrlVerification, AsyncMiddleware) +``` + +#### \_\_init\_\_ + +```python +def __init__(base_logger: Optional[Logger] = None) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/url_verification/index.md b/docs/english/reference/middleware/url_verification/index.md new file mode 100644 index 000000000..ce2b8bd4f --- /dev/null +++ b/docs/english/reference/middleware/url_verification/index.md @@ -0,0 +1,39 @@ +--- +sidebar_label: url_verification +title: slack_bolt.middleware.url_verification +--- + +## Submodules + +- [slack_bolt.middleware.url_verification.async_url_verification](/tools/bolt-python/reference/middleware/url_verification/async_url_verification) +- [slack_bolt.middleware.url_verification.url_verification](/tools/bolt-python/reference/middleware/url_verification/url_verification) + +## UrlVerification Objects + +```python +class UrlVerification(Middleware) +``` + +#### \_\_init\_\_ + +```python +def __init__(base_logger: Optional[Logger] = None) +``` + +Handles url_verification requests. + +Refer to https://docs.slack.dev/reference/events/url_verification/ for details. + +**Arguments**: + +- `base_logger` _Optional[Logger]_ - The base logger + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/middleware/url_verification/url_verification.md b/docs/english/reference/middleware/url_verification/url_verification.md new file mode 100644 index 000000000..a54d70ba2 --- /dev/null +++ b/docs/english/reference/middleware/url_verification/url_verification.md @@ -0,0 +1,35 @@ +--- +sidebar_label: url_verification +title: slack_bolt.middleware.url_verification.url_verification +slug: url_verification +--- + +## UrlVerification Objects + +```python +class UrlVerification(Middleware) +``` + +#### \_\_init\_\_ + +```python +def __init__(base_logger: Optional[Logger] = None) +``` + +Handles url_verification requests. + +Refer to https://docs.slack.dev/reference/events/url_verification/ for details. + +**Arguments**: + +- `base_logger` _Optional[Logger]_ - The base logger + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> BoltResponse +``` diff --git a/docs/english/reference/oauth/async_callback_options.md b/docs/english/reference/oauth/async_callback_options.md new file mode 100644 index 000000000..344fad325 --- /dev/null +++ b/docs/english/reference/oauth/async_callback_options.md @@ -0,0 +1,98 @@ +--- +sidebar_label: async_callback_options +title: slack_bolt.oauth.async_callback_options +--- + +## AsyncSuccessArgs Objects + +```python +class AsyncSuccessArgs() +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + request: AsyncBoltRequest, + installation: Installation, + settings: AsyncOAuthSettings, + default: AsyncCallbackOptions) +``` + +The arguments for a success function. + +**Arguments**: + +- `request` _AsyncBoltRequest_ - The request. +- `installation` _Installation_ - The installation data. +- `settings` _AsyncOAuthSettings_ - The settings for Slack OAuth flow. +- `default` _AsyncCallbackOptions_ - The default `AsyncCallbackOptions`. + +## AsyncFailureArgs Objects + +```python +class AsyncFailureArgs() +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + request: AsyncBoltRequest, + reason: str, + error: Optional[Exception] = None, + suggested_status_code: int, + settings: AsyncOAuthSettings, + default: AsyncCallbackOptions) +``` + +The arguments for a failure function. + +**Arguments**: + +- `request` _AsyncBoltRequest_ - The request. +- `reason` _str_ - The response. +- `error` _Optional[Exception]_ - An exception if exists. +- `suggested_status_code` _int_ - The recommended HTTP status code for the failure. +- `settings` _AsyncOAuthSettings_ - The settings for Slack OAuth flow. +- `default` _AsyncCallbackOptions_ - The default `AsyncCallbackOptions`. + +## AsyncCallbackOptions Objects + +```python +class AsyncCallbackOptions() +``` + +#### success: `Callable[[AsyncSuccessArgs], Awaitable[BoltResponse]]` + +#### failure: `Callable[[AsyncFailureArgs], Awaitable[BoltResponse]]` + +#### \_\_init\_\_ + +```python +def __init__( + success: Callable[[AsyncSuccessArgs], Awaitable[BoltResponse]], + failure: Callable[[AsyncFailureArgs], Awaitable[BoltResponse]]) +``` + +## DefaultAsyncCallbackOptions Objects + +```python +class DefaultAsyncCallbackOptions(AsyncCallbackOptions) +``` + +#### success: `Callable[[AsyncSuccessArgs], Awaitable[BoltResponse]]` + +#### failure: `Callable[[AsyncFailureArgs], Awaitable[BoltResponse]]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + logger: Logger, + state_utils: OAuthStateUtils, + redirect_uri_page_renderer: RedirectUriPageRenderer) +``` diff --git a/docs/english/reference/oauth/async_internals.md b/docs/english/reference/oauth/async_internals.md new file mode 100644 index 000000000..e0e3d5098 --- /dev/null +++ b/docs/english/reference/oauth/async_internals.md @@ -0,0 +1,22 @@ +--- +sidebar_label: async_internals +title: slack_bolt.oauth.async_internals +--- + +#### default\_installation\_stores: `Dict[str, AsyncInstallationStore]` + +#### get\_or\_create\_default\_installation\_store + +```python +def get_or_create_default_installation_store(client_id: str) -> AsyncInstallationStore +``` + +#### select\_consistent\_installation\_store + +```python +def select_consistent_installation_store( + client_id: str, + app_store: Optional[AsyncInstallationStore], + oauth_flow_store: Optional[AsyncInstallationStore], + logger: Logger) -> Optional[AsyncInstallationStore] +``` diff --git a/docs/english/reference/oauth/async_oauth_flow.md b/docs/english/reference/oauth/async_oauth_flow.md new file mode 100644 index 000000000..49c49453d --- /dev/null +++ b/docs/english/reference/oauth/async_oauth_flow.md @@ -0,0 +1,127 @@ +--- +sidebar_label: async_oauth_flow +title: slack_bolt.oauth.async_oauth_flow +--- + +## AsyncOAuthFlow Objects + +```python +class AsyncOAuthFlow() +``` + +#### settings: `AsyncOAuthSettings` + +#### client\_id: `str` + +#### redirect\_uri: `Optional[str]` + +#### install\_path: `str` + +#### redirect\_uri\_path: `str` + +#### success\_handler: `Callable[[AsyncSuccessArgs], Awaitable[BoltResponse]]` + +#### failure\_handler: `Callable[[AsyncFailureArgs], Awaitable[BoltResponse]]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + client: Optional[AsyncWebClient] = None, + logger: Optional[Logger] = None, + settings: AsyncOAuthSettings) +``` + +The module to run the Slack app installation flow (OAuth flow). + +**Arguments**: + +- `client` _Optional[AsyncWebClient]_ - The `slack_sdk.web.async_client.AsyncWebClient` instance. +- `logger` _Optional[Logger]_ - The logger. +- `settings` _AsyncOAuthSettings_ - OAuth settings to configure this module. + +#### client + +```python +@property +def client() -> AsyncWebClient +``` + +#### logger + +```python +@property +def logger() -> Logger +``` + +#### sqlite3 + +```python +def sqlite3( + database: str, + authorization_url: Optional[str] = None, + client_id: Optional[str] = None, + client_secret: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + user_scopes: Optional[Sequence[str]] = None, + redirect_uri: Optional[str] = None, + install_path: Optional[str] = None, + redirect_uri_path: Optional[str] = None, + callback_options: Optional[AsyncCallbackOptions] = None, + success_url: Optional[str] = None, + failure_url: Optional[str] = None, + state_cookie_name: str = OAuthStateUtils.default_cookie_name, + state_expiration_seconds: int = OAuthStateUtils.default_expiration_seconds, + installation_store_bot_only: bool = False, + client: Optional[AsyncWebClient] = None, + logger: Optional[Logger] = None) -> AsyncOAuthFlow +``` + +#### handle\_installation + +```python +async def handle_installation(request: AsyncBoltRequest) -> BoltResponse +``` + +#### issue\_new\_state + +```python +async def issue_new_state(request: AsyncBoltRequest) -> str +``` + +#### build\_authorize\_url + +```python +async def build_authorize_url(state: str, request: AsyncBoltRequest) -> str +``` + +#### build\_install\_page\_html + +```python +async def build_install_page_html(url: str, request: AsyncBoltRequest) -> str +``` + +#### append\_set\_cookie\_headers + +```python +async def append_set_cookie_headers(headers: dict, set_cookie_value: Optional[str]) +``` + +#### handle\_callback + +```python +async def handle_callback(request: AsyncBoltRequest) -> BoltResponse +``` + +#### run\_installation + +```python +async def run_installation(code: str) -> Optional[Installation] +``` + +#### store\_installation + +```python +async def store_installation(request: AsyncBoltRequest, installation: Installation) +``` diff --git a/docs/english/reference/oauth/async_oauth_settings.md b/docs/english/reference/oauth/async_oauth_settings.md new file mode 100644 index 000000000..fca5fd18f --- /dev/null +++ b/docs/english/reference/oauth/async_oauth_settings.md @@ -0,0 +1,118 @@ +--- +sidebar_label: async_oauth_settings +title: slack_bolt.oauth.async_oauth_settings +--- + +## AsyncOAuthSettings Objects + +```python +class AsyncOAuthSettings() +``` + +#### client\_id: `str` + +#### client\_secret: `str` + +#### scopes: `Optional[Sequence[str]]` + +#### user\_scopes: `Optional[Sequence[str]]` + +#### redirect\_uri: `Optional[str]` + +#### install\_path: `str` + +#### install\_page\_rendering\_enabled: `bool` + +#### redirect\_uri\_path: `str` + +#### callback\_options: `Optional[AsyncCallbackOptions]` + +#### success\_url: `Optional[str]` + +#### failure\_url: `Optional[str]` + +#### authorization\_url: `str` + +#### installation\_store: `AsyncInstallationStore` + +#### installation\_store\_bot\_only: `bool` + +#### token\_rotation\_expiration\_minutes: `int` + +#### user\_token\_resolution: `str` + +#### authorize: `AsyncAuthorize` + +#### state\_validation\_enabled: `bool` + +#### state\_store: `AsyncOAuthStateStore` + +#### state\_cookie\_name: `str` + +#### state\_expiration\_seconds: `int` + +#### state\_utils: `OAuthStateUtils` + +#### authorize\_url\_generator: `AuthorizeUrlGenerator` + +#### redirect\_uri\_page\_renderer: `RedirectUriPageRenderer` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__( + *, + client_id: Optional[str] = None, + client_secret: Optional[str] = None, + scopes: Optional[Union[Sequence[str], str]] = None, + user_scopes: Optional[Union[Sequence[str], str]] = None, + redirect_uri: Optional[str] = None, + install_path: str = '/slack/install', + install_page_rendering_enabled: bool = True, + redirect_uri_path: str = '/slack/oauth_redirect', + callback_options: Optional[AsyncCallbackOptions] = None, + success_url: Optional[str] = None, + failure_url: Optional[str] = None, + authorization_url: Optional[str] = None, + installation_store: Optional[AsyncInstallationStore] = None, + installation_store_bot_only: bool = False, + token_rotation_expiration_minutes: int = 120, + user_token_resolution: str = 'authed_user', + state_validation_enabled: bool = True, + state_store: Optional[AsyncOAuthStateStore] = None, + state_cookie_name: str = OAuthStateUtils.default_cookie_name, + state_expiration_seconds: int = OAuthStateUtils.default_expiration_seconds, + logger: Logger = logging.getLogger(__name__)) +``` + +The settings for Slack App installation (OAuth flow). + +**Arguments**: + +- `client_id` _Optional[str]_ - Check the value in Settings > Basic Information > App Credentials +- `client_secret` _Optional[str]_ - Check the value in Settings > Basic Information > App Credentials +- `scopes` _Optional[Union[Sequence[str], str]]_ - Check the value in Settings > Manage Distribution +- `user_scopes` _Optional[Union[Sequence[str], str]]_ - Check the value in Settings > Manage Distribution +- `redirect_uri` _Optional[str]_ - Check the value in Features > OAuth & Permissions > Redirect URLs +- `install_path` _str_ - The endpoint to start an OAuth flow (Default: `/slack/install`) +- `install_page_rendering_enabled` _bool_ - Renders a web page for install_path access if True +- `redirect_uri_path` _str_ - The path of Redirect URL (Default: `/slack/oauth_redirect`) +- `callback_options` _Optional[AsyncCallbackOptions]_ - Give success/failure functions f you want to customize callback functions. +- `success_url` _Optional[str]_ - Set a complete URL if you want to redirect end-users when an installation completes. +- `failure_url` _Optional[str]_ - Set a complete URL if you want to redirect end-users when an installation fails. +- `authorization_url` _Optional[str]_ - Set a URL if you want to customize the URL `https://slack.com/oauth/v2/authorize` +- `installation_store` _Optional[AsyncInstallationStore]_ - Specify the instance of `InstallationStore` (Default: `FileInstallationStore`) +- `installation_store_bot_only` _bool_ - Use `InstallationStore#find_bot()` if True (Default: False) +- `token_rotation_expiration_minutes` _int_ - Minutes before refreshing tokens (Default: 2 hours) +- `user_token_resolution` _str_ - The option to pick up a user token per request (Default: authed_user) + The available values are "authed_user" and "actor". When you want to resolve the user token per request + using the event's actor IDs, you can set "actor" instead. With this option, bolt-python tries to resolve + a user token for context.actor_enterprise/team/user_id. This can be useful for events in Slack Connect + channels. Note that actor IDs can be absent in some scenarios. +- `state_validation_enabled` _bool_ - Set False if your OAuth flow omits the state parameter validation (Default: True) +- `state_store` _Optional[AsyncOAuthStateStore]_ - Specify the instance of `InstallationStore` (Default: `FileOAuthStateStore`) +- `state_cookie_name` _str_ - The cookie name that is set for installers' browser. (Default: "slack-app-oauth-state") +- `state_expiration_seconds` _int_ - The seconds that the state value is alive (Default: 600 seconds) +- `logger` _Logger_ - The logger that will be used internally diff --git a/docs/english/reference/oauth/callback_options.md b/docs/english/reference/oauth/callback_options.md new file mode 100644 index 000000000..44ff7fcbb --- /dev/null +++ b/docs/english/reference/oauth/callback_options.md @@ -0,0 +1,105 @@ +--- +sidebar_label: callback_options +title: slack_bolt.oauth.callback_options +--- + +## SuccessArgs Objects + +```python +class SuccessArgs() +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + request: BoltRequest, + installation: Installation, + settings: OAuthSettings, + default: CallbackOptions) +``` + +The arguments for a success function. + +**Arguments**: + +- `request` _BoltRequest_ - The request. +- `installation` _Installation_ - The installation data. +- `settings` _OAuthSettings_ - The settings for Slack OAuth flow. +- `default` _CallbackOptions_ - The default `CallbackOptions` + +## FailureArgs Objects + +```python +class FailureArgs() +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + request: BoltRequest, + reason: str, + error: Optional[Exception] = None, + suggested_status_code: int, + settings: OAuthSettings, + default: CallbackOptions) +``` + +The arguments for a failure function. + +**Arguments**: + +- `request` _BoltRequest_ - The request. +- `reason` _str_ - The response. +- `error` _Optional[Exception]_ - An exception if exists. +- `suggested_status_code` _int_ - The recommended HTTP status code for the failure. +- `settings` _OAuthSettings_ - The settings for Slack OAuth flow. +- `default` _CallbackOptions_ - The default `CallbackOptions`. + +## CallbackOptions Objects + +```python +class CallbackOptions() +``` + +#### success: `Callable[[SuccessArgs], BoltResponse]` + +#### failure: `Callable[[FailureArgs], BoltResponse]` + +#### \_\_init\_\_ + +```python +def __init__( + success: Callable[[SuccessArgs], BoltResponse], + failure: Callable[[FailureArgs], BoltResponse]) +``` + +The configurations for OAuth flow. + +**Arguments**: + +- `success` _Callable[[SuccessArgs], BoltResponse]_ - A handler for successful installation. +- `failure` _Callable[[FailureArgs], BoltResponse]_ - A handler for any types of installation failures. + +## DefaultCallbackOptions Objects + +```python +class DefaultCallbackOptions(CallbackOptions) +``` + +#### success: `Callable[[SuccessArgs], BoltResponse]` + +#### failure: `Callable[[FailureArgs], BoltResponse]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + logger: Logger, + state_utils: OAuthStateUtils, + redirect_uri_page_renderer: RedirectUriPageRenderer) +``` diff --git a/docs/english/reference/oauth/index.md b/docs/english/reference/oauth/index.md new file mode 100644 index 000000000..29fa841a6 --- /dev/null +++ b/docs/english/reference/oauth/index.md @@ -0,0 +1,143 @@ +--- +sidebar_label: oauth +title: slack_bolt.oauth +--- + +Slack OAuth flow support for building an app that is installable in any workspaces. + +Refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth for details. + +## Submodules + +- [slack_bolt.oauth.async_callback_options](/tools/bolt-python/reference/oauth/async_callback_options) +- [slack_bolt.oauth.async_internals](/tools/bolt-python/reference/oauth/async_internals) +- [slack_bolt.oauth.async_oauth_flow](/tools/bolt-python/reference/oauth/async_oauth_flow) +- [slack_bolt.oauth.async_oauth_settings](/tools/bolt-python/reference/oauth/async_oauth_settings) +- [slack_bolt.oauth.callback_options](/tools/bolt-python/reference/oauth/callback_options) +- [slack_bolt.oauth.internals](/tools/bolt-python/reference/oauth/internals) +- [slack_bolt.oauth.oauth_flow](/tools/bolt-python/reference/oauth/oauth_flow) +- [slack_bolt.oauth.oauth_settings](/tools/bolt-python/reference/oauth/oauth_settings) + +## OAuthFlow Objects + +```python +class OAuthFlow() +``` + +#### settings: `OAuthSettings` + +#### client\_id: `str` + +#### redirect\_uri: `Optional[str]` + +#### install\_path: `str` + +#### redirect\_uri\_path: `str` + +#### success\_handler: `Callable[[SuccessArgs], BoltResponse]` + +#### failure\_handler: `Callable[[FailureArgs], BoltResponse]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + client: Optional[WebClient] = None, + logger: Optional[Logger] = None, + settings: OAuthSettings) +``` + +The module to run the Slack app installation flow (OAuth flow). + +**Arguments**: + +- `client` _Optional[WebClient]_ - The `slack_sdk.web.WebClient` instance. +- `logger` _Optional[Logger]_ - The logger. +- `settings` _OAuthSettings_ - OAuth settings to configure this module. + +#### client + +```python +@property +def client() -> WebClient +``` + +#### logger + +```python +@property +def logger() -> Logger +``` + +#### sqlite3 + +```python +def sqlite3( + database: str, + client_id: Optional[str] = None, + client_secret: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + user_scopes: Optional[Sequence[str]] = None, + redirect_uri: Optional[str] = None, + install_path: Optional[str] = None, + redirect_uri_path: Optional[str] = None, + callback_options: Optional[CallbackOptions] = None, + success_url: Optional[str] = None, + failure_url: Optional[str] = None, + authorization_url: Optional[str] = None, + state_cookie_name: str = OAuthStateUtils.default_cookie_name, + state_expiration_seconds: int = OAuthStateUtils.default_expiration_seconds, + installation_store_bot_only: bool = False, + token_rotation_expiration_minutes: int = 120, + client: Optional[WebClient] = None, + logger: Optional[Logger] = None) -> OAuthFlow +``` + +#### handle\_installation + +```python +def handle_installation(request: BoltRequest) -> BoltResponse +``` + +#### issue\_new\_state + +```python +def issue_new_state(request: BoltRequest) -> str +``` + +#### build\_authorize\_url + +```python +def build_authorize_url(state: str, request: BoltRequest) -> str +``` + +#### build\_install\_page\_html + +```python +def build_install_page_html(url: str, request: BoltRequest) -> str +``` + +#### append\_set\_cookie\_headers + +```python +def append_set_cookie_headers(headers: dict, set_cookie_value: Optional[str]) +``` + +#### handle\_callback + +```python +def handle_callback(request: BoltRequest) -> BoltResponse +``` + +#### run\_installation + +```python +def run_installation(code: str) -> Optional[Installation] +``` + +#### store\_installation + +```python +def store_installation(request: BoltRequest, installation: Installation) +``` diff --git a/docs/english/reference/oauth/internals.md b/docs/english/reference/oauth/internals.md new file mode 100644 index 000000000..34c9fc7ce --- /dev/null +++ b/docs/english/reference/oauth/internals.md @@ -0,0 +1,44 @@ +--- +sidebar_label: internals +title: slack_bolt.oauth.internals +--- + +## CallbackResponseBuilder Objects + +```python +class CallbackResponseBuilder() +``` + +#### \_\_init\_\_ + +```python +def __init__( + *, + logger: Logger, + state_utils: OAuthStateUtils, + redirect_uri_page_renderer: RedirectUriPageRenderer) +``` + +#### default\_installation\_stores: `Dict[str, InstallationStore]` + +#### get\_or\_create\_default\_installation\_store + +```python +def get_or_create_default_installation_store(client_id: str) -> InstallationStore +``` + +#### select\_consistent\_installation\_store + +```python +def select_consistent_installation_store( + client_id: str, + app_store: Optional[InstallationStore], + oauth_flow_store: Optional[InstallationStore], + logger: Logger) -> Optional[InstallationStore] +``` + +#### build\_detailed\_error + +```python +def build_detailed_error(reason: str) -> str +``` diff --git a/docs/english/reference/oauth/oauth_flow.md b/docs/english/reference/oauth/oauth_flow.md new file mode 100644 index 000000000..76e74b02d --- /dev/null +++ b/docs/english/reference/oauth/oauth_flow.md @@ -0,0 +1,128 @@ +--- +sidebar_label: oauth_flow +title: slack_bolt.oauth.oauth_flow +--- + +## OAuthFlow Objects + +```python +class OAuthFlow() +``` + +#### settings: `OAuthSettings` + +#### client\_id: `str` + +#### redirect\_uri: `Optional[str]` + +#### install\_path: `str` + +#### redirect\_uri\_path: `str` + +#### success\_handler: `Callable[[SuccessArgs], BoltResponse]` + +#### failure\_handler: `Callable[[FailureArgs], BoltResponse]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + client: Optional[WebClient] = None, + logger: Optional[Logger] = None, + settings: OAuthSettings) +``` + +The module to run the Slack app installation flow (OAuth flow). + +**Arguments**: + +- `client` _Optional[WebClient]_ - The `slack_sdk.web.WebClient` instance. +- `logger` _Optional[Logger]_ - The logger. +- `settings` _OAuthSettings_ - OAuth settings to configure this module. + +#### client + +```python +@property +def client() -> WebClient +``` + +#### logger + +```python +@property +def logger() -> Logger +``` + +#### sqlite3 + +```python +def sqlite3( + database: str, + client_id: Optional[str] = None, + client_secret: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + user_scopes: Optional[Sequence[str]] = None, + redirect_uri: Optional[str] = None, + install_path: Optional[str] = None, + redirect_uri_path: Optional[str] = None, + callback_options: Optional[CallbackOptions] = None, + success_url: Optional[str] = None, + failure_url: Optional[str] = None, + authorization_url: Optional[str] = None, + state_cookie_name: str = OAuthStateUtils.default_cookie_name, + state_expiration_seconds: int = OAuthStateUtils.default_expiration_seconds, + installation_store_bot_only: bool = False, + token_rotation_expiration_minutes: int = 120, + client: Optional[WebClient] = None, + logger: Optional[Logger] = None) -> OAuthFlow +``` + +#### handle\_installation + +```python +def handle_installation(request: BoltRequest) -> BoltResponse +``` + +#### issue\_new\_state + +```python +def issue_new_state(request: BoltRequest) -> str +``` + +#### build\_authorize\_url + +```python +def build_authorize_url(state: str, request: BoltRequest) -> str +``` + +#### build\_install\_page\_html + +```python +def build_install_page_html(url: str, request: BoltRequest) -> str +``` + +#### append\_set\_cookie\_headers + +```python +def append_set_cookie_headers(headers: dict, set_cookie_value: Optional[str]) +``` + +#### handle\_callback + +```python +def handle_callback(request: BoltRequest) -> BoltResponse +``` + +#### run\_installation + +```python +def run_installation(code: str) -> Optional[Installation] +``` + +#### store\_installation + +```python +def store_installation(request: BoltRequest, installation: Installation) +``` diff --git a/docs/english/reference/oauth/oauth_settings.md b/docs/english/reference/oauth/oauth_settings.md new file mode 100644 index 000000000..3f2793041 --- /dev/null +++ b/docs/english/reference/oauth/oauth_settings.md @@ -0,0 +1,118 @@ +--- +sidebar_label: oauth_settings +title: slack_bolt.oauth.oauth_settings +--- + +## OAuthSettings Objects + +```python +class OAuthSettings() +``` + +#### client\_id: `str` + +#### client\_secret: `str` + +#### scopes: `Optional[Sequence[str]]` + +#### user\_scopes: `Optional[Sequence[str]]` + +#### redirect\_uri: `Optional[str]` + +#### install\_path: `str` + +#### install\_page\_rendering\_enabled: `bool` + +#### redirect\_uri\_path: `str` + +#### callback\_options: `Optional[CallbackOptions]` + +#### success\_url: `Optional[str]` + +#### failure\_url: `Optional[str]` + +#### authorization\_url: `str` + +#### installation\_store: `InstallationStore` + +#### installation\_store\_bot\_only: `bool` + +#### token\_rotation\_expiration\_minutes: `int` + +#### authorize: `Authorize` + +#### user\_token\_resolution: `str` + +#### state\_validation\_enabled: `bool` + +#### state\_store: `OAuthStateStore` + +#### state\_cookie\_name: `str` + +#### state\_expiration\_seconds: `int` + +#### state\_utils: `OAuthStateUtils` + +#### authorize\_url\_generator: `AuthorizeUrlGenerator` + +#### redirect\_uri\_page\_renderer: `RedirectUriPageRenderer` + +#### logger: `Logger` + +#### \_\_init\_\_ + +```python +def __init__( + *, + client_id: Optional[str] = None, + client_secret: Optional[str] = None, + scopes: Optional[Union[Sequence[str], str]] = None, + user_scopes: Optional[Union[Sequence[str], str]] = None, + redirect_uri: Optional[str] = None, + install_path: str = '/slack/install', + install_page_rendering_enabled: bool = True, + redirect_uri_path: str = '/slack/oauth_redirect', + callback_options: Optional[CallbackOptions] = None, + success_url: Optional[str] = None, + failure_url: Optional[str] = None, + authorization_url: Optional[str] = None, + installation_store: Optional[InstallationStore] = None, + installation_store_bot_only: bool = False, + token_rotation_expiration_minutes: int = 120, + user_token_resolution: str = 'authed_user', + state_validation_enabled: bool = True, + state_store: Optional[OAuthStateStore] = None, + state_cookie_name: str = OAuthStateUtils.default_cookie_name, + state_expiration_seconds: int = OAuthStateUtils.default_expiration_seconds, + logger: Logger = logging.getLogger(__name__)) +``` + +The settings for Slack App installation (OAuth flow). + +**Arguments**: + +- `client_id` _Optional[str]_ - Check the value in Settings > Basic Information > App Credentials +- `client_secret` _Optional[str]_ - Check the value in Settings > Basic Information > App Credentials +- `scopes` _Optional[Union[Sequence[str], str]]_ - Check the value in Settings > Manage Distribution +- `user_scopes` _Optional[Union[Sequence[str], str]]_ - Check the value in Settings > Manage Distribution +- `redirect_uri` _Optional[str]_ - Check the value in Features > OAuth & Permissions > Redirect URLs +- `install_path` _str_ - The endpoint to start an OAuth flow (Default: `/slack/install`) +- `install_page_rendering_enabled` _bool_ - Renders a web page for install_path access if True +- `redirect_uri_path` _str_ - The path of Redirect URL (Default: `/slack/oauth_redirect`) +- `callback_options` _Optional[CallbackOptions]_ - Give success/failure functions f you want to customize callback functions. +- `success_url` _Optional[str]_ - Set a complete URL if you want to redirect end-users when an installation completes. +- `failure_url` _Optional[str]_ - Set a complete URL if you want to redirect end-users when an installation fails. +- `authorization_url` _Optional[str]_ - Set a URL if you want to customize the URL `https://slack.com/oauth/v2/authorize` +- `installation_store` _Optional[InstallationStore]_ - Specify the instance of `InstallationStore` (Default: `FileInstallationStore`) +- `installation_store_bot_only` _bool_ - Use `InstallationStore#find_bot()` if True (Default: False) +- `token_rotation_expiration_minutes` _int_ - Minutes before refreshing tokens (Default: 2 hours) +- `user_token_resolution` _str_ - The option to pick up a user token per request (Default: authed_user) + The available values are "authed_user" and "actor". When you want to resolve the user token per request + using the event's actor IDs, you can set "actor" instead. With this option, bolt-python tries to resolve + a user token for context.actor_enterprise/team/user_id. This can be useful for events in Slack Connect + channels. Note that actor IDs can be absent in some scenarios. +- `state_validation_enabled` _bool_ - Set False if your OAuth flow omits the state parameter validation (Default: True) +- `state_store` _Optional[OAuthStateStore]_ - Specify the instance of `InstallationStore` (Default: `FileOAuthStateStore`) +- `state_cookie_name` _str_ - The cookie name that is set for installers' browser. (Default: "slack-app-oauth-state") +- `state_expiration_seconds` _int_ - The seconds that the state value is alive (Default: 600 seconds) +- `logger` _Logger_ - The logger that will be used internally diff --git a/docs/english/reference/request/async_internals.md b/docs/english/reference/request/async_internals.md new file mode 100644 index 000000000..9bc9262d6 --- /dev/null +++ b/docs/english/reference/request/async_internals.md @@ -0,0 +1,12 @@ +--- +sidebar_label: async_internals +title: slack_bolt.request.async_internals +--- + +#### build\_async\_context + +```python +def build_async_context( + context: AsyncBoltContext, + body: Dict[str, Any]) -> AsyncBoltContext +``` diff --git a/docs/english/reference/request/async_request.md b/docs/english/reference/request/async_request.md new file mode 100644 index 000000000..5c5944970 --- /dev/null +++ b/docs/english/reference/request/async_request.md @@ -0,0 +1,56 @@ +--- +sidebar_label: async_request +title: slack_bolt.request.async_request +--- + +## AsyncBoltRequest Objects + +```python +class AsyncBoltRequest() +``` + +#### raw\_body: `str` + +#### body: `Dict[str, Any]` + +#### query: `Dict[str, Sequence[str]]` + +#### headers: `Dict[str, Sequence[str]]` + +#### content\_type: `Optional[str]` + +#### context: `AsyncBoltContext` + +#### lazy\_only: `bool` + +#### lazy\_function\_name: `Optional[str]` + +#### mode: `str` + +#### \_\_init\_\_ + +```python +def __init__( + *, + body: Union[str, dict], + query: Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]] = None, + headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None, + context: Optional[Dict[str, Any]] = None, + mode: str = 'http') +``` + +Request to a Bolt app. + +**Arguments**: + +- `body` _Union[str, dict]_ - The raw request body (only plain text is supported for "http" mode) +- `query` _Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]]_ - The query string data in any data format. +- `headers` _Optional[Dict[str, Union[str, Sequence[str]]]]_ - The request headers. +- `context` _Optional[Dict[str, Any]]_ - The context in this request. +- `mode` _str_ - The mode used for this request. (either "http" or "socket_mode") + +#### to\_copyable + +```python +def to_copyable() -> AsyncBoltRequest +``` diff --git a/docs/english/reference/request/index.md b/docs/english/reference/request/index.md new file mode 100644 index 000000000..2a3e6d251 --- /dev/null +++ b/docs/english/reference/request/index.md @@ -0,0 +1,69 @@ +--- +sidebar_label: request +title: slack_bolt.request +--- + +Incoming request from Slack through either HTTP request or Socket Mode connection. + +Refer to https://docs.slack.dev/apis/events-api/ for the two types of connections. +This interface encapsulates the difference between the two. + +## Submodules + +- [slack_bolt.request.async_internals](/tools/bolt-python/reference/request/async_internals) +- [slack_bolt.request.async_request](/tools/bolt-python/reference/request/async_request) +- [slack_bolt.request.internals](/tools/bolt-python/reference/request/internals) +- [slack_bolt.request.payload_utils](/tools/bolt-python/reference/request/payload_utils) +- [slack_bolt.request.request](/tools/bolt-python/reference/request/request) + +## BoltRequest Objects + +```python +class BoltRequest() +``` + +#### raw\_body: `str` + +#### query: `Dict[str, Sequence[str]]` + +#### headers: `Dict[str, Sequence[str]]` + +#### content\_type: `Optional[str]` + +#### body: `Dict[str, Any]` + +#### context: `BoltContext` + +#### lazy\_only: `bool` + +#### lazy\_function\_name: `Optional[str]` + +#### mode: `str` + +#### \_\_init\_\_ + +```python +def __init__( + *, + body: Union[str, dict], + query: Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]] = None, + headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None, + context: Optional[Dict[str, Any]] = None, + mode: str = 'http') +``` + +Request to a Bolt app. + +**Arguments**: + +- `body` _Union[str, dict]_ - The raw request body (only plain text is supported for "http" mode) +- `query` _Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]]_ - The query string data in any data format. +- `headers` _Optional[Dict[str, Union[str, Sequence[str]]]]_ - The request headers. +- `context` _Optional[Dict[str, Any]]_ - The context in this request. +- `mode` _str_ - The mode used for this request. (either "http" or "socket_mode") + +#### to\_copyable + +```python +def to_copyable() -> BoltRequest +``` diff --git a/docs/english/reference/request/internals.md b/docs/english/reference/request/internals.md new file mode 100644 index 000000000..321deec77 --- /dev/null +++ b/docs/english/reference/request/internals.md @@ -0,0 +1,120 @@ +--- +sidebar_label: internals +title: slack_bolt.request.internals +--- + +#### parse\_query + +```python +def parse_query( + query: Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]]) -> Dict[str, Sequence[str]] +``` + +#### parse\_body + +```python +def parse_body(body: str, content_type: Optional[str]) -> Dict[str, Any] +``` + +#### extract\_is\_enterprise\_install + +```python +def extract_is_enterprise_install(payload: Dict[str, Any]) -> Optional[bool] +``` + +#### extract\_enterprise\_id + +```python +def extract_enterprise_id(payload: Dict[str, Any]) -> Optional[str] +``` + +#### extract\_actor\_enterprise\_id + +```python +def extract_actor_enterprise_id(payload: Dict[str, Any]) -> Optional[str] +``` + +#### extract\_team\_id + +```python +def extract_team_id(payload: Dict[str, Any]) -> Optional[str] +``` + +#### extract\_actor\_team\_id + +```python +def extract_actor_team_id(payload: Dict[str, Any]) -> Optional[str] +``` + +#### extract\_user\_id + +```python +def extract_user_id(payload: Dict[str, Any]) -> Optional[str] +``` + +#### extract\_actor\_user\_id + +```python +def extract_actor_user_id(payload: Dict[str, Any]) -> Optional[str] +``` + +#### extract\_channel\_id + +```python +def extract_channel_id(payload: Dict[str, Any]) -> Optional[str] +``` + +#### extract\_thread\_ts + +```python +def extract_thread_ts(payload: Dict[str, Any]) -> Optional[str] +``` + +#### extract\_function\_execution\_id + +```python +def extract_function_execution_id(payload: Dict[str, Any]) -> Optional[str] +``` + +#### extract\_function\_bot\_access\_token + +```python +def extract_function_bot_access_token(payload: Dict[str, Any]) -> Optional[str] +``` + +#### extract\_function\_inputs + +```python +def extract_function_inputs(payload: Dict[str, Any]) -> Optional[Dict[str, Any]] +``` + +#### build\_context + +```python +def build_context(context: BoltContext, body: Dict[str, Any]) -> BoltContext +``` + +#### extract\_content\_type + +```python +def extract_content_type(headers: Dict[str, Sequence[str]]) -> Optional[str] +``` + +#### build\_normalized\_headers + +```python +def build_normalized_headers( + headers: Optional[Dict[str, Union[str, Sequence[str]]]]) -> Dict[str, Sequence[str]] +``` + +#### error\_message\_raw\_body\_required\_in\_http\_mode + +```python +def error_message_raw_body_required_in_http_mode() -> str +``` + +#### debug\_multiple\_response\_urls\_detected + +```python +def debug_multiple_response_urls_detected() -> str +``` diff --git a/docs/english/reference/request/payload_utils.md b/docs/english/reference/request/payload_utils.md new file mode 100644 index 000000000..cb7a62513 --- /dev/null +++ b/docs/english/reference/request/payload_utils.md @@ -0,0 +1,232 @@ +--- +sidebar_label: payload_utils +title: slack_bolt.request.payload_utils +--- + +#### to\_event + +```python +def to_event(body: Dict[str, Any]) -> Optional[Dict[str, Any]] +``` + +#### to\_message + +```python +def to_message(body: Dict[str, Any]) -> Optional[Dict[str, Any]] +``` + +#### is\_function + +```python +def is_function(body: Dict[str, Any]) -> bool +``` + +#### is\_event + +```python +def is_event(body: Dict[str, Any]) -> bool +``` + +#### is\_workflow\_step\_execute + +```python +def is_workflow_step_execute(body: Dict[str, Any]) -> bool +``` + +#### is\_message\_event + +```python +def is_message_event(body: Dict[str, Any]) -> bool +``` + +#### is\_any\_im\_message\_event + +```python +def is_any_im_message_event(body: Dict[str, Any]) -> bool +``` + +#### is\_im\_message\_event + +```python +def is_im_message_event(body: Dict[str, Any]) -> bool +``` + +#### is\_assistant\_event + +```python +def is_assistant_event(body: Dict[str, Any]) -> bool +``` + +#### is\_assistant\_thread\_started\_event + +```python +def is_assistant_thread_started_event(body: Dict[str, Any]) -> bool +``` + +#### is\_assistant\_thread\_context\_changed\_event + +```python +def is_assistant_thread_context_changed_event(body: Dict[str, Any]) -> bool +``` + +#### is\_app\_home\_opened\_event + +```python +def is_app_home_opened_event(body: Dict[str, Any], tab: Optional[str] = None) -> bool +``` + +#### is\_user\_message\_event\_in\_assistant\_thread + +```python +def is_user_message_event_in_assistant_thread(body: Dict[str, Any]) -> bool +``` + +#### is\_bot\_message\_event\_in\_assistant\_thread + +```python +def is_bot_message_event_in_assistant_thread(body: Dict[str, Any]) -> bool +``` + +#### is\_other\_message\_sub\_event\_in\_assistant\_thread + +```python +def is_other_message_sub_event_in_assistant_thread(body: Dict[str, Any]) -> bool +``` + +#### to\_command + +```python +def to_command(body: Dict[str, Any]) -> Optional[Dict[str, Any]] +``` + +#### is\_slash\_command + +```python +def is_slash_command(body: Dict[str, Any]) -> bool +``` + +#### to\_action + +```python +def to_action(body: Dict[str, Any]) -> Optional[Dict[str, Any]] +``` + +#### is\_action + +```python +def is_action(body: Dict[str, Any]) -> bool +``` + +#### is\_attachment\_action + +```python +def is_attachment_action(body: Dict[str, Any]) -> bool +``` + +#### is\_block\_actions + +```python +def is_block_actions(body: Dict[str, Any]) -> bool +``` + +#### is\_dialog\_submission + +```python +def is_dialog_submission(body: Dict[str, Any]) -> bool +``` + +#### is\_dialog\_cancellation + +```python +def is_dialog_cancellation(body: Dict[str, Any]) -> bool +``` + +#### is\_workflow\_step\_edit + +```python +def is_workflow_step_edit(body: Dict[str, Any]) -> bool +``` + +#### to\_options + +```python +def to_options(body: Dict[str, Any]) -> Optional[Dict[str, Any]] +``` + +#### is\_options + +```python +def is_options(body: Dict[str, Any]) -> bool +``` + +#### is\_block\_suggestion + +```python +def is_block_suggestion(body: Dict[str, Any]) -> bool +``` + +#### is\_dialog\_suggestion + +```python +def is_dialog_suggestion(body: Dict[str, Any]) -> bool +``` + +#### to\_shortcut + +```python +def to_shortcut(body: Dict[str, Any]) -> Optional[Dict[str, Any]] +``` + +#### is\_shortcut + +```python +def is_shortcut(body: Dict[str, Any]) -> bool +``` + +#### is\_global\_shortcut + +```python +def is_global_shortcut(body: Dict[str, Any]) -> bool +``` + +#### is\_message\_shortcut + +```python +def is_message_shortcut(body: Dict[str, Any]) -> bool +``` + +#### to\_view + +```python +def to_view(body: Dict[str, Any]) -> Optional[Dict[str, Any]] +``` + +#### is\_view + +```python +def is_view(body: Dict[str, Any]) -> bool +``` + +#### is\_view\_submission + +```python +def is_view_submission(body: Dict[str, Any]) -> bool +``` + +#### is\_view\_closed + +```python +def is_view_closed(body: Dict[str, Any]) -> bool +``` + +#### is\_workflow\_step\_save + +```python +def is_workflow_step_save(body: Dict[str, Any]) -> bool +``` + +#### to\_step + +```python +def to_step(body: Dict[str, Any]) -> Optional[Dict[str, Any]] +``` diff --git a/docs/english/reference/request/request.md b/docs/english/reference/request/request.md new file mode 100644 index 000000000..e1434a781 --- /dev/null +++ b/docs/english/reference/request/request.md @@ -0,0 +1,57 @@ +--- +sidebar_label: request +title: slack_bolt.request.request +slug: request +--- + +## BoltRequest Objects + +```python +class BoltRequest() +``` + +#### raw\_body: `str` + +#### query: `Dict[str, Sequence[str]]` + +#### headers: `Dict[str, Sequence[str]]` + +#### content\_type: `Optional[str]` + +#### body: `Dict[str, Any]` + +#### context: `BoltContext` + +#### lazy\_only: `bool` + +#### lazy\_function\_name: `Optional[str]` + +#### mode: `str` + +#### \_\_init\_\_ + +```python +def __init__( + *, + body: Union[str, dict], + query: Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]] = None, + headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None, + context: Optional[Dict[str, Any]] = None, + mode: str = 'http') +``` + +Request to a Bolt app. + +**Arguments**: + +- `body` _Union[str, dict]_ - The raw request body (only plain text is supported for "http" mode) +- `query` _Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]]_ - The query string data in any data format. +- `headers` _Optional[Dict[str, Union[str, Sequence[str]]]]_ - The request headers. +- `context` _Optional[Dict[str, Any]]_ - The context in this request. +- `mode` _str_ - The mode used for this request. (either "http" or "socket_mode") + +#### to\_copyable + +```python +def to_copyable() -> BoltRequest +``` diff --git a/docs/english/reference/response/index.md b/docs/english/reference/response/index.md new file mode 100644 index 000000000..1e867986a --- /dev/null +++ b/docs/english/reference/response/index.md @@ -0,0 +1,63 @@ +--- +sidebar_label: response +title: slack_bolt.response +--- + +This interface represents Bolt's synchronous response to Slack. + +In Socket Mode, the response data can be transformed to a WebSocket message. In the HTTP endpoint mode, +the response data becomes an HTTP response data. + +Refer to https://docs.slack.dev/apis/events-api/ for the two types of connections. + +## Submodules + +- [slack_bolt.response.response](/tools/bolt-python/reference/response/response) + +## BoltResponse Objects + +```python +class BoltResponse() +``` + +#### status: `int` + +#### body: `str` + +#### headers: `Dict[str, Sequence[str]]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + status: int, + body: Union[str, dict] = '', + headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None) +``` + +The response from a Bolt app. + +**Arguments**: + +- `status` _int_ - HTTP status code +- `body` _Union[str, dict]_ - The response body (dict and str are supported) +- `headers` _Optional[Dict[str, Union[str, Sequence[str]]]]_ - The response headers. + +#### first\_headers + +```python +def first_headers() -> Dict[str, str] +``` + +#### first\_headers\_without\_set\_cookie + +```python +def first_headers_without_set_cookie() -> Dict[str, str] +``` + +#### cookies + +```python +def cookies() -> Sequence[SimpleCookie] +``` diff --git a/docs/english/reference/response/response.md b/docs/english/reference/response/response.md new file mode 100644 index 000000000..260e4dbc0 --- /dev/null +++ b/docs/english/reference/response/response.md @@ -0,0 +1,53 @@ +--- +sidebar_label: response +title: slack_bolt.response.response +slug: response +--- + +## BoltResponse Objects + +```python +class BoltResponse() +``` + +#### status: `int` + +#### body: `str` + +#### headers: `Dict[str, Sequence[str]]` + +#### \_\_init\_\_ + +```python +def __init__( + *, + status: int, + body: Union[str, dict] = '', + headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None) +``` + +The response from a Bolt app. + +**Arguments**: + +- `status` _int_ - HTTP status code +- `body` _Union[str, dict]_ - The response body (dict and str are supported) +- `headers` _Optional[Dict[str, Union[str, Sequence[str]]]]_ - The response headers. + +#### first\_headers + +```python +def first_headers() -> Dict[str, str] +``` + +#### first\_headers\_without\_set\_cookie + +```python +def first_headers_without_set_cookie() -> Dict[str, str] +``` + +#### cookies + +```python +def cookies() -> Sequence[SimpleCookie] +``` diff --git a/docs/english/reference/sidebar.json b/docs/english/reference/sidebar.json new file mode 100644 index 000000000..4debceb41 --- /dev/null +++ b/docs/english/reference/sidebar.json @@ -0,0 +1,769 @@ +{ + "type": "category", + "label": "Reference", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/index" + }, + "items": [ + { + "type": "category", + "label": "adapter", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/index" + }, + "items": [ + { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/aiohttp/index", + "label": "aiohttp" + }, + { + "type": "category", + "label": "asgi", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/asgi/index" + }, + "items": [ + { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/asgi/aiohttp/index", + "label": "aiohttp" + }, + { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/asgi/builtin/index", + "label": "builtin" + }, + "tools/bolt-python/reference/adapter/asgi/async_handler", + "tools/bolt-python/reference/adapter/asgi/base_handler", + "tools/bolt-python/reference/adapter/asgi/http_request", + "tools/bolt-python/reference/adapter/asgi/http_response", + "tools/bolt-python/reference/adapter/asgi/utils" + ] + }, + { + "type": "category", + "label": "aws_lambda", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/aws_lambda/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/aws_lambda/chalice_handler", + "tools/bolt-python/reference/adapter/aws_lambda/chalice_lazy_listener_runner", + "tools/bolt-python/reference/adapter/aws_lambda/handler", + "tools/bolt-python/reference/adapter/aws_lambda/internals", + "tools/bolt-python/reference/adapter/aws_lambda/lambda_s3_oauth_flow", + "tools/bolt-python/reference/adapter/aws_lambda/lazy_listener_runner", + "tools/bolt-python/reference/adapter/aws_lambda/local_lambda_client" + ] + }, + { + "type": "category", + "label": "bottle", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/bottle/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/bottle/handler" + ] + }, + { + "type": "category", + "label": "cherrypy", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/cherrypy/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/cherrypy/handler" + ] + }, + { + "type": "category", + "label": "django", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/django/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/django/handler" + ] + }, + { + "type": "category", + "label": "falcon", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/falcon/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/falcon/async_resource", + "tools/bolt-python/reference/adapter/falcon/resource" + ] + }, + { + "type": "category", + "label": "fastapi", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/fastapi/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/fastapi/async_handler" + ] + }, + { + "type": "category", + "label": "flask", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/flask/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/flask/handler" + ] + }, + { + "type": "category", + "label": "google_cloud_functions", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/google_cloud_functions/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/google_cloud_functions/handler" + ] + }, + { + "type": "category", + "label": "pyramid", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/pyramid/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/pyramid/handler" + ] + }, + { + "type": "category", + "label": "sanic", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/sanic/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/sanic/async_handler" + ] + }, + { + "type": "category", + "label": "socket_mode", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/socket_mode/index" + }, + "items": [ + { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/socket_mode/aiohttp/index", + "label": "aiohttp" + }, + { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/socket_mode/builtin/index", + "label": "builtin" + }, + { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/socket_mode/websocket_client/index", + "label": "websocket_client" + }, + { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/socket_mode/websockets/index", + "label": "websockets" + }, + "tools/bolt-python/reference/adapter/socket_mode/async_base_handler", + "tools/bolt-python/reference/adapter/socket_mode/async_handler", + "tools/bolt-python/reference/adapter/socket_mode/async_internals", + "tools/bolt-python/reference/adapter/socket_mode/base_handler", + "tools/bolt-python/reference/adapter/socket_mode/internals" + ] + }, + { + "type": "category", + "label": "starlette", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/starlette/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/starlette/async_handler", + "tools/bolt-python/reference/adapter/starlette/handler" + ] + }, + { + "type": "category", + "label": "tornado", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/tornado/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/tornado/async_handler", + "tools/bolt-python/reference/adapter/tornado/handler" + ] + }, + { + "type": "category", + "label": "wsgi", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/adapter/wsgi/index" + }, + "items": [ + "tools/bolt-python/reference/adapter/wsgi/handler", + "tools/bolt-python/reference/adapter/wsgi/http_request", + "tools/bolt-python/reference/adapter/wsgi/http_response", + "tools/bolt-python/reference/adapter/wsgi/internals" + ] + } + ] + }, + { + "type": "category", + "label": "app", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/app/index" + }, + "items": [ + "tools/bolt-python/reference/app/app", + "tools/bolt-python/reference/app/async_app", + "tools/bolt-python/reference/app/async_server" + ] + }, + { + "type": "category", + "label": "authorization", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/authorization/index" + }, + "items": [ + "tools/bolt-python/reference/authorization/async_authorize", + "tools/bolt-python/reference/authorization/async_authorize_args", + "tools/bolt-python/reference/authorization/authorize", + "tools/bolt-python/reference/authorization/authorize_args", + "tools/bolt-python/reference/authorization/authorize_result" + ] + }, + { + "type": "category", + "label": "context", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/index" + }, + "items": [ + { + "type": "category", + "label": "ack", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/ack/index" + }, + "items": [ + "tools/bolt-python/reference/context/ack/ack", + "tools/bolt-python/reference/context/ack/async_ack", + "tools/bolt-python/reference/context/ack/internals" + ] + }, + { + "type": "category", + "label": "assistant", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/assistant/index" + }, + "items": [ + { + "type": "doc", + "id": "tools/bolt-python/reference/context/assistant/thread_context/index", + "label": "thread_context" + }, + { + "type": "category", + "label": "thread_context_store", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/assistant/thread_context_store/index" + }, + "items": [ + { + "type": "doc", + "id": "tools/bolt-python/reference/context/assistant/thread_context_store/file/index", + "label": "file" + }, + "tools/bolt-python/reference/context/assistant/thread_context_store/async_store", + "tools/bolt-python/reference/context/assistant/thread_context_store/default_async_store", + "tools/bolt-python/reference/context/assistant/thread_context_store/default_store", + "tools/bolt-python/reference/context/assistant/thread_context_store/store" + ] + }, + "tools/bolt-python/reference/context/assistant/assistant_utilities", + "tools/bolt-python/reference/context/assistant/async_assistant_utilities", + "tools/bolt-python/reference/context/assistant/internals" + ] + }, + { + "type": "category", + "label": "complete", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/complete/index" + }, + "items": [ + "tools/bolt-python/reference/context/complete/async_complete", + "tools/bolt-python/reference/context/complete/complete" + ] + }, + { + "type": "category", + "label": "fail", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/fail/index" + }, + "items": [ + "tools/bolt-python/reference/context/fail/async_fail", + "tools/bolt-python/reference/context/fail/fail" + ] + }, + { + "type": "category", + "label": "get_thread_context", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/get_thread_context/index" + }, + "items": [ + "tools/bolt-python/reference/context/get_thread_context/async_get_thread_context", + "tools/bolt-python/reference/context/get_thread_context/get_thread_context" + ] + }, + { + "type": "category", + "label": "respond", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/respond/index" + }, + "items": [ + "tools/bolt-python/reference/context/respond/async_respond", + "tools/bolt-python/reference/context/respond/internals", + "tools/bolt-python/reference/context/respond/respond" + ] + }, + { + "type": "category", + "label": "save_thread_context", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/save_thread_context/index" + }, + "items": [ + "tools/bolt-python/reference/context/save_thread_context/async_save_thread_context", + "tools/bolt-python/reference/context/save_thread_context/save_thread_context" + ] + }, + { + "type": "category", + "label": "say", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/say/index" + }, + "items": [ + "tools/bolt-python/reference/context/say/async_say", + "tools/bolt-python/reference/context/say/internals", + "tools/bolt-python/reference/context/say/say" + ] + }, + { + "type": "category", + "label": "say_stream", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/say_stream/index" + }, + "items": [ + "tools/bolt-python/reference/context/say_stream/async_say_stream", + "tools/bolt-python/reference/context/say_stream/say_stream" + ] + }, + { + "type": "category", + "label": "set_status", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/set_status/index" + }, + "items": [ + "tools/bolt-python/reference/context/set_status/async_set_status", + "tools/bolt-python/reference/context/set_status/set_status" + ] + }, + { + "type": "category", + "label": "set_suggested_prompts", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/set_suggested_prompts/index" + }, + "items": [ + "tools/bolt-python/reference/context/set_suggested_prompts/async_set_suggested_prompts", + "tools/bolt-python/reference/context/set_suggested_prompts/set_suggested_prompts" + ] + }, + { + "type": "category", + "label": "set_title", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/context/set_title/index" + }, + "items": [ + "tools/bolt-python/reference/context/set_title/async_set_title", + "tools/bolt-python/reference/context/set_title/set_title" + ] + }, + "tools/bolt-python/reference/context/async_context", + "tools/bolt-python/reference/context/base_context", + "tools/bolt-python/reference/context/context" + ] + }, + { + "type": "doc", + "id": "tools/bolt-python/reference/error/index", + "label": "error" + }, + { + "type": "category", + "label": "kwargs_injection", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/kwargs_injection/index" + }, + "items": [ + "tools/bolt-python/reference/kwargs_injection/args", + "tools/bolt-python/reference/kwargs_injection/async_args", + "tools/bolt-python/reference/kwargs_injection/async_utils", + "tools/bolt-python/reference/kwargs_injection/utils" + ] + }, + { + "type": "category", + "label": "lazy_listener", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/lazy_listener/index" + }, + "items": [ + "tools/bolt-python/reference/lazy_listener/async_internals", + "tools/bolt-python/reference/lazy_listener/async_runner", + "tools/bolt-python/reference/lazy_listener/asyncio_runner", + "tools/bolt-python/reference/lazy_listener/internals", + "tools/bolt-python/reference/lazy_listener/runner", + "tools/bolt-python/reference/lazy_listener/thread_runner" + ] + }, + { + "type": "category", + "label": "listener", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/listener/index" + }, + "items": [ + "tools/bolt-python/reference/listener/async_builtins", + "tools/bolt-python/reference/listener/async_listener", + "tools/bolt-python/reference/listener/async_listener_completion_handler", + "tools/bolt-python/reference/listener/async_listener_error_handler", + "tools/bolt-python/reference/listener/async_listener_start_handler", + "tools/bolt-python/reference/listener/asyncio_runner", + "tools/bolt-python/reference/listener/builtins", + "tools/bolt-python/reference/listener/custom_listener", + "tools/bolt-python/reference/listener/listener", + "tools/bolt-python/reference/listener/listener_completion_handler", + "tools/bolt-python/reference/listener/listener_error_handler", + "tools/bolt-python/reference/listener/listener_start_handler", + "tools/bolt-python/reference/listener/thread_runner" + ] + }, + { + "type": "category", + "label": "listener_matcher", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/listener_matcher/index" + }, + "items": [ + "tools/bolt-python/reference/listener_matcher/async_builtins", + "tools/bolt-python/reference/listener_matcher/async_listener_matcher", + "tools/bolt-python/reference/listener_matcher/builtins", + "tools/bolt-python/reference/listener_matcher/custom_listener_matcher", + "tools/bolt-python/reference/listener_matcher/listener_matcher" + ] + }, + { + "type": "category", + "label": "logger", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/logger/index" + }, + "items": [ + "tools/bolt-python/reference/logger/messages" + ] + }, + { + "type": "category", + "label": "middleware", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/middleware/index" + }, + "items": [ + { + "type": "category", + "label": "assistant", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/middleware/assistant/index" + }, + "items": [ + "tools/bolt-python/reference/middleware/assistant/assistant", + "tools/bolt-python/reference/middleware/assistant/async_assistant" + ] + }, + { + "type": "category", + "label": "attaching_conversation_kwargs", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/middleware/attaching_conversation_kwargs/index" + }, + "items": [ + "tools/bolt-python/reference/middleware/attaching_conversation_kwargs/async_attaching_conversation_kwargs", + "tools/bolt-python/reference/middleware/attaching_conversation_kwargs/attaching_conversation_kwargs" + ] + }, + { + "type": "category", + "label": "attaching_function_token", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/middleware/attaching_function_token/index" + }, + "items": [ + "tools/bolt-python/reference/middleware/attaching_function_token/async_attaching_function_token", + "tools/bolt-python/reference/middleware/attaching_function_token/attaching_function_token" + ] + }, + { + "type": "category", + "label": "authorization", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/middleware/authorization/index" + }, + "items": [ + "tools/bolt-python/reference/middleware/authorization/async_authorization", + "tools/bolt-python/reference/middleware/authorization/async_internals", + "tools/bolt-python/reference/middleware/authorization/async_multi_teams_authorization", + "tools/bolt-python/reference/middleware/authorization/async_single_team_authorization", + "tools/bolt-python/reference/middleware/authorization/authorization", + "tools/bolt-python/reference/middleware/authorization/internals", + "tools/bolt-python/reference/middleware/authorization/multi_teams_authorization", + "tools/bolt-python/reference/middleware/authorization/single_team_authorization" + ] + }, + { + "type": "category", + "label": "ignoring_self_events", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/middleware/ignoring_self_events/index" + }, + "items": [ + "tools/bolt-python/reference/middleware/ignoring_self_events/async_ignoring_self_events", + "tools/bolt-python/reference/middleware/ignoring_self_events/ignoring_self_events" + ] + }, + { + "type": "category", + "label": "message_listener_matches", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/middleware/message_listener_matches/index" + }, + "items": [ + "tools/bolt-python/reference/middleware/message_listener_matches/async_message_listener_matches", + "tools/bolt-python/reference/middleware/message_listener_matches/message_listener_matches" + ] + }, + { + "type": "category", + "label": "request_verification", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/middleware/request_verification/index" + }, + "items": [ + "tools/bolt-python/reference/middleware/request_verification/async_request_verification", + "tools/bolt-python/reference/middleware/request_verification/request_verification" + ] + }, + { + "type": "category", + "label": "ssl_check", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/middleware/ssl_check/index" + }, + "items": [ + "tools/bolt-python/reference/middleware/ssl_check/async_ssl_check", + "tools/bolt-python/reference/middleware/ssl_check/ssl_check" + ] + }, + { + "type": "category", + "label": "url_verification", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/middleware/url_verification/index" + }, + "items": [ + "tools/bolt-python/reference/middleware/url_verification/async_url_verification", + "tools/bolt-python/reference/middleware/url_verification/url_verification" + ] + }, + "tools/bolt-python/reference/middleware/async_builtins", + "tools/bolt-python/reference/middleware/async_custom_middleware", + "tools/bolt-python/reference/middleware/async_middleware", + "tools/bolt-python/reference/middleware/async_middleware_error_handler", + "tools/bolt-python/reference/middleware/custom_middleware", + "tools/bolt-python/reference/middleware/middleware", + "tools/bolt-python/reference/middleware/middleware_error_handler" + ] + }, + { + "type": "category", + "label": "oauth", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/oauth/index" + }, + "items": [ + "tools/bolt-python/reference/oauth/async_callback_options", + "tools/bolt-python/reference/oauth/async_internals", + "tools/bolt-python/reference/oauth/async_oauth_flow", + "tools/bolt-python/reference/oauth/async_oauth_settings", + "tools/bolt-python/reference/oauth/callback_options", + "tools/bolt-python/reference/oauth/internals", + "tools/bolt-python/reference/oauth/oauth_flow", + "tools/bolt-python/reference/oauth/oauth_settings" + ] + }, + { + "type": "category", + "label": "request", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/request/index" + }, + "items": [ + "tools/bolt-python/reference/request/async_internals", + "tools/bolt-python/reference/request/async_request", + "tools/bolt-python/reference/request/internals", + "tools/bolt-python/reference/request/payload_utils", + "tools/bolt-python/reference/request/request" + ] + }, + { + "type": "category", + "label": "response", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/response/index" + }, + "items": [ + "tools/bolt-python/reference/response/response" + ] + }, + { + "type": "category", + "label": "util", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/util/index" + }, + "items": [ + "tools/bolt-python/reference/util/async_utils", + "tools/bolt-python/reference/util/utils" + ] + }, + { + "type": "category", + "label": "workflows", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/workflows/index" + }, + "items": [ + { + "type": "category", + "label": "step", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/workflows/step/index" + }, + "items": [ + { + "type": "category", + "label": "utilities", + "link": { + "type": "doc", + "id": "tools/bolt-python/reference/workflows/step/utilities/index" + }, + "items": [ + "tools/bolt-python/reference/workflows/step/utilities/async_complete", + "tools/bolt-python/reference/workflows/step/utilities/async_configure", + "tools/bolt-python/reference/workflows/step/utilities/async_fail", + "tools/bolt-python/reference/workflows/step/utilities/async_update", + "tools/bolt-python/reference/workflows/step/utilities/complete", + "tools/bolt-python/reference/workflows/step/utilities/configure", + "tools/bolt-python/reference/workflows/step/utilities/fail", + "tools/bolt-python/reference/workflows/step/utilities/update" + ] + }, + "tools/bolt-python/reference/workflows/step/async_step", + "tools/bolt-python/reference/workflows/step/async_step_middleware", + "tools/bolt-python/reference/workflows/step/internals", + "tools/bolt-python/reference/workflows/step/step", + "tools/bolt-python/reference/workflows/step/step_middleware" + ] + } + ] + }, + "tools/bolt-python/reference/async_app", + "tools/bolt-python/reference/version" + ] +} diff --git a/docs/english/reference/util/async_utils.md b/docs/english/reference/util/async_utils.md new file mode 100644 index 000000000..9c2f7ffb7 --- /dev/null +++ b/docs/english/reference/util/async_utils.md @@ -0,0 +1,12 @@ +--- +sidebar_label: async_utils +title: slack_bolt.util.async_utils +--- + +#### create\_async\_web\_client + +```python +def create_async_web_client( + token: Optional[str] = None, + logger: Optional[Logger] = None) -> AsyncWebClient +``` diff --git a/docs/english/reference/util/index.md b/docs/english/reference/util/index.md new file mode 100644 index 000000000..8ddfc4828 --- /dev/null +++ b/docs/english/reference/util/index.md @@ -0,0 +1,11 @@ +--- +sidebar_label: util +title: slack_bolt.util +--- + +Internal utilities for the Bolt framework. + +## Submodules + +- [slack_bolt.util.async_utils](/tools/bolt-python/reference/util/async_utils) +- [slack_bolt.util.utils](/tools/bolt-python/reference/util/utils) diff --git a/docs/english/reference/util/utils.md b/docs/english/reference/util/utils.md new file mode 100644 index 000000000..58b64ad08 --- /dev/null +++ b/docs/english/reference/util/utils.md @@ -0,0 +1,80 @@ +--- +sidebar_label: utils +title: slack_bolt.util.utils +--- + +#### create\_web\_client + +```python +def create_web_client( + token: Optional[str] = None, + logger: Optional[Logger] = None) -> WebClient +``` + +#### convert\_to\_dict\_list + +```python +def convert_to_dict_list(objects: Sequence[Union[Dict, JsonObject]]) -> Sequence[Dict] +``` + +#### convert\_to\_dict + +```python +def convert_to_dict(obj: Union[Dict, JsonObject]) -> Dict +``` + +#### create\_copy + +```python +def create_copy(original: Any) -> Any +``` + +#### get\_boot\_message + +```python +def get_boot_message(development_server: bool = False) -> str +``` + +#### get\_name\_for\_callable + +```python +def get_name_for_callable(func: Callable) -> str +``` + +Returns the name for the given Callable function object. + +**Arguments**: + +- `func` _Callable_ - Either a `Callable` instance or a function, which as `__name__` + +**Returns**: + +- `str` - The name of the given Callable object + +#### get\_arg\_names\_of\_callable + +```python +def get_arg_names_of_callable(func: Callable) -> List[str] +``` + +#### is\_callable\_coroutine + +```python +def is_callable_coroutine(func: Optional[Any]) -> bool +``` + +#### is\_used\_without\_argument + +```python +def is_used_without_argument(args) -> bool +``` + +Tests if a decorator invocation is without () or (args). + +**Arguments**: + +- `args` - arguments + +**Returns**: + +- `bool` - True if it's an invocation without args diff --git a/docs/english/reference/version.md b/docs/english/reference/version.md new file mode 100644 index 000000000..8d3dce3f9 --- /dev/null +++ b/docs/english/reference/version.md @@ -0,0 +1,6 @@ +--- +sidebar_label: version +title: slack_bolt.version +--- + +Check the latest version at https://pypi.org/project/slack-bolt/ diff --git a/docs/english/reference/workflows/index.md b/docs/english/reference/workflows/index.md new file mode 100644 index 000000000..9fc44f347 --- /dev/null +++ b/docs/english/reference/workflows/index.md @@ -0,0 +1,18 @@ +--- +sidebar_label: workflows +title: slack_bolt.workflows +--- + +Steps from apps enables developers to build their own steps. + +Check the following API documents first: + +* `slack_bolt.workflows.step.step` +* `slack_bolt.workflows.step.utilities` +* `slack_bolt.workflows.step.async_step` (if you use asyncio-based `AsyncApp`) + +Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details. + +## Submodules + +- [slack_bolt.workflows.step](/tools/bolt-python/reference/workflows/step) diff --git a/docs/english/reference/workflows/step/async_step.md b/docs/english/reference/workflows/step/async_step.md new file mode 100644 index 000000000..b8eb7edf5 --- /dev/null +++ b/docs/english/reference/workflows/step/async_step.md @@ -0,0 +1,299 @@ +--- +sidebar_label: async_step +title: slack_bolt.workflows.step.async_step +--- + +## AsyncWorkflowStepBuilder Objects + +```python +class AsyncWorkflowStepBuilder() +``` + +Steps from apps +Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details. + +#### callback\_id: `Union[str, Pattern]` + +#### \_\_init\_\_ + +```python +def __init__( + callback_id: Union[str, Pattern], + app_name: Optional[str] = None, + base_logger: Optional[Logger] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +This builder is supposed to be used as decorator. + +```python +my_step = AsyncWorkflowStep.builder("my_step") +@my_step.edit +async def edit_my_step(ack, configure): + pass +@my_step.save +async def save_my_step(ack, step, update): + pass +@my_step.execute +async def execute_my_step(step, complete, fail): + pass +app.step(my_step) +``` + +For further information about AsyncWorkflowStep specific function arguments +such as `configure`, `update`, `complete`, and `fail`, +refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents. + +**Arguments**: + +- `callback_id` _Union[str, Pattern]_ - The callback_id for the workflow +- `app_name` _Optional[str]_ - The application name mainly for logging +- `base_logger` _Optional[Logger]_ - The base logger + +#### edit + +```python +def edit( + *args, + matchers: Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]] = None, + middleware: Optional[Union[Callable, AsyncMiddleware]] = None, + lazy: Optional[List[Callable[..., Awaitable[None]]]] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +Registers a new edit listener with details. + +You can use this method as decorator as well. + +```python +@my_step.edit +def edit_my_step(ack, configure): + pass +``` + +It's also possible to add additional listener matchers and/or middleware + +```python +@my_step.edit(matchers=[is_valid], middleware=[update_context]) +def edit_my_step(ack, configure): + pass +``` + +For further information about AsyncWorkflowStep specific function arguments +such as `configure`, `update`, `complete`, and `fail`, +refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents. + +**Arguments**: + +- `*args` - This method can behave as either decorator or a method +- `matchers` _Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]]_ - Listener matchers +- `middleware` _Optional[Union[Callable, AsyncMiddleware]]_ - Listener middleware +- `lazy` _Optional[List[Callable[..., Awaitable[None]]]]_ - Lazy listeners + +#### save + +```python +def save( + *args, + matchers: Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]] = None, + middleware: Optional[Union[Callable, AsyncMiddleware]] = None, + lazy: Optional[List[Callable[..., Awaitable[None]]]] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +Registers a new save listener with details. + +You can use this method as decorator as well. + +```python +@my_step.save +def save_my_step(ack, step, update): + pass +``` + +It's also possible to add additional listener matchers and/or middleware + +```python +@my_step.save(matchers=[is_valid], middleware=[update_context]) +def save_my_step(ack, step, update): + pass +``` + +For further information about AsyncWorkflowStep specific function arguments +such as `configure`, `update`, `complete`, and `fail`, +refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents. + +**Arguments**: + +- `*args` - This method can behave as either decorator or a method +- `matchers` _Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]]_ - Listener matchers +- `middleware` _Optional[Union[Callable, AsyncMiddleware]]_ - Listener middleware +- `lazy` _Optional[List[Callable[..., Awaitable[None]]]]_ - Lazy listeners + +#### execute + +```python +def execute( + *args, + matchers: Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]] = None, + middleware: Optional[Union[Callable, AsyncMiddleware]] = None, + lazy: Optional[List[Callable[..., Awaitable[None]]]] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +Registers a new execute listener with details. + +You can use this method as decorator as well. + +```python +@my_step.execute +def execute_my_step(step, complete, fail): + pass +``` + +It's also possible to add additional listener matchers and/or middleware + +```python +@my_step.save(matchers=[is_valid], middleware=[update_context]) +def execute_my_step(step, complete, fail): + pass +``` + +For further information about AsyncWorkflowStep specific function arguments +such as `configure`, `update`, `complete`, and `fail`, +refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents. + +**Arguments**: + +- `*args` - This method can behave as either decorator or a method +- `matchers` _Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]]_ - Listener matchers +- `middleware` _Optional[Union[Callable, AsyncMiddleware]]_ - Listener middleware +- `lazy` _Optional[List[Callable[..., Awaitable[None]]]]_ - Lazy listeners + +#### build + +```python +def build(base_logger: Optional[Logger] = None) -> AsyncWorkflowStep +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +Constructs a WorkflowStep object. This method may raise an exception +if the builder doesn't have enough configurations to build the object. + +**Returns**: + +- `AsyncWorkflowStep` - An `AsyncWorkflowStep` object + +#### to\_listener\_matchers + +```python +def to_listener_matchers( + app_name: str, + matchers: Optional[List[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]]]) -> List[AsyncListenerMatcher] +``` + +#### to\_listener\_middleware + +```python +def to_listener_middleware( + app_name: str, + middleware: Optional[List[Union[Callable, AsyncMiddleware]]]) -> List[AsyncMiddleware] +``` + +## AsyncWorkflowStep Objects + +```python +class AsyncWorkflowStep() +``` + +#### callback\_id: `Union[str, Pattern]` + +The Callback ID of the step from app + +#### edit: `AsyncListener` + +`edit` listener, which displays a modal in Workflow Builder + +#### save: `AsyncListener` + +`save` listener, which accepts workflow creator's data submission in Workflow Builder + +#### execute: `AsyncListener` + +`execute` listener, which processes the step from app execution + +#### \_\_init\_\_ + +```python +def __init__( + *, + callback_id: Union[str, Pattern], + edit: Union[Callable[..., Awaitable[BoltResponse]], AsyncListener, Sequence[Callable]], + save: Union[Callable[..., Awaitable[BoltResponse]], AsyncListener, Sequence[Callable]], + execute: Union[Callable[..., Awaitable[BoltResponse]], AsyncListener, Sequence[Callable]], + app_name: Optional[str] = None, + base_logger: Optional[Logger] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +**Arguments**: + +- `callback_id` _Union[str, Pattern]_ - The callback_id for this step from app +- `edit` _Union[Callable[..., Awaitable[BoltResponse]], AsyncListener, Sequence[Callable]]_ - Either a single function or a list of functions for opening a modal in the builder UI + When it's a list, the first one is responsible for ack() while the rest are lazy listeners. +- `save` _Union[Callable[..., Awaitable[BoltResponse]], AsyncListener, Sequence[Callable]]_ - Either a single function or a list of functions for handling modal interactions in the builder UI + When it's a list, the first one is responsible for ack() while the rest are lazy listeners. +- `execute` _Union[Callable[..., Awaitable[BoltResponse]], AsyncListener, Sequence[Callable]]_ - Either a single function or a list of functions for handling steps from apps executions + When it's a list, the first one is responsible for ack() while the rest are lazy listeners. +- `app_name` _Optional[str]_ - The app name that can be mainly used for logging +- `base_logger` _Optional[Logger]_ - The logger instance that can be used as a template when creating this step's logger + +#### builder + +```python +def builder( + callback_id: Union[str, Pattern], + base_logger: Optional[Logger] = None) -> AsyncWorkflowStepBuilder +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +#### build\_listener + +```python +def build_listener( + callback_id: Union[str, Pattern], + app_name: str, + listener_or_functions: Union[AsyncListener, Callable, List[Callable]], + name: str, + matchers: Optional[List[AsyncListenerMatcher]] = None, + middleware: Optional[List[AsyncMiddleware]] = None, + base_logger: Optional[Logger] = None) +``` diff --git a/docs/english/reference/workflows/step/async_step_middleware.md b/docs/english/reference/workflows/step/async_step_middleware.md new file mode 100644 index 000000000..a1b5583f6 --- /dev/null +++ b/docs/english/reference/workflows/step/async_step_middleware.md @@ -0,0 +1,28 @@ +--- +sidebar_label: async_step_middleware +title: slack_bolt.workflows.step.async_step_middleware +--- + +## AsyncWorkflowStepMiddleware Objects + +```python +class AsyncWorkflowStepMiddleware(AsyncMiddleware) +``` + +Base middleware for step from app specific ones + +#### \_\_init\_\_ + +```python +def __init__(step: AsyncWorkflowStep) +``` + +#### async\_process + +```python +async def async_process( + *, + req: AsyncBoltRequest, + resp: BoltResponse, + next: Callable[[], Awaitable[BoltResponse]]) -> BoltResponse +``` diff --git a/docs/english/reference/workflows/step/index.md b/docs/english/reference/workflows/step/index.md new file mode 100644 index 000000000..8b32aa68a --- /dev/null +++ b/docs/english/reference/workflows/step/index.md @@ -0,0 +1,279 @@ +--- +sidebar_label: step +title: slack_bolt.workflows.step +--- + +## Submodules + +- [slack_bolt.workflows.step.async_step](/tools/bolt-python/reference/workflows/step/async_step) +- [slack_bolt.workflows.step.async_step_middleware](/tools/bolt-python/reference/workflows/step/async_step_middleware) +- [slack_bolt.workflows.step.internals](/tools/bolt-python/reference/workflows/step/internals) +- [slack_bolt.workflows.step.step](/tools/bolt-python/reference/workflows/step/step) +- [slack_bolt.workflows.step.step_middleware](/tools/bolt-python/reference/workflows/step/step_middleware) +- [slack_bolt.workflows.step.utilities](/tools/bolt-python/reference/workflows/step/utilities) + +## WorkflowStep Objects + +```python +class WorkflowStep() +``` + +#### callback\_id: `Union[str, Pattern]` + +The Callback ID of the step from app + +#### edit: `Listener` + +`edit` listener, which displays a modal in Workflow Builder + +#### save: `Listener` + +`save` listener, which accepts workflow creator's data submission in Workflow Builder + +#### execute: `Listener` + +`execute` listener, which processes step from app execution + +#### \_\_init\_\_ + +```python +def __init__( + *, + callback_id: Union[str, Pattern], + edit: Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]], + save: Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]], + execute: Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]], + app_name: Optional[str] = None, + base_logger: Optional[Logger] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +**Arguments**: + +- `callback_id` _Union[str, Pattern]_ - The callback_id for this step from app +- `edit` _Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]_ - Either a single function or a list of functions for opening a modal in the builder UI + When it's a list, the first one is responsible for ack() while the rest are lazy listeners. +- `save` _Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]_ - Either a single function or a list of functions for handling modal interactions in the builder UI + When it's a list, the first one is responsible for ack() while the rest are lazy listeners. +- `execute` _Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]_ - Either a single function or a list of functions for handling step from app executions + When it's a list, the first one is responsible for ack() while the rest are lazy listeners. +- `app_name` _Optional[str]_ - The app name that can be mainly used for logging +- `base_logger` _Optional[Logger]_ - The logger instance that can be used as a template when creating this step's logger + +#### builder + +```python +def builder( + callback_id: Union[str, Pattern], + base_logger: Optional[Logger] = None) -> WorkflowStepBuilder +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +#### build\_listener + +```python +def build_listener( + callback_id: Union[str, Pattern], + app_name: str, + listener_or_functions: Union[Listener, Callable, List[Callable]], + name: str, + matchers: Optional[List[ListenerMatcher]] = None, + middleware: Optional[List[Middleware]] = None, + base_logger: Optional[Logger] = None) -> Listener +``` + +## WorkflowStepMiddleware Objects + +```python +class WorkflowStepMiddleware(Middleware) +``` + +Base middleware for step from app specific ones + +#### \_\_init\_\_ + +```python +def __init__(step: WorkflowStep) +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> Optional[BoltResponse] +``` + +## Complete Objects + +```python +class Complete() +``` + +`complete()` utility to tell Slack the completion of a step from app execution. + +```python +def execute(step, complete, fail): + inputs = step["inputs"] + # if everything was successful + outputs = { + "task_name": inputs["task_name"]["value"], + "task_description": inputs["task_description"]["value"], + } + complete(outputs=outputs) + +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +This utility is a thin wrapper of workflows.stepCompleted API method. +Refer to https://api.slack.com/methods/workflows.stepCompleted for details. + +#### \_\_init\_\_ + +```python +def __init__(*, client: WebClient, body: dict) +``` + +## Configure Objects + +```python +class Configure() +``` + +`configure()` utility to send the modal view in Workflow Builder. + +```python +def edit(ack, step, configure): + ack() + + blocks = [ + { + "type": "input", + "block_id": "task_name_input", + "element": { + "type": "plain_text_input", + "action_id": "name", + "placeholder": {"type": "plain_text", "text": "Add a task name"}, + }, + "label": {"type": "plain_text", "text": "Task name"}, + }, + ] + configure(blocks=blocks) + +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details. + +#### \_\_init\_\_ + +```python +def __init__(*, callback_id: str, client: WebClient, body: dict) +``` + +## Update Objects + +```python +class Update() +``` + +`update()` utility to tell Slack the processing results of a `save` listener. + +```python +def save(ack, view, update): + ack() + + values = view["state"]["values"] + task_name = values["task_name_input"]["name"] + task_description = values["task_description_input"]["description"] + + inputs = { + "task_name": {"value": task_name["value"]}, + "task_description": {"value": task_description["value"]} + } + outputs = [ + { + "type": "text", + "name": "task_name", + "label": "Task name", + }, + { + "type": "text", + "name": "task_description", + "label": "Task description", + } + ] + update(inputs=inputs, outputs=outputs) + +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +This utility is a thin wrapper of workflows.stepFailed API method. +Refer to https://api.slack.com/methods/workflows.updateStep for details. + +#### \_\_init\_\_ + +```python +def __init__(*, client: WebClient, body: dict) +``` + +## Fail Objects + +```python +class Fail() +``` + +`fail()` utility to tell Slack the execution failure of a step from app. + +```python +def execute(step, complete, fail): + inputs = step["inputs"] + # if something went wrong + error = {"message": "Just testing step failure!"} + fail(error=error) + +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +This utility is a thin wrapper of workflows.stepFailed API method. +Refer to https://api.slack.com/methods/workflows.stepFailed for details. + +#### \_\_init\_\_ + +```python +def __init__(*, client: WebClient, body: dict) +``` diff --git a/docs/english/reference/workflows/step/internals.md b/docs/english/reference/workflows/step/internals.md new file mode 100644 index 000000000..4ffaea65e --- /dev/null +++ b/docs/english/reference/workflows/step/internals.md @@ -0,0 +1,6 @@ +--- +sidebar_label: internals +title: slack_bolt.workflows.step.internals +--- + + diff --git a/docs/english/reference/workflows/step/step.md b/docs/english/reference/workflows/step/step.md new file mode 100644 index 000000000..6bdda856c --- /dev/null +++ b/docs/english/reference/workflows/step/step.md @@ -0,0 +1,302 @@ +--- +sidebar_label: step +title: slack_bolt.workflows.step.step +slug: step +--- + +## WorkflowStepBuilder Objects + +```python +class WorkflowStepBuilder() +``` + +Steps from apps +Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details. + +#### callback\_id: `Union[str, Pattern]` + +#### \_\_init\_\_ + +```python +def __init__( + callback_id: Union[str, Pattern], + app_name: Optional[str] = None, + base_logger: Optional[Logger] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +This builder is supposed to be used as decorator. + +```python +my_step = WorkflowStep.builder("my_step") +@my_step.edit +def edit_my_step(ack, configure): + pass +@my_step.save +def save_my_step(ack, step, update): + pass +@my_step.execute +def execute_my_step(step, complete, fail): + pass +app.step(my_step) +``` + +For further information about WorkflowStep specific function arguments +such as `configure`, `update`, `complete`, and `fail`, +refer to `slack_bolt.workflows.step.utilities` API documents. + +**Arguments**: + +- `callback_id` _Union[str, Pattern]_ - The callback_id for the workflow +- `app_name` _Optional[str]_ - The application name mainly for logging +- `base_logger` _Optional[Logger]_ - The base logger + +#### edit + +```python +def edit( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +Registers a new edit listener with details. + +You can use this method as decorator as well. + +```python +@my_step.edit +def edit_my_step(ack, configure): + pass +``` + +It's also possible to add additional listener matchers and/or middleware + +```python +@my_step.edit(matchers=[is_valid], middleware=[update_context]) +def edit_my_step(ack, configure): + pass +``` + +For further information about WorkflowStep specific function arguments +such as `configure`, `update`, `complete`, and `fail`, +refer to `slack_bolt.workflows.step.utilities` API documents. + +**Arguments**: + +- `*args` - This method can behave as either decorator or a method +- `matchers` _Optional[Union[Callable[..., bool], ListenerMatcher]]_ - Listener matchers +- `middleware` _Optional[Union[Callable, Middleware]]_ - Listener middleware +- `lazy` _Optional[List[Callable[..., None]]]_ - Lazy listeners + +#### save + +```python +def save( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +Registers a new save listener with details. + +You can use this method as decorator as well. + +```python +@my_step.save +def save_my_step(ack, step, update): + pass +``` + +It's also possible to add additional listener matchers and/or middleware + +```python +@my_step.save(matchers=[is_valid], middleware=[update_context]) +def save_my_step(ack, step, update): + pass +``` + +For further information about WorkflowStep specific function arguments +such as `configure`, `update`, `complete`, and `fail`, +refer to `slack_bolt.workflows.step.utilities` API documents. + +**Arguments**: + +- `*args` - This method can behave as either decorator or a method +- `matchers` _Optional[Union[Callable[..., bool], ListenerMatcher]]_ - Listener matchers +- `middleware` _Optional[Union[Callable, Middleware]]_ - Listener middleware +- `lazy` _Optional[List[Callable[..., None]]]_ - Lazy listeners + +#### execute + +```python +def execute( + *args, + matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None, + middleware: Optional[Union[Callable, Middleware]] = None, + lazy: Optional[List[Callable[..., None]]] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +Registers a new execute listener with details. + +You can use this method as decorator as well. + +```python +@my_step.execute +def execute_my_step(step, complete, fail): + pass +``` + +It's also possible to add additional listener matchers and/or middleware + +```python +@my_step.save(matchers=[is_valid], middleware=[update_context]) +def execute_my_step(step, complete, fail): + pass +``` + +For further information about WorkflowStep specific function arguments +such as `configure`, `update`, `complete`, and `fail`, +refer to `slack_bolt.workflows.step.utilities` API documents. + +**Arguments**: + +- `*args` - This method can behave as either decorator or a method +- `matchers` _Optional[Union[Callable[..., bool], ListenerMatcher]]_ - Listener matchers +- `middleware` _Optional[Union[Callable, Middleware]]_ - Listener middleware +- `lazy` _Optional[List[Callable[..., None]]]_ - Lazy listeners + +#### build + +```python +def build(base_logger: Optional[Logger] = None) -> WorkflowStep +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +Constructs a WorkflowStep object. This method may raise an exception +if the builder doesn't have enough configurations to build the object. + +**Returns**: + +- `WorkflowStep` - WorkflowStep object + +#### to\_listener\_matchers + +```python +def to_listener_matchers( + app_name: str, + matchers: Optional[List[Union[Callable[..., bool], ListenerMatcher]]], + base_logger: Optional[Logger] = None) -> List[ListenerMatcher] +``` + +#### to\_listener\_middleware + +```python +def to_listener_middleware( + app_name: str, + middleware: Optional[List[Union[Callable, Middleware]]], + base_logger: Optional[Logger] = None) -> List[Middleware] +``` + +## WorkflowStep Objects + +```python +class WorkflowStep() +``` + +#### callback\_id: `Union[str, Pattern]` + +The Callback ID of the step from app + +#### edit: `Listener` + +`edit` listener, which displays a modal in Workflow Builder + +#### save: `Listener` + +`save` listener, which accepts workflow creator's data submission in Workflow Builder + +#### execute: `Listener` + +`execute` listener, which processes step from app execution + +#### \_\_init\_\_ + +```python +def __init__( + *, + callback_id: Union[str, Pattern], + edit: Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]], + save: Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]], + execute: Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]], + app_name: Optional[str] = None, + base_logger: Optional[Logger] = None) +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +**Arguments**: + +- `callback_id` _Union[str, Pattern]_ - The callback_id for this step from app +- `edit` _Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]_ - Either a single function or a list of functions for opening a modal in the builder UI + When it's a list, the first one is responsible for ack() while the rest are lazy listeners. +- `save` _Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]_ - Either a single function or a list of functions for handling modal interactions in the builder UI + When it's a list, the first one is responsible for ack() while the rest are lazy listeners. +- `execute` _Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]_ - Either a single function or a list of functions for handling step from app executions + When it's a list, the first one is responsible for ack() while the rest are lazy listeners. +- `app_name` _Optional[str]_ - The app name that can be mainly used for logging +- `base_logger` _Optional[Logger]_ - The logger instance that can be used as a template when creating this step's logger + +#### builder + +```python +def builder( + callback_id: Union[str, Pattern], + base_logger: Optional[Logger] = None) -> WorkflowStepBuilder +``` + +**Deprecated**: + +Steps from apps for legacy workflows are now deprecated. +Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/ + +#### build\_listener + +```python +def build_listener( + callback_id: Union[str, Pattern], + app_name: str, + listener_or_functions: Union[Listener, Callable, List[Callable]], + name: str, + matchers: Optional[List[ListenerMatcher]] = None, + middleware: Optional[List[Middleware]] = None, + base_logger: Optional[Logger] = None) -> Listener +``` diff --git a/docs/english/reference/workflows/step/step_middleware.md b/docs/english/reference/workflows/step/step_middleware.md new file mode 100644 index 000000000..8895e872d --- /dev/null +++ b/docs/english/reference/workflows/step/step_middleware.md @@ -0,0 +1,28 @@ +--- +sidebar_label: step_middleware +title: slack_bolt.workflows.step.step_middleware +--- + +## WorkflowStepMiddleware Objects + +```python +class WorkflowStepMiddleware(Middleware) +``` + +Base middleware for step from app specific ones + +#### \_\_init\_\_ + +```python +def __init__(step: WorkflowStep) +``` + +#### process + +```python +def process( + *, + req: BoltRequest, + resp: BoltResponse, + next: Callable[[], BoltResponse]) -> Optional[BoltResponse] +``` diff --git a/docs/english/reference/workflows/step/utilities/async_complete.md b/docs/english/reference/workflows/step/utilities/async_complete.md new file mode 100644 index 000000000..ff80ef42e --- /dev/null +++ b/docs/english/reference/workflows/step/utilities/async_complete.md @@ -0,0 +1,40 @@ +--- +sidebar_label: async_complete +title: slack_bolt.workflows.step.utilities.async_complete +--- + +## AsyncComplete Objects + +```python +class AsyncComplete() +``` + +`complete()` utility to tell Slack the completion of a step from app execution. + +```python +async def execute(step, complete, fail): + inputs = step["inputs"] + # if everything was successful + outputs = { + "task_name": inputs["task_name"]["value"], + "task_description": inputs["task_description"]["value"], + } + await complete(outputs=outputs) + +ws = AsyncWorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +This utility is a thin wrapper of workflows.stepCompleted API method. +Refer to https://api.slack.com/methods/workflows.stepCompleted for details. + +#### \_\_init\_\_ + +```python +def __init__(*, client: AsyncWebClient, body: dict) +``` diff --git a/docs/english/reference/workflows/step/utilities/async_configure.md b/docs/english/reference/workflows/step/utilities/async_configure.md new file mode 100644 index 000000000..c9a17f0db --- /dev/null +++ b/docs/english/reference/workflows/step/utilities/async_configure.md @@ -0,0 +1,47 @@ +--- +sidebar_label: async_configure +title: slack_bolt.workflows.step.utilities.async_configure +--- + +## AsyncConfigure Objects + +```python +class AsyncConfigure() +``` + +`configure()` utility to send the modal view in Workflow Builder. + +```python +async def edit(ack, step, configure): + await ack() + + blocks = [ + { + "type": "input", + "block_id": "task_name_input", + "element": { + "type": "plain_text_input", + "action_id": "name", + "placeholder": {"type": "plain_text", "text": "Add a task name"}, + }, + "label": {"type": "plain_text", "text": "Task name"}, + }, + ] + await configure(blocks=blocks) + +ws = AsyncWorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details. + +#### \_\_init\_\_ + +```python +def __init__(*, callback_id: str, client: AsyncWebClient, body: dict) +``` diff --git a/docs/english/reference/workflows/step/utilities/async_fail.md b/docs/english/reference/workflows/step/utilities/async_fail.md new file mode 100644 index 000000000..cfadf7b0d --- /dev/null +++ b/docs/english/reference/workflows/step/utilities/async_fail.md @@ -0,0 +1,37 @@ +--- +sidebar_label: async_fail +title: slack_bolt.workflows.step.utilities.async_fail +--- + +## AsyncFail Objects + +```python +class AsyncFail() +``` + +`fail()` utility to tell Slack the execution failure of a step from app. + +```python +async def execute(step, complete, fail): + inputs = step["inputs"] + # if something went wrong + error = {"message": "Just testing step failure!"} + await fail(error=error) + +ws = AsyncWorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +This utility is a thin wrapper of workflows.stepFailed API method. +Refer to https://api.slack.com/methods/workflows.stepFailed for details. + +#### \_\_init\_\_ + +```python +def __init__(*, client: AsyncWebClient, body: dict) +``` diff --git a/docs/english/reference/workflows/step/utilities/async_update.md b/docs/english/reference/workflows/step/utilities/async_update.md new file mode 100644 index 000000000..7a761e4e9 --- /dev/null +++ b/docs/english/reference/workflows/step/utilities/async_update.md @@ -0,0 +1,56 @@ +--- +sidebar_label: async_update +title: slack_bolt.workflows.step.utilities.async_update +--- + +## AsyncUpdate Objects + +```python +class AsyncUpdate() +``` + +`update()` utility to tell Slack the processing results of a `save` listener. + +```python +async def save(ack, view, update): + await ack() + + values = view["state"]["values"] + task_name = values["task_name_input"]["name"] + task_description = values["task_description_input"]["description"] + + inputs = { + "task_name": {"value": task_name["value"]}, + "task_description": {"value": task_description["value"]} + } + outputs = [ + { + "type": "text", + "name": "task_name", + "label": "Task name", + }, + { + "type": "text", + "name": "task_description", + "label": "Task description", + } + ] + await update(inputs=inputs, outputs=outputs) + +ws = AsyncWorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +This utility is a thin wrapper of workflows.stepFailed API method. +Refer to https://api.slack.com/methods/workflows.updateStep for details. + +#### \_\_init\_\_ + +```python +def __init__(*, client: AsyncWebClient, body: dict) +``` diff --git a/docs/english/reference/workflows/step/utilities/complete.md b/docs/english/reference/workflows/step/utilities/complete.md new file mode 100644 index 000000000..624901495 --- /dev/null +++ b/docs/english/reference/workflows/step/utilities/complete.md @@ -0,0 +1,40 @@ +--- +sidebar_label: complete +title: slack_bolt.workflows.step.utilities.complete +--- + +## Complete Objects + +```python +class Complete() +``` + +`complete()` utility to tell Slack the completion of a step from app execution. + +```python +def execute(step, complete, fail): + inputs = step["inputs"] + # if everything was successful + outputs = { + "task_name": inputs["task_name"]["value"], + "task_description": inputs["task_description"]["value"], + } + complete(outputs=outputs) + +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +This utility is a thin wrapper of workflows.stepCompleted API method. +Refer to https://api.slack.com/methods/workflows.stepCompleted for details. + +#### \_\_init\_\_ + +```python +def __init__(*, client: WebClient, body: dict) +``` diff --git a/docs/english/reference/workflows/step/utilities/configure.md b/docs/english/reference/workflows/step/utilities/configure.md new file mode 100644 index 000000000..bc33f857a --- /dev/null +++ b/docs/english/reference/workflows/step/utilities/configure.md @@ -0,0 +1,47 @@ +--- +sidebar_label: configure +title: slack_bolt.workflows.step.utilities.configure +--- + +## Configure Objects + +```python +class Configure() +``` + +`configure()` utility to send the modal view in Workflow Builder. + +```python +def edit(ack, step, configure): + ack() + + blocks = [ + { + "type": "input", + "block_id": "task_name_input", + "element": { + "type": "plain_text_input", + "action_id": "name", + "placeholder": {"type": "plain_text", "text": "Add a task name"}, + }, + "label": {"type": "plain_text", "text": "Task name"}, + }, + ] + configure(blocks=blocks) + +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details. + +#### \_\_init\_\_ + +```python +def __init__(*, callback_id: str, client: WebClient, body: dict) +``` diff --git a/docs/english/reference/workflows/step/utilities/fail.md b/docs/english/reference/workflows/step/utilities/fail.md new file mode 100644 index 000000000..ccf3c6fec --- /dev/null +++ b/docs/english/reference/workflows/step/utilities/fail.md @@ -0,0 +1,37 @@ +--- +sidebar_label: fail +title: slack_bolt.workflows.step.utilities.fail +--- + +## Fail Objects + +```python +class Fail() +``` + +`fail()` utility to tell Slack the execution failure of a step from app. + +```python +def execute(step, complete, fail): + inputs = step["inputs"] + # if something went wrong + error = {"message": "Just testing step failure!"} + fail(error=error) + +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +This utility is a thin wrapper of workflows.stepFailed API method. +Refer to https://api.slack.com/methods/workflows.stepFailed for details. + +#### \_\_init\_\_ + +```python +def __init__(*, client: WebClient, body: dict) +``` diff --git a/docs/english/reference/workflows/step/utilities/index.md b/docs/english/reference/workflows/step/utilities/index.md new file mode 100644 index 000000000..54afc1e7e --- /dev/null +++ b/docs/english/reference/workflows/step/utilities/index.md @@ -0,0 +1,34 @@ +--- +sidebar_label: utilities +title: slack_bolt.workflows.step.utilities +--- + +Utilities specific to steps from apps. + +In steps from apps listeners, you can use a few specific listener/middleware arguments. + +### `edit` listener + +* `slack_bolt.workflows.step.utilities.configure` for building a modal view + +### `save` listener + +* `slack_bolt.workflows.step.utilities.update` for updating the step metadata + +### `execute` listener + +* `slack_bolt.workflows.step.utilities.fail` for notifying the execution failure to Slack +* `slack_bolt.workflows.step.utilities.complete` for notifying the execution completion to Slack + +For asyncio-based apps, refer to the corresponding `async` prefixed ones. + +## Submodules + +- [slack_bolt.workflows.step.utilities.async_complete](/tools/bolt-python/reference/workflows/step/utilities/async_complete) +- [slack_bolt.workflows.step.utilities.async_configure](/tools/bolt-python/reference/workflows/step/utilities/async_configure) +- [slack_bolt.workflows.step.utilities.async_fail](/tools/bolt-python/reference/workflows/step/utilities/async_fail) +- [slack_bolt.workflows.step.utilities.async_update](/tools/bolt-python/reference/workflows/step/utilities/async_update) +- [slack_bolt.workflows.step.utilities.complete](/tools/bolt-python/reference/workflows/step/utilities/complete) +- [slack_bolt.workflows.step.utilities.configure](/tools/bolt-python/reference/workflows/step/utilities/configure) +- [slack_bolt.workflows.step.utilities.fail](/tools/bolt-python/reference/workflows/step/utilities/fail) +- [slack_bolt.workflows.step.utilities.update](/tools/bolt-python/reference/workflows/step/utilities/update) diff --git a/docs/english/reference/workflows/step/utilities/update.md b/docs/english/reference/workflows/step/utilities/update.md new file mode 100644 index 000000000..066f89be3 --- /dev/null +++ b/docs/english/reference/workflows/step/utilities/update.md @@ -0,0 +1,56 @@ +--- +sidebar_label: update +title: slack_bolt.workflows.step.utilities.update +--- + +## Update Objects + +```python +class Update() +``` + +`update()` utility to tell Slack the processing results of a `save` listener. + +```python +def save(ack, view, update): + ack() + + values = view["state"]["values"] + task_name = values["task_name_input"]["name"] + task_description = values["task_description_input"]["description"] + + inputs = { + "task_name": {"value": task_name["value"]}, + "task_description": {"value": task_description["value"]} + } + outputs = [ + { + "type": "text", + "name": "task_name", + "label": "Task name", + }, + { + "type": "text", + "name": "task_description", + "label": "Task description", + } + ] + update(inputs=inputs, outputs=outputs) + +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +This utility is a thin wrapper of workflows.stepFailed API method. +Refer to https://api.slack.com/methods/workflows.updateStep for details. + +#### \_\_init\_\_ + +```python +def __init__(*, client: WebClient, body: dict) +``` diff --git a/docs/english/reference_redirects.json b/docs/english/reference_redirects.json new file mode 100644 index 000000000..f14a9c800 --- /dev/null +++ b/docs/english/reference_redirects.json @@ -0,0 +1,236 @@ +{ + "/tools/bolt-python/reference/adapter/aiohttp/index.html": "/tools/bolt-python/reference/adapter/aiohttp", + "/tools/bolt-python/reference/adapter/asgi/aiohttp/index.html": "/tools/bolt-python/reference/adapter/asgi/aiohttp", + "/tools/bolt-python/reference/adapter/asgi/async_handler.html": "/tools/bolt-python/reference/adapter/asgi/async_handler", + "/tools/bolt-python/reference/adapter/asgi/base_handler.html": "/tools/bolt-python/reference/adapter/asgi/base_handler", + "/tools/bolt-python/reference/adapter/asgi/builtin/index.html": "/tools/bolt-python/reference/adapter/asgi/builtin", + "/tools/bolt-python/reference/adapter/asgi/http_request.html": "/tools/bolt-python/reference/adapter/asgi/http_request", + "/tools/bolt-python/reference/adapter/asgi/http_response.html": "/tools/bolt-python/reference/adapter/asgi/http_response", + "/tools/bolt-python/reference/adapter/asgi/index.html": "/tools/bolt-python/reference/adapter/asgi", + "/tools/bolt-python/reference/adapter/asgi/utils.html": "/tools/bolt-python/reference/adapter/asgi/utils", + "/tools/bolt-python/reference/adapter/aws_lambda/chalice_handler.html": "/tools/bolt-python/reference/adapter/aws_lambda/chalice_handler", + "/tools/bolt-python/reference/adapter/aws_lambda/chalice_lazy_listener_runner.html": "/tools/bolt-python/reference/adapter/aws_lambda/chalice_lazy_listener_runner", + "/tools/bolt-python/reference/adapter/aws_lambda/handler.html": "/tools/bolt-python/reference/adapter/aws_lambda/handler", + "/tools/bolt-python/reference/adapter/aws_lambda/index.html": "/tools/bolt-python/reference/adapter/aws_lambda", + "/tools/bolt-python/reference/adapter/aws_lambda/internals.html": "/tools/bolt-python/reference/adapter/aws_lambda/internals", + "/tools/bolt-python/reference/adapter/aws_lambda/lambda_s3_oauth_flow.html": "/tools/bolt-python/reference/adapter/aws_lambda/lambda_s3_oauth_flow", + "/tools/bolt-python/reference/adapter/aws_lambda/lazy_listener_runner.html": "/tools/bolt-python/reference/adapter/aws_lambda/lazy_listener_runner", + "/tools/bolt-python/reference/adapter/aws_lambda/local_lambda_client.html": "/tools/bolt-python/reference/adapter/aws_lambda/local_lambda_client", + "/tools/bolt-python/reference/adapter/bottle/handler.html": "/tools/bolt-python/reference/adapter/bottle/handler", + "/tools/bolt-python/reference/adapter/bottle/index.html": "/tools/bolt-python/reference/adapter/bottle", + "/tools/bolt-python/reference/adapter/cherrypy/handler.html": "/tools/bolt-python/reference/adapter/cherrypy/handler", + "/tools/bolt-python/reference/adapter/cherrypy/index.html": "/tools/bolt-python/reference/adapter/cherrypy", + "/tools/bolt-python/reference/adapter/django/handler.html": "/tools/bolt-python/reference/adapter/django/handler", + "/tools/bolt-python/reference/adapter/django/index.html": "/tools/bolt-python/reference/adapter/django", + "/tools/bolt-python/reference/adapter/falcon/async_resource.html": "/tools/bolt-python/reference/adapter/falcon/async_resource", + "/tools/bolt-python/reference/adapter/falcon/index.html": "/tools/bolt-python/reference/adapter/falcon", + "/tools/bolt-python/reference/adapter/falcon/resource.html": "/tools/bolt-python/reference/adapter/falcon/resource", + "/tools/bolt-python/reference/adapter/fastapi/async_handler.html": "/tools/bolt-python/reference/adapter/fastapi/async_handler", + "/tools/bolt-python/reference/adapter/fastapi/index.html": "/tools/bolt-python/reference/adapter/fastapi", + "/tools/bolt-python/reference/adapter/flask/handler.html": "/tools/bolt-python/reference/adapter/flask/handler", + "/tools/bolt-python/reference/adapter/flask/index.html": "/tools/bolt-python/reference/adapter/flask", + "/tools/bolt-python/reference/adapter/google_cloud_functions/handler.html": "/tools/bolt-python/reference/adapter/google_cloud_functions/handler", + "/tools/bolt-python/reference/adapter/google_cloud_functions/index.html": "/tools/bolt-python/reference/adapter/google_cloud_functions", + "/tools/bolt-python/reference/adapter/index.html": "/tools/bolt-python/reference/adapter", + "/tools/bolt-python/reference/adapter/pyramid/handler.html": "/tools/bolt-python/reference/adapter/pyramid/handler", + "/tools/bolt-python/reference/adapter/pyramid/index.html": "/tools/bolt-python/reference/adapter/pyramid", + "/tools/bolt-python/reference/adapter/sanic/async_handler.html": "/tools/bolt-python/reference/adapter/sanic/async_handler", + "/tools/bolt-python/reference/adapter/sanic/index.html": "/tools/bolt-python/reference/adapter/sanic", + "/tools/bolt-python/reference/adapter/socket_mode/aiohttp/index.html": "/tools/bolt-python/reference/adapter/socket_mode/aiohttp", + "/tools/bolt-python/reference/adapter/socket_mode/async_base_handler.html": "/tools/bolt-python/reference/adapter/socket_mode/async_base_handler", + "/tools/bolt-python/reference/adapter/socket_mode/async_handler.html": "/tools/bolt-python/reference/adapter/socket_mode/async_handler", + "/tools/bolt-python/reference/adapter/socket_mode/async_internals.html": "/tools/bolt-python/reference/adapter/socket_mode/async_internals", + "/tools/bolt-python/reference/adapter/socket_mode/base_handler.html": "/tools/bolt-python/reference/adapter/socket_mode/base_handler", + "/tools/bolt-python/reference/adapter/socket_mode/builtin/index.html": "/tools/bolt-python/reference/adapter/socket_mode/builtin", + "/tools/bolt-python/reference/adapter/socket_mode/index.html": "/tools/bolt-python/reference/adapter/socket_mode", + "/tools/bolt-python/reference/adapter/socket_mode/internals.html": "/tools/bolt-python/reference/adapter/socket_mode/internals", + "/tools/bolt-python/reference/adapter/socket_mode/websocket_client/index.html": "/tools/bolt-python/reference/adapter/socket_mode/websocket_client", + "/tools/bolt-python/reference/adapter/socket_mode/websockets/index.html": "/tools/bolt-python/reference/adapter/socket_mode/websockets", + "/tools/bolt-python/reference/adapter/starlette/async_handler.html": "/tools/bolt-python/reference/adapter/starlette/async_handler", + "/tools/bolt-python/reference/adapter/starlette/handler.html": "/tools/bolt-python/reference/adapter/starlette/handler", + "/tools/bolt-python/reference/adapter/starlette/index.html": "/tools/bolt-python/reference/adapter/starlette", + "/tools/bolt-python/reference/adapter/tornado/async_handler.html": "/tools/bolt-python/reference/adapter/tornado/async_handler", + "/tools/bolt-python/reference/adapter/tornado/handler.html": "/tools/bolt-python/reference/adapter/tornado/handler", + "/tools/bolt-python/reference/adapter/tornado/index.html": "/tools/bolt-python/reference/adapter/tornado", + "/tools/bolt-python/reference/adapter/wsgi/handler.html": "/tools/bolt-python/reference/adapter/wsgi/handler", + "/tools/bolt-python/reference/adapter/wsgi/http_request.html": "/tools/bolt-python/reference/adapter/wsgi/http_request", + "/tools/bolt-python/reference/adapter/wsgi/http_response.html": "/tools/bolt-python/reference/adapter/wsgi/http_response", + "/tools/bolt-python/reference/adapter/wsgi/index.html": "/tools/bolt-python/reference/adapter/wsgi", + "/tools/bolt-python/reference/adapter/wsgi/internals.html": "/tools/bolt-python/reference/adapter/wsgi/internals", + "/tools/bolt-python/reference/app/app.html": "/tools/bolt-python/reference/app/app", + "/tools/bolt-python/reference/app/async_app.html": "/tools/bolt-python/reference/app/async_app", + "/tools/bolt-python/reference/app/async_server.html": "/tools/bolt-python/reference/app/async_server", + "/tools/bolt-python/reference/app/index.html": "/tools/bolt-python/reference/app", + "/tools/bolt-python/reference/async_app.html": "/tools/bolt-python/reference/async_app", + "/tools/bolt-python/reference/authorization/async_authorize.html": "/tools/bolt-python/reference/authorization/async_authorize", + "/tools/bolt-python/reference/authorization/async_authorize_args.html": "/tools/bolt-python/reference/authorization/async_authorize_args", + "/tools/bolt-python/reference/authorization/authorize.html": "/tools/bolt-python/reference/authorization/authorize", + "/tools/bolt-python/reference/authorization/authorize_args.html": "/tools/bolt-python/reference/authorization/authorize_args", + "/tools/bolt-python/reference/authorization/authorize_result.html": "/tools/bolt-python/reference/authorization/authorize_result", + "/tools/bolt-python/reference/authorization/index.html": "/tools/bolt-python/reference/authorization", + "/tools/bolt-python/reference/context/ack/ack.html": "/tools/bolt-python/reference/context/ack/ack", + "/tools/bolt-python/reference/context/ack/async_ack.html": "/tools/bolt-python/reference/context/ack/async_ack", + "/tools/bolt-python/reference/context/ack/index.html": "/tools/bolt-python/reference/context/ack", + "/tools/bolt-python/reference/context/ack/internals.html": "/tools/bolt-python/reference/context/ack/internals", + "/tools/bolt-python/reference/context/assistant/assistant_utilities.html": "/tools/bolt-python/reference/context/assistant/assistant_utilities", + "/tools/bolt-python/reference/context/assistant/async_assistant_utilities.html": "/tools/bolt-python/reference/context/assistant/async_assistant_utilities", + "/tools/bolt-python/reference/context/assistant/index.html": "/tools/bolt-python/reference/context/assistant", + "/tools/bolt-python/reference/context/assistant/internals.html": "/tools/bolt-python/reference/context/assistant/internals", + "/tools/bolt-python/reference/context/assistant/thread_context/index.html": "/tools/bolt-python/reference/context/assistant/thread_context", + "/tools/bolt-python/reference/context/assistant/thread_context_store/async_store.html": "/tools/bolt-python/reference/context/assistant/thread_context_store/async_store", + "/tools/bolt-python/reference/context/assistant/thread_context_store/default_async_store.html": "/tools/bolt-python/reference/context/assistant/thread_context_store/default_async_store", + "/tools/bolt-python/reference/context/assistant/thread_context_store/default_store.html": "/tools/bolt-python/reference/context/assistant/thread_context_store/default_store", + "/tools/bolt-python/reference/context/assistant/thread_context_store/file/index.html": "/tools/bolt-python/reference/context/assistant/thread_context_store/file", + "/tools/bolt-python/reference/context/assistant/thread_context_store/index.html": "/tools/bolt-python/reference/context/assistant/thread_context_store", + "/tools/bolt-python/reference/context/assistant/thread_context_store/store.html": "/tools/bolt-python/reference/context/assistant/thread_context_store/store", + "/tools/bolt-python/reference/context/async_context.html": "/tools/bolt-python/reference/context/async_context", + "/tools/bolt-python/reference/context/base_context.html": "/tools/bolt-python/reference/context/base_context", + "/tools/bolt-python/reference/context/complete/async_complete.html": "/tools/bolt-python/reference/context/complete/async_complete", + "/tools/bolt-python/reference/context/complete/complete.html": "/tools/bolt-python/reference/context/complete/complete", + "/tools/bolt-python/reference/context/complete/index.html": "/tools/bolt-python/reference/context/complete", + "/tools/bolt-python/reference/context/context.html": "/tools/bolt-python/reference/context/context", + "/tools/bolt-python/reference/context/fail/async_fail.html": "/tools/bolt-python/reference/context/fail/async_fail", + "/tools/bolt-python/reference/context/fail/fail.html": "/tools/bolt-python/reference/context/fail/fail", + "/tools/bolt-python/reference/context/fail/index.html": "/tools/bolt-python/reference/context/fail", + "/tools/bolt-python/reference/context/get_thread_context/async_get_thread_context.html": "/tools/bolt-python/reference/context/get_thread_context/async_get_thread_context", + "/tools/bolt-python/reference/context/get_thread_context/get_thread_context.html": "/tools/bolt-python/reference/context/get_thread_context/get_thread_context", + "/tools/bolt-python/reference/context/get_thread_context/index.html": "/tools/bolt-python/reference/context/get_thread_context", + "/tools/bolt-python/reference/context/index.html": "/tools/bolt-python/reference/context", + "/tools/bolt-python/reference/context/respond/async_respond.html": "/tools/bolt-python/reference/context/respond/async_respond", + "/tools/bolt-python/reference/context/respond/index.html": "/tools/bolt-python/reference/context/respond", + "/tools/bolt-python/reference/context/respond/internals.html": "/tools/bolt-python/reference/context/respond/internals", + "/tools/bolt-python/reference/context/respond/respond.html": "/tools/bolt-python/reference/context/respond/respond", + "/tools/bolt-python/reference/context/save_thread_context/async_save_thread_context.html": "/tools/bolt-python/reference/context/save_thread_context/async_save_thread_context", + "/tools/bolt-python/reference/context/save_thread_context/index.html": "/tools/bolt-python/reference/context/save_thread_context", + "/tools/bolt-python/reference/context/save_thread_context/save_thread_context.html": "/tools/bolt-python/reference/context/save_thread_context/save_thread_context", + "/tools/bolt-python/reference/context/say/async_say.html": "/tools/bolt-python/reference/context/say/async_say", + "/tools/bolt-python/reference/context/say/index.html": "/tools/bolt-python/reference/context/say", + "/tools/bolt-python/reference/context/say/internals.html": "/tools/bolt-python/reference/context/say/internals", + "/tools/bolt-python/reference/context/say/say.html": "/tools/bolt-python/reference/context/say/say", + "/tools/bolt-python/reference/context/say_stream/async_say_stream.html": "/tools/bolt-python/reference/context/say_stream/async_say_stream", + "/tools/bolt-python/reference/context/say_stream/index.html": "/tools/bolt-python/reference/context/say_stream", + "/tools/bolt-python/reference/context/say_stream/say_stream.html": "/tools/bolt-python/reference/context/say_stream/say_stream", + "/tools/bolt-python/reference/context/set_status/async_set_status.html": "/tools/bolt-python/reference/context/set_status/async_set_status", + "/tools/bolt-python/reference/context/set_status/index.html": "/tools/bolt-python/reference/context/set_status", + "/tools/bolt-python/reference/context/set_status/set_status.html": "/tools/bolt-python/reference/context/set_status/set_status", + "/tools/bolt-python/reference/context/set_suggested_prompts/async_set_suggested_prompts.html": "/tools/bolt-python/reference/context/set_suggested_prompts/async_set_suggested_prompts", + "/tools/bolt-python/reference/context/set_suggested_prompts/index.html": "/tools/bolt-python/reference/context/set_suggested_prompts", + "/tools/bolt-python/reference/context/set_suggested_prompts/set_suggested_prompts.html": "/tools/bolt-python/reference/context/set_suggested_prompts/set_suggested_prompts", + "/tools/bolt-python/reference/context/set_title/async_set_title.html": "/tools/bolt-python/reference/context/set_title/async_set_title", + "/tools/bolt-python/reference/context/set_title/index.html": "/tools/bolt-python/reference/context/set_title", + "/tools/bolt-python/reference/context/set_title/set_title.html": "/tools/bolt-python/reference/context/set_title/set_title", + "/tools/bolt-python/reference/error/index.html": "/tools/bolt-python/reference/error", + "/tools/bolt-python/reference/index.html": "/tools/bolt-python/reference", + "/tools/bolt-python/reference/kwargs_injection/args.html": "/tools/bolt-python/reference/kwargs_injection/args", + "/tools/bolt-python/reference/kwargs_injection/async_args.html": "/tools/bolt-python/reference/kwargs_injection/async_args", + "/tools/bolt-python/reference/kwargs_injection/async_utils.html": "/tools/bolt-python/reference/kwargs_injection/async_utils", + "/tools/bolt-python/reference/kwargs_injection/index.html": "/tools/bolt-python/reference/kwargs_injection", + "/tools/bolt-python/reference/kwargs_injection/utils.html": "/tools/bolt-python/reference/kwargs_injection/utils", + "/tools/bolt-python/reference/lazy_listener/async_internals.html": "/tools/bolt-python/reference/lazy_listener/async_internals", + "/tools/bolt-python/reference/lazy_listener/async_runner.html": "/tools/bolt-python/reference/lazy_listener/async_runner", + "/tools/bolt-python/reference/lazy_listener/asyncio_runner.html": "/tools/bolt-python/reference/lazy_listener/asyncio_runner", + "/tools/bolt-python/reference/lazy_listener/index.html": "/tools/bolt-python/reference/lazy_listener", + "/tools/bolt-python/reference/lazy_listener/internals.html": "/tools/bolt-python/reference/lazy_listener/internals", + "/tools/bolt-python/reference/lazy_listener/runner.html": "/tools/bolt-python/reference/lazy_listener/runner", + "/tools/bolt-python/reference/lazy_listener/thread_runner.html": "/tools/bolt-python/reference/lazy_listener/thread_runner", + "/tools/bolt-python/reference/listener/async_builtins.html": "/tools/bolt-python/reference/listener/async_builtins", + "/tools/bolt-python/reference/listener/async_listener.html": "/tools/bolt-python/reference/listener/async_listener", + "/tools/bolt-python/reference/listener/async_listener_completion_handler.html": "/tools/bolt-python/reference/listener/async_listener_completion_handler", + "/tools/bolt-python/reference/listener/async_listener_error_handler.html": "/tools/bolt-python/reference/listener/async_listener_error_handler", + "/tools/bolt-python/reference/listener/async_listener_start_handler.html": "/tools/bolt-python/reference/listener/async_listener_start_handler", + "/tools/bolt-python/reference/listener/asyncio_runner.html": "/tools/bolt-python/reference/listener/asyncio_runner", + "/tools/bolt-python/reference/listener/builtins.html": "/tools/bolt-python/reference/listener/builtins", + "/tools/bolt-python/reference/listener/custom_listener.html": "/tools/bolt-python/reference/listener/custom_listener", + "/tools/bolt-python/reference/listener/index.html": "/tools/bolt-python/reference/listener", + "/tools/bolt-python/reference/listener/listener.html": "/tools/bolt-python/reference/listener/listener", + "/tools/bolt-python/reference/listener/listener_completion_handler.html": "/tools/bolt-python/reference/listener/listener_completion_handler", + "/tools/bolt-python/reference/listener/listener_error_handler.html": "/tools/bolt-python/reference/listener/listener_error_handler", + "/tools/bolt-python/reference/listener/listener_start_handler.html": "/tools/bolt-python/reference/listener/listener_start_handler", + "/tools/bolt-python/reference/listener/thread_runner.html": "/tools/bolt-python/reference/listener/thread_runner", + "/tools/bolt-python/reference/listener_matcher/async_builtins.html": "/tools/bolt-python/reference/listener_matcher/async_builtins", + "/tools/bolt-python/reference/listener_matcher/async_listener_matcher.html": "/tools/bolt-python/reference/listener_matcher/async_listener_matcher", + "/tools/bolt-python/reference/listener_matcher/builtins.html": "/tools/bolt-python/reference/listener_matcher/builtins", + "/tools/bolt-python/reference/listener_matcher/custom_listener_matcher.html": "/tools/bolt-python/reference/listener_matcher/custom_listener_matcher", + "/tools/bolt-python/reference/listener_matcher/index.html": "/tools/bolt-python/reference/listener_matcher", + "/tools/bolt-python/reference/listener_matcher/listener_matcher.html": "/tools/bolt-python/reference/listener_matcher/listener_matcher", + "/tools/bolt-python/reference/logger/index.html": "/tools/bolt-python/reference/logger", + "/tools/bolt-python/reference/logger/messages.html": "/tools/bolt-python/reference/logger/messages", + "/tools/bolt-python/reference/middleware/assistant/assistant.html": "/tools/bolt-python/reference/middleware/assistant/assistant", + "/tools/bolt-python/reference/middleware/assistant/async_assistant.html": "/tools/bolt-python/reference/middleware/assistant/async_assistant", + "/tools/bolt-python/reference/middleware/assistant/index.html": "/tools/bolt-python/reference/middleware/assistant", + "/tools/bolt-python/reference/middleware/async_builtins.html": "/tools/bolt-python/reference/middleware/async_builtins", + "/tools/bolt-python/reference/middleware/async_custom_middleware.html": "/tools/bolt-python/reference/middleware/async_custom_middleware", + "/tools/bolt-python/reference/middleware/async_middleware.html": "/tools/bolt-python/reference/middleware/async_middleware", + "/tools/bolt-python/reference/middleware/async_middleware_error_handler.html": "/tools/bolt-python/reference/middleware/async_middleware_error_handler", + "/tools/bolt-python/reference/middleware/attaching_conversation_kwargs/async_attaching_conversation_kwargs.html": "/tools/bolt-python/reference/middleware/attaching_conversation_kwargs/async_attaching_conversation_kwargs", + "/tools/bolt-python/reference/middleware/attaching_conversation_kwargs/attaching_conversation_kwargs.html": "/tools/bolt-python/reference/middleware/attaching_conversation_kwargs/attaching_conversation_kwargs", + "/tools/bolt-python/reference/middleware/attaching_conversation_kwargs/index.html": "/tools/bolt-python/reference/middleware/attaching_conversation_kwargs", + "/tools/bolt-python/reference/middleware/attaching_function_token/async_attaching_function_token.html": "/tools/bolt-python/reference/middleware/attaching_function_token/async_attaching_function_token", + "/tools/bolt-python/reference/middleware/attaching_function_token/attaching_function_token.html": "/tools/bolt-python/reference/middleware/attaching_function_token/attaching_function_token", + "/tools/bolt-python/reference/middleware/attaching_function_token/index.html": "/tools/bolt-python/reference/middleware/attaching_function_token", + "/tools/bolt-python/reference/middleware/authorization/async_authorization.html": "/tools/bolt-python/reference/middleware/authorization/async_authorization", + "/tools/bolt-python/reference/middleware/authorization/async_internals.html": "/tools/bolt-python/reference/middleware/authorization/async_internals", + "/tools/bolt-python/reference/middleware/authorization/async_multi_teams_authorization.html": "/tools/bolt-python/reference/middleware/authorization/async_multi_teams_authorization", + "/tools/bolt-python/reference/middleware/authorization/async_single_team_authorization.html": "/tools/bolt-python/reference/middleware/authorization/async_single_team_authorization", + "/tools/bolt-python/reference/middleware/authorization/authorization.html": "/tools/bolt-python/reference/middleware/authorization/authorization", + "/tools/bolt-python/reference/middleware/authorization/index.html": "/tools/bolt-python/reference/middleware/authorization", + "/tools/bolt-python/reference/middleware/authorization/internals.html": "/tools/bolt-python/reference/middleware/authorization/internals", + "/tools/bolt-python/reference/middleware/authorization/multi_teams_authorization.html": "/tools/bolt-python/reference/middleware/authorization/multi_teams_authorization", + "/tools/bolt-python/reference/middleware/authorization/single_team_authorization.html": "/tools/bolt-python/reference/middleware/authorization/single_team_authorization", + "/tools/bolt-python/reference/middleware/custom_middleware.html": "/tools/bolt-python/reference/middleware/custom_middleware", + "/tools/bolt-python/reference/middleware/ignoring_self_events/async_ignoring_self_events.html": "/tools/bolt-python/reference/middleware/ignoring_self_events/async_ignoring_self_events", + "/tools/bolt-python/reference/middleware/ignoring_self_events/ignoring_self_events.html": "/tools/bolt-python/reference/middleware/ignoring_self_events/ignoring_self_events", + "/tools/bolt-python/reference/middleware/ignoring_self_events/index.html": "/tools/bolt-python/reference/middleware/ignoring_self_events", + "/tools/bolt-python/reference/middleware/index.html": "/tools/bolt-python/reference/middleware", + "/tools/bolt-python/reference/middleware/message_listener_matches/async_message_listener_matches.html": "/tools/bolt-python/reference/middleware/message_listener_matches/async_message_listener_matches", + "/tools/bolt-python/reference/middleware/message_listener_matches/index.html": "/tools/bolt-python/reference/middleware/message_listener_matches", + "/tools/bolt-python/reference/middleware/message_listener_matches/message_listener_matches.html": "/tools/bolt-python/reference/middleware/message_listener_matches/message_listener_matches", + "/tools/bolt-python/reference/middleware/middleware.html": "/tools/bolt-python/reference/middleware/middleware", + "/tools/bolt-python/reference/middleware/middleware_error_handler.html": "/tools/bolt-python/reference/middleware/middleware_error_handler", + "/tools/bolt-python/reference/middleware/request_verification/async_request_verification.html": "/tools/bolt-python/reference/middleware/request_verification/async_request_verification", + "/tools/bolt-python/reference/middleware/request_verification/index.html": "/tools/bolt-python/reference/middleware/request_verification", + "/tools/bolt-python/reference/middleware/request_verification/request_verification.html": "/tools/bolt-python/reference/middleware/request_verification/request_verification", + "/tools/bolt-python/reference/middleware/ssl_check/async_ssl_check.html": "/tools/bolt-python/reference/middleware/ssl_check/async_ssl_check", + "/tools/bolt-python/reference/middleware/ssl_check/index.html": "/tools/bolt-python/reference/middleware/ssl_check", + "/tools/bolt-python/reference/middleware/ssl_check/ssl_check.html": "/tools/bolt-python/reference/middleware/ssl_check/ssl_check", + "/tools/bolt-python/reference/middleware/url_verification/async_url_verification.html": "/tools/bolt-python/reference/middleware/url_verification/async_url_verification", + "/tools/bolt-python/reference/middleware/url_verification/index.html": "/tools/bolt-python/reference/middleware/url_verification", + "/tools/bolt-python/reference/middleware/url_verification/url_verification.html": "/tools/bolt-python/reference/middleware/url_verification/url_verification", + "/tools/bolt-python/reference/oauth/async_callback_options.html": "/tools/bolt-python/reference/oauth/async_callback_options", + "/tools/bolt-python/reference/oauth/async_internals.html": "/tools/bolt-python/reference/oauth/async_internals", + "/tools/bolt-python/reference/oauth/async_oauth_flow.html": "/tools/bolt-python/reference/oauth/async_oauth_flow", + "/tools/bolt-python/reference/oauth/async_oauth_settings.html": "/tools/bolt-python/reference/oauth/async_oauth_settings", + "/tools/bolt-python/reference/oauth/callback_options.html": "/tools/bolt-python/reference/oauth/callback_options", + "/tools/bolt-python/reference/oauth/index.html": "/tools/bolt-python/reference/oauth", + "/tools/bolt-python/reference/oauth/internals.html": "/tools/bolt-python/reference/oauth/internals", + "/tools/bolt-python/reference/oauth/oauth_flow.html": "/tools/bolt-python/reference/oauth/oauth_flow", + "/tools/bolt-python/reference/oauth/oauth_settings.html": "/tools/bolt-python/reference/oauth/oauth_settings", + "/tools/bolt-python/reference/request/async_internals.html": "/tools/bolt-python/reference/request/async_internals", + "/tools/bolt-python/reference/request/async_request.html": "/tools/bolt-python/reference/request/async_request", + "/tools/bolt-python/reference/request/index.html": "/tools/bolt-python/reference/request", + "/tools/bolt-python/reference/request/internals.html": "/tools/bolt-python/reference/request/internals", + "/tools/bolt-python/reference/request/payload_utils.html": "/tools/bolt-python/reference/request/payload_utils", + "/tools/bolt-python/reference/request/request.html": "/tools/bolt-python/reference/request/request", + "/tools/bolt-python/reference/response/index.html": "/tools/bolt-python/reference/response", + "/tools/bolt-python/reference/response/response.html": "/tools/bolt-python/reference/response/response", + "/tools/bolt-python/reference/util/async_utils.html": "/tools/bolt-python/reference/util/async_utils", + "/tools/bolt-python/reference/util/index.html": "/tools/bolt-python/reference/util", + "/tools/bolt-python/reference/util/utils.html": "/tools/bolt-python/reference/util/utils", + "/tools/bolt-python/reference/version.html": "/tools/bolt-python/reference/version", + "/tools/bolt-python/reference/workflows/index.html": "/tools/bolt-python/reference/workflows", + "/tools/bolt-python/reference/workflows/step/async_step.html": "/tools/bolt-python/reference/workflows/step/async_step", + "/tools/bolt-python/reference/workflows/step/async_step_middleware.html": "/tools/bolt-python/reference/workflows/step/async_step_middleware", + "/tools/bolt-python/reference/workflows/step/index.html": "/tools/bolt-python/reference/workflows/step", + "/tools/bolt-python/reference/workflows/step/internals.html": "/tools/bolt-python/reference/workflows/step/internals", + "/tools/bolt-python/reference/workflows/step/step.html": "/tools/bolt-python/reference/workflows/step/step", + "/tools/bolt-python/reference/workflows/step/step_middleware.html": "/tools/bolt-python/reference/workflows/step/step_middleware", + "/tools/bolt-python/reference/workflows/step/utilities/async_complete.html": "/tools/bolt-python/reference/workflows/step/utilities/async_complete", + "/tools/bolt-python/reference/workflows/step/utilities/async_configure.html": "/tools/bolt-python/reference/workflows/step/utilities/async_configure", + "/tools/bolt-python/reference/workflows/step/utilities/async_fail.html": "/tools/bolt-python/reference/workflows/step/utilities/async_fail", + "/tools/bolt-python/reference/workflows/step/utilities/async_update.html": "/tools/bolt-python/reference/workflows/step/utilities/async_update", + "/tools/bolt-python/reference/workflows/step/utilities/complete.html": "/tools/bolt-python/reference/workflows/step/utilities/complete", + "/tools/bolt-python/reference/workflows/step/utilities/configure.html": "/tools/bolt-python/reference/workflows/step/utilities/configure", + "/tools/bolt-python/reference/workflows/step/utilities/fail.html": "/tools/bolt-python/reference/workflows/step/utilities/fail", + "/tools/bolt-python/reference/workflows/step/utilities/index.html": "/tools/bolt-python/reference/workflows/step/utilities", + "/tools/bolt-python/reference/workflows/step/utilities/update.html": "/tools/bolt-python/reference/workflows/step/utilities/update" +} \ No newline at end of file diff --git a/docs/reference/adapter/aiohttp/index.html b/docs/reference/adapter/aiohttp/index.html deleted file mode 100644 index 7d7ceedbe..000000000 --- a/docs/reference/adapter/aiohttp/index.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - -slack_bolt.adapter.aiohttp API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.aiohttp

-
-
-
-
-
-
-
-
-

Functions

-
-
-async def to_aiohttp_response(bolt_resp: BoltResponse) ‑> aiohttp.web_response.Response -
-
-
- -Expand source code - -
async def to_aiohttp_response(bolt_resp: BoltResponse) -> web.Response:
-    content_type = bolt_resp.headers.pop(
-        "content-type",
-        ["application/json" if bolt_resp.body.startswith("{") else "text/plain"],
-    )[0]
-    content_type = re.sub(r";\s*charset=utf-8", "", content_type)
-    resp = web.Response(
-        status=bolt_resp.status,
-        body=bolt_resp.body,
-        headers=bolt_resp.first_headers_without_set_cookie(),
-        content_type=content_type,
-    )
-    for cookie in bolt_resp.cookies():
-        for name, c in cookie.items():
-            resp.set_cookie(
-                name=name,
-                value=c.value,
-                max_age=c.get("max-age"),
-                expires=c.get("expires"),
-                path=c.get("path"),  # type: ignore[arg-type]
-                domain=c.get("domain"),
-                secure=True,
-                httponly=True,
-            )
-    return resp
-
-
-
-
-async def to_bolt_request(request: aiohttp.web_request.Request) ‑> AsyncBoltRequest -
-
-
- -Expand source code - -
async def to_bolt_request(request: web.Request) -> AsyncBoltRequest:
-    return AsyncBoltRequest(
-        body=await request.text(),
-        query=request.query_string,
-        headers=request.headers,  # type: ignore[arg-type]
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/asgi/aiohttp/index.html b/docs/reference/adapter/asgi/aiohttp/index.html deleted file mode 100644 index a6aa7c92d..000000000 --- a/docs/reference/adapter/asgi/aiohttp/index.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - -slack_bolt.adapter.asgi.aiohttp API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.asgi.aiohttp

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSlackRequestHandler -(app: AsyncApp,
path: str = '/slack/events')
-
-
-
- -Expand source code - -
class AsyncSlackRequestHandler(SlackRequestHandler):
-    app: AsyncApp
-
-    def __init__(self, app: AsyncApp, path: str = "/slack/events"):
-        """Setup Bolt as an ASGI web framework, this will make your application compatible with ASGI web servers.
-        This can be used for production deployment.
-
-        With the default settings, `http://localhost:3000/slack/events`
-        Run Bolt with [uvicron](https://www.uvicorn.org/)
-
-            # Python
-            app = AsyncApp()
-            api = SlackRequestHandler(app)
-
-            # bash
-            export SLACK_SIGNING_SECRET=***
-            export SLACK_BOT_TOKEN=xoxb-***
-            uvicorn app:api --port 3000 --log-level debug
-
-        Args:
-            app: Your bolt application
-            path: The path to handle request from Slack (Default: `/slack/events`)
-        """
-        self.path = path
-        self.app = app
-
-    async def dispatch(self, request: AsgiHttpRequest) -> BoltResponse:
-        return await self.app.async_dispatch(
-            AsyncBoltRequest(body=await request.get_raw_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    async def handle_installation(self, request: AsgiHttpRequest) -> BoltResponse:
-        return await self.app.oauth_flow.handle_installation(  # type: ignore[union-attr]
-            AsyncBoltRequest(body=await request.get_raw_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    async def handle_callback(self, request: AsgiHttpRequest) -> BoltResponse:
-        return await self.app.oauth_flow.handle_callback(  # type: ignore[union-attr]
-            AsyncBoltRequest(body=await request.get_raw_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-

Setup Bolt as an ASGI web framework, this will make your application compatible with ASGI web servers. -This can be used for production deployment.

-

With the default settings, http://localhost:3000/slack/events -Run Bolt with uvicron

-
# Python
-app = AsyncApp()
-api = SlackRequestHandler(app)
-
-# bash
-export SLACK_SIGNING_SECRET=***
-export SLACK_BOT_TOKEN=xoxb-***
-uvicorn app:api --port 3000 --log-level debug
-
-

Args

-
-
app
-
Your bolt application
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/asgi/async_handler.html b/docs/reference/adapter/asgi/async_handler.html deleted file mode 100644 index 23433ffce..000000000 --- a/docs/reference/adapter/asgi/async_handler.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - -slack_bolt.adapter.asgi.async_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.asgi.async_handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSlackRequestHandler -(app: AsyncApp,
path: str = '/slack/events')
-
-
-
- -Expand source code - -
class AsyncSlackRequestHandler(SlackRequestHandler):
-    app: AsyncApp
-
-    def __init__(self, app: AsyncApp, path: str = "/slack/events"):
-        """Setup Bolt as an ASGI web framework, this will make your application compatible with ASGI web servers.
-        This can be used for production deployment.
-
-        With the default settings, `http://localhost:3000/slack/events`
-        Run Bolt with [uvicron](https://www.uvicorn.org/)
-
-            # Python
-            app = AsyncApp()
-            api = SlackRequestHandler(app)
-
-            # bash
-            export SLACK_SIGNING_SECRET=***
-            export SLACK_BOT_TOKEN=xoxb-***
-            uvicorn app:api --port 3000 --log-level debug
-
-        Args:
-            app: Your bolt application
-            path: The path to handle request from Slack (Default: `/slack/events`)
-        """
-        self.path = path
-        self.app = app
-
-    async def dispatch(self, request: AsgiHttpRequest) -> BoltResponse:
-        return await self.app.async_dispatch(
-            AsyncBoltRequest(body=await request.get_raw_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    async def handle_installation(self, request: AsgiHttpRequest) -> BoltResponse:
-        return await self.app.oauth_flow.handle_installation(  # type: ignore[union-attr]
-            AsyncBoltRequest(body=await request.get_raw_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    async def handle_callback(self, request: AsgiHttpRequest) -> BoltResponse:
-        return await self.app.oauth_flow.handle_callback(  # type: ignore[union-attr]
-            AsyncBoltRequest(body=await request.get_raw_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-

Setup Bolt as an ASGI web framework, this will make your application compatible with ASGI web servers. -This can be used for production deployment.

-

With the default settings, http://localhost:3000/slack/events -Run Bolt with uvicron

-
# Python
-app = AsyncApp()
-api = SlackRequestHandler(app)
-
-# bash
-export SLACK_SIGNING_SECRET=***
-export SLACK_BOT_TOKEN=xoxb-***
-uvicorn app:api --port 3000 --log-level debug
-
-

Args

-
-
app
-
Your bolt application
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/asgi/base_handler.html b/docs/reference/adapter/asgi/base_handler.html deleted file mode 100644 index 74358683e..000000000 --- a/docs/reference/adapter/asgi/base_handler.html +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - -slack_bolt.adapter.asgi.base_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.asgi.base_handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class BaseSlackRequestHandler -
-
-
- -Expand source code - -
class BaseSlackRequestHandler:
-    app: Union[App, "AsyncApp"]  # type: ignore[name-defined]
-    path: str
-
-    async def dispatch(self, request: AsgiHttpRequest) -> BoltResponse:
-        """Dispatches a request to the Bolt App"""
-        raise NotImplementedError
-
-    async def handle_installation(self, request: AsgiHttpRequest) -> BoltResponse:
-        """Handles installation of the OAuthFlow"""
-        raise NotImplementedError
-
-    async def handle_callback(self, request: AsgiHttpRequest) -> BoltResponse:
-        """Handles the callback of the OAuthFlow"""
-        raise NotImplementedError
-
-    async def _get_http_response(self, method: str, path: str, request: AsgiHttpRequest) -> AsgiHttpResponse:
-        if method == "GET":
-            if self.app.oauth_flow is not None:
-                if path == self.app.oauth_flow.install_path:
-                    bolt_response: BoltResponse = await self.handle_installation(request)
-                    return AsgiHttpResponse(
-                        status=bolt_response.status, headers=bolt_response.headers, body=bolt_response.body
-                    )
-                elif path == self.app.oauth_flow.redirect_uri_path:
-                    bolt_response = await self.handle_callback(request)
-                    return AsgiHttpResponse(
-                        status=bolt_response.status, headers=bolt_response.headers, body=bolt_response.body
-                    )
-        if method == "POST" and path == self.path:
-            bolt_response = await self.dispatch(request)
-            return AsgiHttpResponse(status=bolt_response.status, headers=bolt_response.headers, body=bolt_response.body)
-        return AsgiHttpResponse(status=404, headers={"content-type": ["text/plain;charset=utf-8"]}, body="Not Found")
-
-    async def _handle_lifespan(self, receive: Callable, send: Callable) -> None:
-        message = await receive()
-        if message["type"] == "lifespan.startup":
-            await send({"type": "lifespan.startup.complete"})
-            message = await receive()
-        if message["type"] == "lifespan.shutdown":
-            await send({"type": "lifespan.shutdown.complete"})
-
-    async def __call__(self, scope: scope_type, receive: Callable, send: Callable) -> None:
-        if scope["type"] == "http":
-            response: AsgiHttpResponse = await self._get_http_response(
-                method=scope["method"], path=scope["path"], request=AsgiHttpRequest(scope, receive)  # type: ignore[arg-type]
-            )
-            await send(response.get_response_start())
-            await send(response.get_response_body())
-            return
-        if scope["type"] == "lifespan":
-            await self._handle_lifespan(receive, send)
-            return
-        raise TypeError(f"Unsupported scope type: {scope['type']!r}")
-
-
-

Subclasses

- -

Class variables

-
-
var appApp | AsyncApp
-
-

The type of the None singleton.

-
-
var path : str
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-async def dispatch(self,
request: AsgiHttpRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
async def dispatch(self, request: AsgiHttpRequest) -> BoltResponse:
-    """Dispatches a request to the Bolt App"""
-    raise NotImplementedError
-
-

Dispatches a request to the Bolt App

-
-
-async def handle_callback(self,
request: AsgiHttpRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
async def handle_callback(self, request: AsgiHttpRequest) -> BoltResponse:
-    """Handles the callback of the OAuthFlow"""
-    raise NotImplementedError
-
-

Handles the callback of the OAuthFlow

-
-
-async def handle_installation(self,
request: AsgiHttpRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
async def handle_installation(self, request: AsgiHttpRequest) -> BoltResponse:
-    """Handles installation of the OAuthFlow"""
-    raise NotImplementedError
-
-

Handles installation of the OAuthFlow

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/asgi/builtin/index.html b/docs/reference/adapter/asgi/builtin/index.html deleted file mode 100644 index 9147380c5..000000000 --- a/docs/reference/adapter/asgi/builtin/index.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - -slack_bolt.adapter.asgi.builtin API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.asgi.builtin

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App,
path: str = '/slack/events')
-
-
-
- -Expand source code - -
class SlackRequestHandler(BaseSlackRequestHandler):
-    def __init__(self, app: App, path: str = "/slack/events"):
-        """Setup Bolt as an ASGI web framework, this will make your application compatible with ASGI web servers.
-        This can be used for production deployment.
-
-        With the default settings, `http://localhost:3000/slack/events`
-        Run Bolt with [uvicron](https://www.uvicorn.org/)
-
-            # Python
-            app = App()
-            api = SlackRequestHandler(app)
-
-            # bash
-            export SLACK_SIGNING_SECRET=***
-            export SLACK_BOT_TOKEN=xoxb-***
-            uvicorn app:api --port 3000 --log-level debug
-
-        Args:
-            app: Your bolt application
-            path: The path to handle request from Slack (Default: `/slack/events`)
-        """
-        self.path = path
-        self.app = app
-
-    async def dispatch(self, request: AsgiHttpRequest) -> BoltResponse:
-        return self.app.dispatch(
-            BoltRequest(body=await request.get_raw_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    async def handle_installation(self, request: AsgiHttpRequest) -> BoltResponse:
-        return self.app.oauth_flow.handle_installation(  # type: ignore[union-attr]
-            BoltRequest(body=await request.get_raw_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    async def handle_callback(self, request: AsgiHttpRequest) -> BoltResponse:
-        return self.app.oauth_flow.handle_callback(  # type: ignore[union-attr]
-            BoltRequest(body=await request.get_raw_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-

Setup Bolt as an ASGI web framework, this will make your application compatible with ASGI web servers. -This can be used for production deployment.

-

With the default settings, http://localhost:3000/slack/events -Run Bolt with uvicron

-
# Python
-app = App()
-api = SlackRequestHandler(app)
-
-# bash
-export SLACK_SIGNING_SECRET=***
-export SLACK_BOT_TOKEN=xoxb-***
-uvicorn app:api --port 3000 --log-level debug
-
-

Args

-
-
app
-
Your bolt application
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
-

Ancestors

- -

Subclasses

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/asgi/http_request.html b/docs/reference/adapter/asgi/http_request.html deleted file mode 100644 index 062ac7ca2..000000000 --- a/docs/reference/adapter/asgi/http_request.html +++ /dev/null @@ -1,256 +0,0 @@ - - - - - - -slack_bolt.adapter.asgi.http_request API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.asgi.http_request

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsgiHttpRequest -(scope: Dict[str, str | bytes | Iterable[Tuple[bytes, bytes]]],
receive: Callable)
-
-
-
- -Expand source code - -
class AsgiHttpRequest:
-    __slots__ = ("receive", "query_string", "raw_headers")
-
-    def __init__(self, scope: scope_type, receive: Callable):
-        self.receive = receive
-        self.query_string = str(scope["query_string"], ENCODING)  # type: ignore[arg-type]
-        self.raw_headers: Iterable[Tuple[bytes, bytes]] = scope["headers"]  # type: ignore[assignment]
-
-    def get_headers(self) -> Dict[str, Union[str, Sequence[str]]]:
-        return {str(header[0], ENCODING): str(header[1], (ENCODING)) for header in self.raw_headers}
-
-    async def get_raw_body(self) -> str:
-        chunks = bytearray()
-        while True:
-            chunk: Dict[str, Union[str, bytes]] = await self.receive()
-
-            if chunk["type"] != "http.request":
-                raise Exception("Body chunks could not be received from asgi server")
-
-            chunks.extend(chunk.get("body", b""))  # type: ignore[arg-type]
-            if not chunk.get("more_body", False):
-                break
-        return bytes(chunks).decode(ENCODING)
-
-
-

Instance variables

-
-
var query_string
-
-
- -Expand source code - -
class AsgiHttpRequest:
-    __slots__ = ("receive", "query_string", "raw_headers")
-
-    def __init__(self, scope: scope_type, receive: Callable):
-        self.receive = receive
-        self.query_string = str(scope["query_string"], ENCODING)  # type: ignore[arg-type]
-        self.raw_headers: Iterable[Tuple[bytes, bytes]] = scope["headers"]  # type: ignore[assignment]
-
-    def get_headers(self) -> Dict[str, Union[str, Sequence[str]]]:
-        return {str(header[0], ENCODING): str(header[1], (ENCODING)) for header in self.raw_headers}
-
-    async def get_raw_body(self) -> str:
-        chunks = bytearray()
-        while True:
-            chunk: Dict[str, Union[str, bytes]] = await self.receive()
-
-            if chunk["type"] != "http.request":
-                raise Exception("Body chunks could not be received from asgi server")
-
-            chunks.extend(chunk.get("body", b""))  # type: ignore[arg-type]
-            if not chunk.get("more_body", False):
-                break
-        return bytes(chunks).decode(ENCODING)
-
-
-
-
var raw_headers
-
-
- -Expand source code - -
class AsgiHttpRequest:
-    __slots__ = ("receive", "query_string", "raw_headers")
-
-    def __init__(self, scope: scope_type, receive: Callable):
-        self.receive = receive
-        self.query_string = str(scope["query_string"], ENCODING)  # type: ignore[arg-type]
-        self.raw_headers: Iterable[Tuple[bytes, bytes]] = scope["headers"]  # type: ignore[assignment]
-
-    def get_headers(self) -> Dict[str, Union[str, Sequence[str]]]:
-        return {str(header[0], ENCODING): str(header[1], (ENCODING)) for header in self.raw_headers}
-
-    async def get_raw_body(self) -> str:
-        chunks = bytearray()
-        while True:
-            chunk: Dict[str, Union[str, bytes]] = await self.receive()
-
-            if chunk["type"] != "http.request":
-                raise Exception("Body chunks could not be received from asgi server")
-
-            chunks.extend(chunk.get("body", b""))  # type: ignore[arg-type]
-            if not chunk.get("more_body", False):
-                break
-        return bytes(chunks).decode(ENCODING)
-
-
-
-
var receive
-
-
- -Expand source code - -
class AsgiHttpRequest:
-    __slots__ = ("receive", "query_string", "raw_headers")
-
-    def __init__(self, scope: scope_type, receive: Callable):
-        self.receive = receive
-        self.query_string = str(scope["query_string"], ENCODING)  # type: ignore[arg-type]
-        self.raw_headers: Iterable[Tuple[bytes, bytes]] = scope["headers"]  # type: ignore[assignment]
-
-    def get_headers(self) -> Dict[str, Union[str, Sequence[str]]]:
-        return {str(header[0], ENCODING): str(header[1], (ENCODING)) for header in self.raw_headers}
-
-    async def get_raw_body(self) -> str:
-        chunks = bytearray()
-        while True:
-            chunk: Dict[str, Union[str, bytes]] = await self.receive()
-
-            if chunk["type"] != "http.request":
-                raise Exception("Body chunks could not be received from asgi server")
-
-            chunks.extend(chunk.get("body", b""))  # type: ignore[arg-type]
-            if not chunk.get("more_body", False):
-                break
-        return bytes(chunks).decode(ENCODING)
-
-
-
-
-

Methods

-
-
-def get_headers(self) ‑> Dict[str, str | Sequence[str]] -
-
-
- -Expand source code - -
def get_headers(self) -> Dict[str, Union[str, Sequence[str]]]:
-    return {str(header[0], ENCODING): str(header[1], (ENCODING)) for header in self.raw_headers}
-
-
-
-
-async def get_raw_body(self) ‑> str -
-
-
- -Expand source code - -
async def get_raw_body(self) -> str:
-    chunks = bytearray()
-    while True:
-        chunk: Dict[str, Union[str, bytes]] = await self.receive()
-
-        if chunk["type"] != "http.request":
-            raise Exception("Body chunks could not be received from asgi server")
-
-        chunks.extend(chunk.get("body", b""))  # type: ignore[arg-type]
-        if not chunk.get("more_body", False):
-            break
-    return bytes(chunks).decode(ENCODING)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/asgi/http_response.html b/docs/reference/adapter/asgi/http_response.html deleted file mode 100644 index 0c42d9a9f..000000000 --- a/docs/reference/adapter/asgi/http_response.html +++ /dev/null @@ -1,270 +0,0 @@ - - - - - - -slack_bolt.adapter.asgi.http_response API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.asgi.http_response

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsgiHttpResponse -(status: int, headers: Dict[str, Sequence[str]] = {}, body: str = '') -
-
-
- -Expand source code - -
class AsgiHttpResponse:
-    __slots__ = ("status", "raw_headers", "body")
-
-    def __init__(self, status: int, headers: Dict[str, Sequence[str]] = {}, body: str = ""):
-        self.status: int = status
-        self.body: bytes = bytes(body, ENCODING)
-        self.raw_headers: List[Tuple[bytes, bytes]] = []
-        for key, values in headers.items():
-            if key.lower() == "content-length":
-                continue
-            for v in values:
-                self.raw_headers.append((bytes(key, ENCODING), bytes(v, ENCODING)))
-        self.raw_headers.append((b"content-length", bytes(str(len(self.body)), ENCODING)))
-
-    def get_response_start(self) -> Dict[str, Union[str, int, Iterable[Tuple[bytes, bytes]]]]:
-        return {
-            "type": "http.response.start",
-            "status": self.status,
-            "headers": self.raw_headers,
-        }
-
-    def get_response_body(self) -> Dict[str, Union[str, bytes, bool]]:
-        return {
-            "type": "http.response.body",
-            "body": self.body,
-            "more_body": False,
-        }
-
-
-

Instance variables

-
-
var body
-
-
- -Expand source code - -
class AsgiHttpResponse:
-    __slots__ = ("status", "raw_headers", "body")
-
-    def __init__(self, status: int, headers: Dict[str, Sequence[str]] = {}, body: str = ""):
-        self.status: int = status
-        self.body: bytes = bytes(body, ENCODING)
-        self.raw_headers: List[Tuple[bytes, bytes]] = []
-        for key, values in headers.items():
-            if key.lower() == "content-length":
-                continue
-            for v in values:
-                self.raw_headers.append((bytes(key, ENCODING), bytes(v, ENCODING)))
-        self.raw_headers.append((b"content-length", bytes(str(len(self.body)), ENCODING)))
-
-    def get_response_start(self) -> Dict[str, Union[str, int, Iterable[Tuple[bytes, bytes]]]]:
-        return {
-            "type": "http.response.start",
-            "status": self.status,
-            "headers": self.raw_headers,
-        }
-
-    def get_response_body(self) -> Dict[str, Union[str, bytes, bool]]:
-        return {
-            "type": "http.response.body",
-            "body": self.body,
-            "more_body": False,
-        }
-
-
-
-
var raw_headers
-
-
- -Expand source code - -
class AsgiHttpResponse:
-    __slots__ = ("status", "raw_headers", "body")
-
-    def __init__(self, status: int, headers: Dict[str, Sequence[str]] = {}, body: str = ""):
-        self.status: int = status
-        self.body: bytes = bytes(body, ENCODING)
-        self.raw_headers: List[Tuple[bytes, bytes]] = []
-        for key, values in headers.items():
-            if key.lower() == "content-length":
-                continue
-            for v in values:
-                self.raw_headers.append((bytes(key, ENCODING), bytes(v, ENCODING)))
-        self.raw_headers.append((b"content-length", bytes(str(len(self.body)), ENCODING)))
-
-    def get_response_start(self) -> Dict[str, Union[str, int, Iterable[Tuple[bytes, bytes]]]]:
-        return {
-            "type": "http.response.start",
-            "status": self.status,
-            "headers": self.raw_headers,
-        }
-
-    def get_response_body(self) -> Dict[str, Union[str, bytes, bool]]:
-        return {
-            "type": "http.response.body",
-            "body": self.body,
-            "more_body": False,
-        }
-
-
-
-
var status
-
-
- -Expand source code - -
class AsgiHttpResponse:
-    __slots__ = ("status", "raw_headers", "body")
-
-    def __init__(self, status: int, headers: Dict[str, Sequence[str]] = {}, body: str = ""):
-        self.status: int = status
-        self.body: bytes = bytes(body, ENCODING)
-        self.raw_headers: List[Tuple[bytes, bytes]] = []
-        for key, values in headers.items():
-            if key.lower() == "content-length":
-                continue
-            for v in values:
-                self.raw_headers.append((bytes(key, ENCODING), bytes(v, ENCODING)))
-        self.raw_headers.append((b"content-length", bytes(str(len(self.body)), ENCODING)))
-
-    def get_response_start(self) -> Dict[str, Union[str, int, Iterable[Tuple[bytes, bytes]]]]:
-        return {
-            "type": "http.response.start",
-            "status": self.status,
-            "headers": self.raw_headers,
-        }
-
-    def get_response_body(self) -> Dict[str, Union[str, bytes, bool]]:
-        return {
-            "type": "http.response.body",
-            "body": self.body,
-            "more_body": False,
-        }
-
-
-
-
-

Methods

-
-
-def get_response_body(self) ‑> Dict[str, str | bytes | bool] -
-
-
- -Expand source code - -
def get_response_body(self) -> Dict[str, Union[str, bytes, bool]]:
-    return {
-        "type": "http.response.body",
-        "body": self.body,
-        "more_body": False,
-    }
-
-
-
-
-def get_response_start(self) ‑> Dict[str, str | int | Iterable[Tuple[bytes, bytes]]] -
-
-
- -Expand source code - -
def get_response_start(self) -> Dict[str, Union[str, int, Iterable[Tuple[bytes, bytes]]]]:
-    return {
-        "type": "http.response.start",
-        "status": self.status,
-        "headers": self.raw_headers,
-    }
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/asgi/index.html b/docs/reference/adapter/asgi/index.html deleted file mode 100644 index 0f2abec74..000000000 --- a/docs/reference/adapter/asgi/index.html +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - -slack_bolt.adapter.asgi API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.asgi

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.asgi.aiohttp
-
-
-
-
slack_bolt.adapter.asgi.async_handler
-
-
-
-
slack_bolt.adapter.asgi.base_handler
-
-
-
-
slack_bolt.adapter.asgi.builtin
-
-
-
-
slack_bolt.adapter.asgi.http_request
-
-
-
-
slack_bolt.adapter.asgi.http_response
-
-
-
-
slack_bolt.adapter.asgi.utils
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App,
path: str = '/slack/events')
-
-
-
- -Expand source code - -
class SlackRequestHandler(BaseSlackRequestHandler):
-    def __init__(self, app: App, path: str = "/slack/events"):
-        """Setup Bolt as an ASGI web framework, this will make your application compatible with ASGI web servers.
-        This can be used for production deployment.
-
-        With the default settings, `http://localhost:3000/slack/events`
-        Run Bolt with [uvicron](https://www.uvicorn.org/)
-
-            # Python
-            app = App()
-            api = SlackRequestHandler(app)
-
-            # bash
-            export SLACK_SIGNING_SECRET=***
-            export SLACK_BOT_TOKEN=xoxb-***
-            uvicorn app:api --port 3000 --log-level debug
-
-        Args:
-            app: Your bolt application
-            path: The path to handle request from Slack (Default: `/slack/events`)
-        """
-        self.path = path
-        self.app = app
-
-    async def dispatch(self, request: AsgiHttpRequest) -> BoltResponse:
-        return self.app.dispatch(
-            BoltRequest(body=await request.get_raw_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    async def handle_installation(self, request: AsgiHttpRequest) -> BoltResponse:
-        return self.app.oauth_flow.handle_installation(  # type: ignore[union-attr]
-            BoltRequest(body=await request.get_raw_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    async def handle_callback(self, request: AsgiHttpRequest) -> BoltResponse:
-        return self.app.oauth_flow.handle_callback(  # type: ignore[union-attr]
-            BoltRequest(body=await request.get_raw_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-

Setup Bolt as an ASGI web framework, this will make your application compatible with ASGI web servers. -This can be used for production deployment.

-

With the default settings, http://localhost:3000/slack/events -Run Bolt with uvicron

-
# Python
-app = App()
-api = SlackRequestHandler(app)
-
-# bash
-export SLACK_SIGNING_SECRET=***
-export SLACK_BOT_TOKEN=xoxb-***
-uvicorn app:api --port 3000 --log-level debug
-
-

Args

-
-
app
-
Your bolt application
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
-

Ancestors

- -

Subclasses

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/asgi/utils.html b/docs/reference/adapter/asgi/utils.html deleted file mode 100644 index 8eb2a24f1..000000000 --- a/docs/reference/adapter/asgi/utils.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - -slack_bolt.adapter.asgi.utils API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.asgi.utils

-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/aws_lambda/chalice_handler.html b/docs/reference/adapter/aws_lambda/chalice_handler.html deleted file mode 100644 index 28c75ea6a..000000000 --- a/docs/reference/adapter/aws_lambda/chalice_handler.html +++ /dev/null @@ -1,284 +0,0 @@ - - - - - - -slack_bolt.adapter.aws_lambda.chalice_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.aws_lambda.chalice_handler

-
-
-
-
-
-
-
-
-

Functions

-
-
-def not_found() ‑> chalice.app.Response -
-
-
- -Expand source code - -
def not_found() -> Response:
-    return Response(
-        status_code=404,
-        body="Not Found",
-        headers={},
-    )
-
-
-
-
-def to_bolt_request(request: chalice.app.Request, body: str) ‑> BoltRequest -
-
-
- -Expand source code - -
def to_bolt_request(request: Request, body: str) -> BoltRequest:
-    return BoltRequest(
-        body=body,
-        query=request.query_params,  # type: ignore[arg-type]
-        headers=request.headers,  # type: ignore[arg-type]
-    )
-
-
-
-
-def to_chalice_response(resp: BoltResponse) ‑> chalice.app.Response -
-
-
- -Expand source code - -
def to_chalice_response(resp: BoltResponse) -> Response:
-    return Response(
-        status_code=resp.status,
-        body=resp.body,
-        headers=resp.first_headers(),  # type: ignore[arg-type]
-    )
-
-
-
-
-
-
-

Classes

-
-
-class ChaliceSlackRequestHandler -(app: App,
chalice: chalice.app.Chalice,
lambda_client: botocore.client.BaseClient | None = None)
-
-
-
- -Expand source code - -
class ChaliceSlackRequestHandler:
-    def __init__(self, app: App, chalice: Chalice, lambda_client: Optional[BaseClient] = None):
-        self.app = app
-        self.chalice = chalice
-        self.logger = get_bolt_app_logger(app.name, ChaliceSlackRequestHandler, app.logger)
-
-        if getenv("AWS_CHALICE_CLI_MODE") == "true" and lambda_client is None:
-            try:
-                from slack_bolt.adapter.aws_lambda.local_lambda_client import (
-                    LocalLambdaClient,
-                )
-
-                lambda_client = LocalLambdaClient(self.chalice, None)  # type: ignore[arg-type]
-            except ImportError:
-                logging.info("Failed to load LocalLambdaClient for CLI mode.")
-                pass
-
-        self.app.listener_runner.lazy_listener_runner = ChaliceLazyListenerRunner(
-            logger=self.logger, lambda_client=lambda_client
-        )
-
-        if self.app.oauth_flow is not None:
-            self.app.oauth_flow.settings.redirect_uri_page_renderer.install_path = "?"
-
-    @classmethod
-    def clear_all_log_handlers(cls):
-        # https://stackoverflow.com/questions/37703609/using-python-logging-with-aws-lambda
-        root = logging.getLogger()
-        if root.handlers:
-            for handler in root.handlers:
-                root.removeHandler(handler)
-
-    def handle(self, request: Request):
-        body: str = request.raw_body.decode("utf-8") if request.raw_body else ""  # type: ignore[union-attr]
-        self.logger.debug(f"Incoming request: {request.to_dict()}, body: {body}")
-
-        method = request.method
-        if method is None:
-            return not_found()
-        if method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                bolt_req: BoltRequest = to_bolt_request(request, body)
-                query = bolt_req.query
-                is_callback = query is not None and (
-                    (_first_value(query, "code") is not None and _first_value(query, "state") is not None)
-                    or _first_value(query, "error") is not None
-                )
-                if is_callback:
-                    bolt_resp = oauth_flow.handle_callback(bolt_req)
-                    return to_chalice_response(bolt_resp)
-                else:
-                    bolt_resp = oauth_flow.handle_installation(bolt_req)
-                    return to_chalice_response(bolt_resp)
-        elif method == "POST":
-            bolt_req = to_bolt_request(request, body)
-            # https://docs.aws.amazon.com/lambda/latest/dg/python-context.html
-            aws_lambda_function_name = self.chalice.lambda_context.function_name
-            bolt_req.context["aws_lambda_function_name"] = aws_lambda_function_name
-            bolt_req.context["chalice_request"] = request.to_dict()
-            bolt_resp = self.app.dispatch(bolt_req)
-            aws_response = to_chalice_response(bolt_resp)
-            return aws_response
-        elif method == "NONE":
-            bolt_req = to_bolt_request(request, body)
-            bolt_resp = self.app.dispatch(bolt_req)
-            aws_response = to_chalice_response(bolt_resp)
-            return aws_response
-
-        return not_found()
-
-
-

Static methods

-
-
-def clear_all_log_handlers() -
-
-
-
-
-

Methods

-
-
-def handle(self, request: chalice.app.Request) -
-
-
- -Expand source code - -
def handle(self, request: Request):
-    body: str = request.raw_body.decode("utf-8") if request.raw_body else ""  # type: ignore[union-attr]
-    self.logger.debug(f"Incoming request: {request.to_dict()}, body: {body}")
-
-    method = request.method
-    if method is None:
-        return not_found()
-    if method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            bolt_req: BoltRequest = to_bolt_request(request, body)
-            query = bolt_req.query
-            is_callback = query is not None and (
-                (_first_value(query, "code") is not None and _first_value(query, "state") is not None)
-                or _first_value(query, "error") is not None
-            )
-            if is_callback:
-                bolt_resp = oauth_flow.handle_callback(bolt_req)
-                return to_chalice_response(bolt_resp)
-            else:
-                bolt_resp = oauth_flow.handle_installation(bolt_req)
-                return to_chalice_response(bolt_resp)
-    elif method == "POST":
-        bolt_req = to_bolt_request(request, body)
-        # https://docs.aws.amazon.com/lambda/latest/dg/python-context.html
-        aws_lambda_function_name = self.chalice.lambda_context.function_name
-        bolt_req.context["aws_lambda_function_name"] = aws_lambda_function_name
-        bolt_req.context["chalice_request"] = request.to_dict()
-        bolt_resp = self.app.dispatch(bolt_req)
-        aws_response = to_chalice_response(bolt_resp)
-        return aws_response
-    elif method == "NONE":
-        bolt_req = to_bolt_request(request, body)
-        bolt_resp = self.app.dispatch(bolt_req)
-        aws_response = to_chalice_response(bolt_resp)
-        return aws_response
-
-    return not_found()
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/aws_lambda/chalice_lazy_listener_runner.html b/docs/reference/adapter/aws_lambda/chalice_lazy_listener_runner.html deleted file mode 100644 index f27e09c93..000000000 --- a/docs/reference/adapter/aws_lambda/chalice_lazy_listener_runner.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - -slack_bolt.adapter.aws_lambda.chalice_lazy_listener_runner API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.aws_lambda.chalice_lazy_listener_runner

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class ChaliceLazyListenerRunner -(logger: logging.Logger,
lambda_client: botocore.client.BaseClient | None = None)
-
-
-
- -Expand source code - -
class ChaliceLazyListenerRunner(LazyListenerRunner):
-    def __init__(self, logger: Logger, lambda_client: Optional[BaseClient] = None):
-        self.lambda_client = lambda_client
-        self.logger = logger
-
-    def start(self, function: Callable[..., None], request: BoltRequest) -> None:
-        if self.lambda_client is None:
-            self.lambda_client = boto3.client("lambda")
-
-        chalice_request: dict = request.context["chalice_request"]
-        request.headers["x-slack-bolt-lazy-only"] = ["1"]
-        request.headers["x-slack-bolt-lazy-function-name"] = [request.lazy_function_name]  # type: ignore[list-item]
-        payload = {
-            "method": "NONE",
-            "headers": {k: v[0] for k, v in request.headers.items()},
-            "multiValueQueryStringParameters": request.query,
-            "queryStringParameters": {k: v[0] for k, v in request.query.items()},
-            "pathParameters": {},
-            "stageVariables": {},
-            "requestContext": chalice_request["context"],
-            "body": request.raw_body,
-            "isBase64Encoded": False,
-        }
-        invocation = self.lambda_client.invoke(
-            FunctionName=request.context["aws_lambda_function_name"],
-            InvocationType="Event",
-            Payload=json.dumps(payload),
-        )
-
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/aws_lambda/handler.html b/docs/reference/adapter/aws_lambda/handler.html deleted file mode 100644 index 08e4ac9b7..000000000 --- a/docs/reference/adapter/aws_lambda/handler.html +++ /dev/null @@ -1,287 +0,0 @@ - - - - - - -slack_bolt.adapter.aws_lambda.handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.aws_lambda.handler

-
-
-
-
-
-
-
-
-

Functions

-
-
-def not_found() ‑> Dict[str, Any] -
-
-
- -Expand source code - -
def not_found() -> Dict[str, Any]:
-    return {
-        "statusCode": 404,
-        "body": "Not Found",
-        "headers": {},
-    }
-
-
-
-
-def to_aws_response(resp: BoltResponse) ‑> Dict[str, Any] -
-
-
- -Expand source code - -
def to_aws_response(resp: BoltResponse) -> Dict[str, Any]:
-    return {
-        "statusCode": resp.status,
-        "body": resp.body,
-        "headers": resp.first_headers(),
-    }
-
-
-
-
-def to_bolt_request(event) ‑> BoltRequest -
-
-
- -Expand source code - -
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", [])
-    if cookies is None or len(cookies) == 0:
-        # In the case of format v1
-        multiValueHeaders = event.get("multiValueHeaders", {})
-        cookies = multiValueHeaders.get("cookie", [])
-        if len(cookies) == 0:
-            # Try using uppercase
-            cookies = multiValueHeaders.get("Cookie", [])
-    headers = event.get("headers", {})
-    headers["cookie"] = cookies
-    return BoltRequest(
-        body=body,
-        query=event.get("queryStringParameters", {}),
-        headers=headers,
-    )
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-        self.logger = get_bolt_app_logger(app.name, SlackRequestHandler, app.logger)
-        self.app.listener_runner.lazy_listener_runner = LambdaLazyListenerRunner(self.logger)
-        if self.app.oauth_flow is not None:
-            self.app.oauth_flow.settings.redirect_uri_page_renderer.install_path = "?"
-
-    @classmethod
-    def clear_all_log_handlers(cls):
-        # https://stackoverflow.com/questions/37703609/using-python-logging-with-aws-lambda
-        root = logging.getLogger()
-        if root.handlers:
-            for handler in root.handlers:
-                root.removeHandler(handler)
-
-    def handle(self, event, context):
-        self.logger.debug(f"Incoming event: {event}, context: {context}")
-
-        method = event.get("requestContext", {}).get("http", {}).get("method")
-        if method is None:
-            method = event.get("requestContext", {}).get("httpMethod")
-
-        if method is None:
-            return not_found()
-        if method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                bolt_req: BoltRequest = to_bolt_request(event)
-                query = bolt_req.query
-                is_callback = query is not None and (
-                    (_first_value(query, "code") is not None and _first_value(query, "state") is not None)
-                    or _first_value(query, "error") is not None
-                )
-                if is_callback:
-                    bolt_resp = oauth_flow.handle_callback(bolt_req)
-                    return to_aws_response(bolt_resp)
-                else:
-                    bolt_resp = oauth_flow.handle_installation(bolt_req)
-                    return to_aws_response(bolt_resp)
-        elif method == "POST":
-            bolt_req = to_bolt_request(event)
-            # https://docs.aws.amazon.com/lambda/latest/dg/python-context.html
-            aws_lambda_function_name = context.function_name
-            bolt_req.context["aws_lambda_function_name"] = aws_lambda_function_name
-            bolt_req.context["aws_lambda_invoked_function_arn"] = context.invoked_function_arn
-            bolt_req.context["lambda_request"] = event
-            bolt_resp = self.app.dispatch(bolt_req)
-            aws_response = to_aws_response(bolt_resp)
-            return aws_response
-        elif method == "NONE":
-            bolt_req = to_bolt_request(event)
-            bolt_resp = self.app.dispatch(bolt_req)
-            aws_response = to_aws_response(bolt_resp)
-            return aws_response
-
-        return not_found()
-
-
-

Static methods

-
-
-def clear_all_log_handlers() -
-
-
-
-
-

Methods

-
-
-def handle(self, event, context) -
-
-
- -Expand source code - -
def handle(self, event, context):
-    self.logger.debug(f"Incoming event: {event}, context: {context}")
-
-    method = event.get("requestContext", {}).get("http", {}).get("method")
-    if method is None:
-        method = event.get("requestContext", {}).get("httpMethod")
-
-    if method is None:
-        return not_found()
-    if method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            bolt_req: BoltRequest = to_bolt_request(event)
-            query = bolt_req.query
-            is_callback = query is not None and (
-                (_first_value(query, "code") is not None and _first_value(query, "state") is not None)
-                or _first_value(query, "error") is not None
-            )
-            if is_callback:
-                bolt_resp = oauth_flow.handle_callback(bolt_req)
-                return to_aws_response(bolt_resp)
-            else:
-                bolt_resp = oauth_flow.handle_installation(bolt_req)
-                return to_aws_response(bolt_resp)
-    elif method == "POST":
-        bolt_req = to_bolt_request(event)
-        # https://docs.aws.amazon.com/lambda/latest/dg/python-context.html
-        aws_lambda_function_name = context.function_name
-        bolt_req.context["aws_lambda_function_name"] = aws_lambda_function_name
-        bolt_req.context["aws_lambda_invoked_function_arn"] = context.invoked_function_arn
-        bolt_req.context["lambda_request"] = event
-        bolt_resp = self.app.dispatch(bolt_req)
-        aws_response = to_aws_response(bolt_resp)
-        return aws_response
-    elif method == "NONE":
-        bolt_req = to_bolt_request(event)
-        bolt_resp = self.app.dispatch(bolt_req)
-        aws_response = to_aws_response(bolt_resp)
-        return aws_response
-
-    return not_found()
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/aws_lambda/index.html b/docs/reference/adapter/aws_lambda/index.html deleted file mode 100644 index 0aae2c31a..000000000 --- a/docs/reference/adapter/aws_lambda/index.html +++ /dev/null @@ -1,255 +0,0 @@ - - - - - - -slack_bolt.adapter.aws_lambda API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.aws_lambda

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.aws_lambda.chalice_handler
-
-
-
-
slack_bolt.adapter.aws_lambda.chalice_lazy_listener_runner
-
-
-
-
slack_bolt.adapter.aws_lambda.handler
-
-
-
-
slack_bolt.adapter.aws_lambda.internals
-
-
-
-
slack_bolt.adapter.aws_lambda.lambda_s3_oauth_flow
-
-
-
-
slack_bolt.adapter.aws_lambda.lazy_listener_runner
-
-
-
-
slack_bolt.adapter.aws_lambda.local_lambda_client
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-        self.logger = get_bolt_app_logger(app.name, SlackRequestHandler, app.logger)
-        self.app.listener_runner.lazy_listener_runner = LambdaLazyListenerRunner(self.logger)
-        if self.app.oauth_flow is not None:
-            self.app.oauth_flow.settings.redirect_uri_page_renderer.install_path = "?"
-
-    @classmethod
-    def clear_all_log_handlers(cls):
-        # https://stackoverflow.com/questions/37703609/using-python-logging-with-aws-lambda
-        root = logging.getLogger()
-        if root.handlers:
-            for handler in root.handlers:
-                root.removeHandler(handler)
-
-    def handle(self, event, context):
-        self.logger.debug(f"Incoming event: {event}, context: {context}")
-
-        method = event.get("requestContext", {}).get("http", {}).get("method")
-        if method is None:
-            method = event.get("requestContext", {}).get("httpMethod")
-
-        if method is None:
-            return not_found()
-        if method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                bolt_req: BoltRequest = to_bolt_request(event)
-                query = bolt_req.query
-                is_callback = query is not None and (
-                    (_first_value(query, "code") is not None and _first_value(query, "state") is not None)
-                    or _first_value(query, "error") is not None
-                )
-                if is_callback:
-                    bolt_resp = oauth_flow.handle_callback(bolt_req)
-                    return to_aws_response(bolt_resp)
-                else:
-                    bolt_resp = oauth_flow.handle_installation(bolt_req)
-                    return to_aws_response(bolt_resp)
-        elif method == "POST":
-            bolt_req = to_bolt_request(event)
-            # https://docs.aws.amazon.com/lambda/latest/dg/python-context.html
-            aws_lambda_function_name = context.function_name
-            bolt_req.context["aws_lambda_function_name"] = aws_lambda_function_name
-            bolt_req.context["aws_lambda_invoked_function_arn"] = context.invoked_function_arn
-            bolt_req.context["lambda_request"] = event
-            bolt_resp = self.app.dispatch(bolt_req)
-            aws_response = to_aws_response(bolt_resp)
-            return aws_response
-        elif method == "NONE":
-            bolt_req = to_bolt_request(event)
-            bolt_resp = self.app.dispatch(bolt_req)
-            aws_response = to_aws_response(bolt_resp)
-            return aws_response
-
-        return not_found()
-
-
-

Static methods

-
-
-def clear_all_log_handlers() -
-
-
-
-
-

Methods

-
-
-def handle(self, event, context) -
-
-
- -Expand source code - -
def handle(self, event, context):
-    self.logger.debug(f"Incoming event: {event}, context: {context}")
-
-    method = event.get("requestContext", {}).get("http", {}).get("method")
-    if method is None:
-        method = event.get("requestContext", {}).get("httpMethod")
-
-    if method is None:
-        return not_found()
-    if method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            bolt_req: BoltRequest = to_bolt_request(event)
-            query = bolt_req.query
-            is_callback = query is not None and (
-                (_first_value(query, "code") is not None and _first_value(query, "state") is not None)
-                or _first_value(query, "error") is not None
-            )
-            if is_callback:
-                bolt_resp = oauth_flow.handle_callback(bolt_req)
-                return to_aws_response(bolt_resp)
-            else:
-                bolt_resp = oauth_flow.handle_installation(bolt_req)
-                return to_aws_response(bolt_resp)
-    elif method == "POST":
-        bolt_req = to_bolt_request(event)
-        # https://docs.aws.amazon.com/lambda/latest/dg/python-context.html
-        aws_lambda_function_name = context.function_name
-        bolt_req.context["aws_lambda_function_name"] = aws_lambda_function_name
-        bolt_req.context["aws_lambda_invoked_function_arn"] = context.invoked_function_arn
-        bolt_req.context["lambda_request"] = event
-        bolt_resp = self.app.dispatch(bolt_req)
-        aws_response = to_aws_response(bolt_resp)
-        return aws_response
-    elif method == "NONE":
-        bolt_req = to_bolt_request(event)
-        bolt_resp = self.app.dispatch(bolt_req)
-        aws_response = to_aws_response(bolt_resp)
-        return aws_response
-
-    return not_found()
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/aws_lambda/internals.html b/docs/reference/adapter/aws_lambda/internals.html deleted file mode 100644 index bbbe281b0..000000000 --- a/docs/reference/adapter/aws_lambda/internals.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - -slack_bolt.adapter.aws_lambda.internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.aws_lambda.internals

-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/aws_lambda/lambda_s3_oauth_flow.html b/docs/reference/adapter/aws_lambda/lambda_s3_oauth_flow.html deleted file mode 100644 index 11845c902..000000000 --- a/docs/reference/adapter/aws_lambda/lambda_s3_oauth_flow.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - -slack_bolt.adapter.aws_lambda.lambda_s3_oauth_flow API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.aws_lambda.lambda_s3_oauth_flow

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class LambdaS3OAuthFlow -(*,
client: slack_sdk.web.client.WebClient | None = None,
logger: logging.Logger | None = None,
settings: OAuthSettings | None = None,
oauth_state_bucket_name: str | None = None,
installation_bucket_name: str | None = None)
-
-
-
- -Expand source code - -
class LambdaS3OAuthFlow(OAuthFlow):
-    def __init__(
-        self,
-        *,
-        client: Optional[WebClient] = None,
-        logger: Optional[Logger] = None,
-        settings: Optional[OAuthSettings] = None,
-        oauth_state_bucket_name: Optional[str] = None,  # required
-        installation_bucket_name: Optional[str] = None,  # required
-    ):
-        logger = logger or logging.getLogger(__name__)
-        settings = settings or OAuthSettings(
-            client_id=os.environ["SLACK_CLIENT_ID"],
-            client_secret=os.environ["SLACK_CLIENT_SECRET"],
-        )
-        oauth_state_bucket_name = oauth_state_bucket_name or os.environ["SLACK_STATE_S3_BUCKET_NAME"]
-        installation_bucket_name = installation_bucket_name or os.environ["SLACK_INSTALLATION_S3_BUCKET_NAME"]
-        self.s3_client = boto3.client("s3")
-        if settings.state_store is None or not isinstance(settings.state_store, AmazonS3OAuthStateStore):
-            settings.state_store = AmazonS3OAuthStateStore(
-                logger=logger,
-                s3_client=self.s3_client,
-                bucket_name=oauth_state_bucket_name,
-                expiration_seconds=settings.state_expiration_seconds,
-            )
-
-        if settings.installation_store is None or not isinstance(settings.installation_store, AmazonS3InstallationStore):
-            settings.installation_store = AmazonS3InstallationStore(
-                logger=logger,
-                s3_client=self.s3_client,
-                bucket_name=installation_bucket_name,
-                client_id=settings.client_id,
-            )
-
-        # Set up authorize function to surely use this installation_store.
-        # When a developer use a settings initialized outside this constructor,
-        # the settings may already have pre-defined authorize.
-        # In this case, the /slack/events endpoint doesn't work along with the OAuth flow.
-        settings.authorize = InstallationStoreAuthorize(
-            logger=logger,
-            client_id=settings.client_id,
-            client_secret=settings.client_secret,
-            installation_store=settings.installation_store,
-            bot_only=settings.installation_store_bot_only,
-            user_token_resolution=(settings.user_token_resolution if settings is not None else "authed_user"),
-        )
-
-        OAuthFlow.__init__(self, client=client, logger=logger, settings=settings)
-
-    @property
-    def client(self) -> WebClient:
-        if self._client is None:
-            self._client = create_web_client(logger=self.logger)
-        return self._client
-
-    @property
-    def logger(self) -> Logger:
-        if self._logger is None:
-            self._logger = logging.getLogger(__name__)
-        return self._logger
-
-

The module to run the Slack app installation flow (OAuth flow).

-

Args

-
-
client
-
The slack_sdk.web.WebClient instance.
-
logger
-
The logger.
-
settings
-
OAuth settings to configure this module.
-
-

Ancestors

- -

Instance variables

-
-
prop client : slack_sdk.web.client.WebClient
-
-
- -Expand source code - -
@property
-def client(self) -> WebClient:
-    if self._client is None:
-        self._client = create_web_client(logger=self.logger)
-    return self._client
-
-
-
-
prop logger : logging.Logger
-
-
- -Expand source code - -
@property
-def logger(self) -> Logger:
-    if self._logger is None:
-        self._logger = logging.getLogger(__name__)
-    return self._logger
-
-
-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/aws_lambda/lazy_listener_runner.html b/docs/reference/adapter/aws_lambda/lazy_listener_runner.html deleted file mode 100644 index df53f5f22..000000000 --- a/docs/reference/adapter/aws_lambda/lazy_listener_runner.html +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - -slack_bolt.adapter.aws_lambda.lazy_listener_runner API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.aws_lambda.lazy_listener_runner

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class LambdaLazyListenerRunner -(logger: logging.Logger, lambda_client: Any | None = None) -
-
-
- -Expand source code - -
class LambdaLazyListenerRunner(LazyListenerRunner):
-    def __init__(self, logger: Logger, lambda_client: Optional[Any] = None):
-        self.lambda_client = lambda_client
-        self.logger = logger
-
-    def start(self, function: Callable[..., None], request: BoltRequest) -> None:
-        if self.lambda_client is None:
-            self.lambda_client = boto3.client("lambda")
-
-        event: dict = request.context["lambda_request"]
-        headers = event["headers"]
-        headers["x-slack-bolt-lazy-only"] = "1"  # not an array
-        headers["x-slack-bolt-lazy-function-name"] = request.lazy_function_name  # not an array
-        event["method"] = "NONE"
-        invocation = self.lambda_client.invoke(
-            FunctionName=request.context["aws_lambda_invoked_function_arn"],
-            InvocationType="Event",
-            Payload=json.dumps(event),
-        )
-        self.logger.info(invocation)
-
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/aws_lambda/local_lambda_client.html b/docs/reference/adapter/aws_lambda/local_lambda_client.html deleted file mode 100644 index 45ee0510b..000000000 --- a/docs/reference/adapter/aws_lambda/local_lambda_client.html +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - -slack_bolt.adapter.aws_lambda.local_lambda_client API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.aws_lambda.local_lambda_client

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class LocalLambdaClient -(app: chalice.app.Chalice, config: chalice.config.Config) -
-
-
- -Expand source code - -
class LocalLambdaClient(BaseClient):
-    """Lambda client implementing `invoke` for use when running with Chalice CLI."""
-
-    def __init__(self, app: Chalice, config: Config) -> None:
-        self._app = app
-        self._config = config if config else Config()
-
-    def invoke(
-        self,
-        FunctionName: str,
-        InvocationType: str = "Event",
-        Payload: str = "{}",
-    ) -> InvokeResponse:
-        scoped = self._config.scope(self._config.chalice_stage, FunctionName)
-        lambda_context = LambdaContext(FunctionName, memory_size=scoped.lambda_memory_size)
-
-        with self._patched_env_vars(scoped.environment_variables):
-            response = self._app(json.loads(Payload), lambda_context)
-        return InvokeResponse(payload=response)
-
-

Lambda client implementing invoke for use when running with Chalice CLI.

-

Ancestors

-
    -
  • chalice.test.BaseClient
  • -
-

Methods

-
-
-def invoke(self, FunctionName: str, InvocationType: str = 'Event', Payload: str = '{}') ‑> chalice.test.InvokeResponse -
-
-
- -Expand source code - -
def invoke(
-    self,
-    FunctionName: str,
-    InvocationType: str = "Event",
-    Payload: str = "{}",
-) -> InvokeResponse:
-    scoped = self._config.scope(self._config.chalice_stage, FunctionName)
-    lambda_context = LambdaContext(FunctionName, memory_size=scoped.lambda_memory_size)
-
-    with self._patched_env_vars(scoped.environment_variables):
-        response = self._app(json.loads(Payload), lambda_context)
-    return InvokeResponse(payload=response)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/bottle/handler.html b/docs/reference/adapter/bottle/handler.html deleted file mode 100644 index fe6f8ae1a..000000000 --- a/docs/reference/adapter/bottle/handler.html +++ /dev/null @@ -1,192 +0,0 @@ - - - - - - -slack_bolt.adapter.bottle.handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.bottle.handler

-
-
-
-
-
-
-
-
-

Functions

-
-
-def set_response(bolt_resp: BoltResponse,
resp: bottle.BaseResponse) ‑> None
-
-
-
- -Expand source code - -
def set_response(bolt_resp: BoltResponse, resp: Response) -> None:
-    resp.status = bolt_resp.status
-    for k, values in bolt_resp.headers.items():
-        for v in values:
-            resp.add_header(k, v)
-
-
-
-
-def to_bolt_request(req: bottle.BaseRequest) ‑> BoltRequest -
-
-
- -Expand source code - -
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,
-    )
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-
-    def handle(self, req: Request, resp: Response) -> str:
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                if req.path == oauth_flow.install_path:
-                    bolt_resp = oauth_flow.handle_installation(to_bolt_request(req))
-                    set_response(bolt_resp, resp)
-                    return bolt_resp.body or ""
-                elif req.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = oauth_flow.handle_callback(to_bolt_request(req))
-                    set_response(bolt_resp, resp)
-                    return bolt_resp.body or ""
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(to_bolt_request(req))
-            set_response(bolt_resp, resp)
-            return bolt_resp.body or ""
-
-        resp.status = 404
-        return "Not Found"
-
-
-

Methods

-
-
-def handle(self, req: bottle.BaseRequest, resp: bottle.BaseResponse) ‑> str -
-
-
- -Expand source code - -
def handle(self, req: Request, resp: Response) -> str:
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if req.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(to_bolt_request(req))
-                set_response(bolt_resp, resp)
-                return bolt_resp.body or ""
-            elif req.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(to_bolt_request(req))
-                set_response(bolt_resp, resp)
-                return bolt_resp.body or ""
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(to_bolt_request(req))
-        set_response(bolt_resp, resp)
-        return bolt_resp.body or ""
-
-    resp.status = 404
-    return "Not Found"
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/bottle/index.html b/docs/reference/adapter/bottle/index.html deleted file mode 100644 index f240d52bc..000000000 --- a/docs/reference/adapter/bottle/index.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - -slack_bolt.adapter.bottle API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.bottle

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.bottle.handler
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-
-    def handle(self, req: Request, resp: Response) -> str:
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                if req.path == oauth_flow.install_path:
-                    bolt_resp = oauth_flow.handle_installation(to_bolt_request(req))
-                    set_response(bolt_resp, resp)
-                    return bolt_resp.body or ""
-                elif req.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = oauth_flow.handle_callback(to_bolt_request(req))
-                    set_response(bolt_resp, resp)
-                    return bolt_resp.body or ""
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(to_bolt_request(req))
-            set_response(bolt_resp, resp)
-            return bolt_resp.body or ""
-
-        resp.status = 404
-        return "Not Found"
-
-
-

Methods

-
-
-def handle(self, req: bottle.BaseRequest, resp: bottle.BaseResponse) ‑> str -
-
-
- -Expand source code - -
def handle(self, req: Request, resp: Response) -> str:
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if req.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(to_bolt_request(req))
-                set_response(bolt_resp, resp)
-                return bolt_resp.body or ""
-            elif req.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(to_bolt_request(req))
-                set_response(bolt_resp, resp)
-                return bolt_resp.body or ""
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(to_bolt_request(req))
-        set_response(bolt_resp, resp)
-        return bolt_resp.body or ""
-
-    resp.status = 404
-    return "Not Found"
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/cherrypy/handler.html b/docs/reference/adapter/cherrypy/handler.html deleted file mode 100644 index d41f00148..000000000 --- a/docs/reference/adapter/cherrypy/handler.html +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - -slack_bolt.adapter.cherrypy.handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.cherrypy.handler

-
-
-
-
-
-
-
-
-

Functions

-
-
-def build_bolt_request() ‑> BoltRequest -
-
-
- -Expand source code - -
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 set_response_status_and_headers(bolt_resp: BoltResponse) ‑> None -
-
-
- -Expand source code - -
def set_response_status_and_headers(bolt_resp: BoltResponse) -> None:
-    cherrypy.response.status = bolt_resp.status
-    for k, v in bolt_resp.first_headers_without_set_cookie().items():
-        cherrypy.response.headers[k] = v
-    for cookie in bolt_resp.cookies():
-        for name, c in cookie.items():
-            str_max_age: Optional[str] = c.get("max-age")
-            max_age: Optional[int] = int(str_max_age) if str_max_age else None
-            cherrypy_cookie = cherrypy.response.cookie
-            cherrypy_cookie[name] = c.value
-            cherrypy_cookie[name]["expires"] = c.get("expires")
-            cherrypy_cookie[name]["max-age"] = max_age
-            cherrypy_cookie[name]["domain"] = c.get("domain")
-            cherrypy_cookie[name]["path"] = c.get("path")
-            cherrypy_cookie[name]["secure"] = True
-            cherrypy_cookie[name]["httponly"] = True
-
-
-
-
-def slack_in() -
-
-
- -Expand source code - -
@cherrypy.tools.register("on_start_resource")
-def slack_in():
-    request = cherrypy.serving.request
-
-    def slack_processor(entity):
-        try:
-            if request.process_request_body:
-                body = entity.fp.read()
-                body = body.decode("utf-8") if isinstance(body, bytes) else ""
-                request.raw_body = body
-        except ValueError:
-            raise cherrypy.HTTPError(400, "Invalid request body")
-
-    request.body.processors.clear()
-    request.body.processors["application/json"] = slack_processor
-    request.body.processors["application/x-www-form-urlencoded"] = slack_processor
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-
-    def handle(self) -> bytes:
-        req = cherrypy.request
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                request_path = req.wsgi_environ["REQUEST_URI"].split("?")[0]
-                if request_path == oauth_flow.install_path:
-                    bolt_resp = oauth_flow.handle_installation(build_bolt_request())
-                    set_response_status_and_headers(bolt_resp)
-                    return (bolt_resp.body or "").encode("utf-8")
-                elif request_path == oauth_flow.redirect_uri_path:
-                    bolt_resp = oauth_flow.handle_callback(build_bolt_request())
-                    set_response_status_and_headers(bolt_resp)
-                    return (bolt_resp.body or "").encode("utf-8")
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(build_bolt_request())
-            set_response_status_and_headers(bolt_resp)
-            return (bolt_resp.body or "").encode("utf-8")
-
-        cherrypy.response.status = 404
-        return "Not Found".encode("utf-8")
-
-
-

Methods

-
-
-def handle(self) ‑> bytes -
-
-
- -Expand source code - -
def handle(self) -> bytes:
-    req = cherrypy.request
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            request_path = req.wsgi_environ["REQUEST_URI"].split("?")[0]
-            if request_path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(build_bolt_request())
-                set_response_status_and_headers(bolt_resp)
-                return (bolt_resp.body or "").encode("utf-8")
-            elif request_path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(build_bolt_request())
-                set_response_status_and_headers(bolt_resp)
-                return (bolt_resp.body or "").encode("utf-8")
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(build_bolt_request())
-        set_response_status_and_headers(bolt_resp)
-        return (bolt_resp.body or "").encode("utf-8")
-
-    cherrypy.response.status = 404
-    return "Not Found".encode("utf-8")
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/cherrypy/index.html b/docs/reference/adapter/cherrypy/index.html deleted file mode 100644 index 5a322fd7a..000000000 --- a/docs/reference/adapter/cherrypy/index.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - -slack_bolt.adapter.cherrypy API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.cherrypy

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.cherrypy.handler
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-
-    def handle(self) -> bytes:
-        req = cherrypy.request
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                request_path = req.wsgi_environ["REQUEST_URI"].split("?")[0]
-                if request_path == oauth_flow.install_path:
-                    bolt_resp = oauth_flow.handle_installation(build_bolt_request())
-                    set_response_status_and_headers(bolt_resp)
-                    return (bolt_resp.body or "").encode("utf-8")
-                elif request_path == oauth_flow.redirect_uri_path:
-                    bolt_resp = oauth_flow.handle_callback(build_bolt_request())
-                    set_response_status_and_headers(bolt_resp)
-                    return (bolt_resp.body or "").encode("utf-8")
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(build_bolt_request())
-            set_response_status_and_headers(bolt_resp)
-            return (bolt_resp.body or "").encode("utf-8")
-
-        cherrypy.response.status = 404
-        return "Not Found".encode("utf-8")
-
-
-

Methods

-
-
-def handle(self) ‑> bytes -
-
-
- -Expand source code - -
def handle(self) -> bytes:
-    req = cherrypy.request
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            request_path = req.wsgi_environ["REQUEST_URI"].split("?")[0]
-            if request_path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(build_bolt_request())
-                set_response_status_and_headers(bolt_resp)
-                return (bolt_resp.body or "").encode("utf-8")
-            elif request_path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(build_bolt_request())
-                set_response_status_and_headers(bolt_resp)
-                return (bolt_resp.body or "").encode("utf-8")
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(build_bolt_request())
-        set_response_status_and_headers(bolt_resp)
-        return (bolt_resp.body or "").encode("utf-8")
-
-    cherrypy.response.status = 404
-    return "Not Found".encode("utf-8")
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/django/handler.html b/docs/reference/adapter/django/handler.html deleted file mode 100644 index 4fe9e359a..000000000 --- a/docs/reference/adapter/django/handler.html +++ /dev/null @@ -1,388 +0,0 @@ - - - - - - -slack_bolt.adapter.django.handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.django.handler

-
-
-
-
-
-
-
-
-

Functions

-
-
-def release_thread_local_connections(logger: logging.Logger, execution_timing: str) -
-
-
- -Expand source code - -
def release_thread_local_connections(logger: Logger, execution_timing: str):
-    close_old_connections()
-    if logger.level <= logging.DEBUG:
-        current: Thread = current_thread()
-        logger.debug(
-            "Released thread-bound old DB connections "
-            f"(thread name: {current.name}, execution timing: {execution_timing})"
-        )
-
-
-
-
-def to_bolt_request(req: django.http.request.HttpRequest) ‑> BoltRequest -
-
-
- -Expand source code - -
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 to_django_response(bolt_resp: BoltResponse) ‑> django.http.response.HttpResponse -
-
-
- -Expand source code - -
def to_django_response(bolt_resp: BoltResponse) -> HttpResponse:
-    resp: HttpResponse = HttpResponse(
-        status=bolt_resp.status,
-        content=bolt_resp.body.encode("utf-8"),
-    )
-    for k, v in bolt_resp.first_headers_without_set_cookie().items():
-        resp[k] = v
-
-    for cookie in bolt_resp.cookies():
-        for name, c in cookie.items():
-            str_max_age: Optional[str] = c.get("max-age")
-            max_age: Optional[int] = int(str_max_age) if str_max_age else None
-            resp.set_cookie(
-                key=name,
-                value=c.value,
-                expires=c.get("expires"),
-                max_age=max_age,
-                domain=c.get("domain"),
-                path=c.get("path"),
-                secure=True,
-                httponly=True,
-            )
-    return resp
-
-
-
-
-
-
-

Classes

-
-
-class DjangoListenerCompletionHandler -
-
-
- -Expand source code - -
class DjangoListenerCompletionHandler(ListenerCompletionHandler):
-    """Django sets DB connections as a thread-local variable per thread.
-    If the thread is not managed on the Django app side, the connections won't be released by Django.
-    This handler releases the connections every time a ThreadListenerRunner execution completes.
-    """
-
-    def handle(self, request: BoltRequest, response: Optional[BoltResponse]) -> None:
-        release_thread_local_connections(request.context.logger, "listener-completion")
-
-

Django sets DB connections as a thread-local variable per thread. -If the thread is not managed on the Django app side, the connections won't be released by Django. -This handler releases the connections every time a ThreadListenerRunner execution completes.

-

Ancestors

- -

Inherited members

- -
-
-class DjangoListenerStartHandler -
-
-
- -Expand source code - -
class DjangoListenerStartHandler(ListenerStartHandler):
-    """Django sets DB connections as a thread-local variable per thread.
-    If the thread is not managed on the Django app side, the connections won't be released by Django.
-    This handler releases the connections every time a ThreadListenerRunner execution completes.
-    """
-
-    def handle(self, request: BoltRequest, response: Optional[BoltResponse]) -> None:
-        release_thread_local_connections(request.context.logger, "listener-start")
-
-

Django sets DB connections as a thread-local variable per thread. -If the thread is not managed on the Django app side, the connections won't be released by Django. -This handler releases the connections every time a ThreadListenerRunner execution completes.

-

Ancestors

- -

Inherited members

- -
-
-class DjangoThreadLazyListenerRunner -(logger: logging.Logger, executor: concurrent.futures._base.Executor) -
-
-
- -Expand source code - -
class DjangoThreadLazyListenerRunner(ThreadLazyListenerRunner):
-    def start(self, function: Callable[..., None], request: BoltRequest) -> None:
-        func: Callable[[], None] = build_runnable_function(
-            func=function,
-            logger=self.logger,
-            request=request,
-        )
-
-        def wrapped_func():
-            release_thread_local_connections(request.context.logger, "before-lazy-listener")
-            try:
-                func()
-            finally:
-                release_thread_local_connections(request.context.logger, "lazy-listener-completion")
-
-        self.executor.submit(wrapped_func)
-
-
-

Ancestors

- -

Inherited members

- -
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-        listener_runner = self.app.listener_runner
-        # This runner closes all thread-local connections in the thread when an execution completes
-        self.app.listener_runner.lazy_listener_runner = DjangoThreadLazyListenerRunner(
-            logger=listener_runner.logger,
-            executor=listener_runner.listener_executor,
-        )
-
-        if not isinstance(listener_runner, ThreadListenerRunner):
-            raise BoltError("Custom listener_runners are not compatible with this Django adapter.")
-
-        if app.process_before_response is True:
-            # As long as the app access Django models in the same thread,
-            # Django cleans the connections up for you.
-            self.app.logger.debug("App.process_before_response is set to True")
-            return
-
-        current_start_handler = listener_runner.listener_start_handler
-        if current_start_handler is not None and not isinstance(current_start_handler, DefaultListenerStartHandler):
-            # As we run release_thread_local_connections() before listener executions,
-            # it's okay to skip calling the same connection clean-up method at the listener completion.
-            message = """As you've already set app.listener_runner.listener_start_handler to your own one,
-            Bolt skipped to set it to slack_sdk.adapter.django.DjangoListenerStartHandler.
-
-            If you go with your own handler here, we highly recommend having the following lines of code
-            in your handle() method to clean up unmanaged stale/old database connections:
-
-            from django.db import close_old_connections
-            close_old_connections()
-            """
-            self.app.logger.info(message)
-        else:
-            # for proper management of thread-local Django DB connections
-            self.app.listener_runner.listener_start_handler = DjangoListenerStartHandler()
-            self.app.logger.debug("DjangoListenerStartHandler has been enabled")
-
-        current_completion_handler = listener_runner.listener_completion_handler
-        if current_completion_handler is not None and not isinstance(
-            current_completion_handler, DefaultListenerCompletionHandler
-        ):
-            # As we run release_thread_local_connections() before listener executions,
-            # it's okay to skip calling the same connection clean-up method at the listener completion.
-            message = """As you've already set app.listener_runner.listener_completion_handler to your own one,
-            Bolt skipped to set it to slack_sdk.adapter.django.DjangoListenerCompletionHandler.
-            """
-            self.app.logger.info(message)
-            return
-        # for proper management of thread-local Django DB connections
-        self.app.listener_runner.listener_completion_handler = DjangoListenerCompletionHandler()
-        self.app.logger.debug("DjangoListenerCompletionHandler has been enabled")
-
-    def handle(self, req: HttpRequest) -> HttpResponse:
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                if req.path == oauth_flow.install_path:
-                    bolt_resp = oauth_flow.handle_installation(to_bolt_request(req))
-                    return to_django_response(bolt_resp)
-                elif req.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = oauth_flow.handle_callback(to_bolt_request(req))
-                    return to_django_response(bolt_resp)
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(to_bolt_request(req))
-            return to_django_response(bolt_resp)
-
-        return HttpResponse(status=404, content=b"Not Found")
-
-
-

Methods

-
-
-def handle(self, req: django.http.request.HttpRequest) ‑> django.http.response.HttpResponse -
-
-
- -Expand source code - -
def handle(self, req: HttpRequest) -> HttpResponse:
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if req.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(to_bolt_request(req))
-                return to_django_response(bolt_resp)
-            elif req.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(to_bolt_request(req))
-                return to_django_response(bolt_resp)
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(to_bolt_request(req))
-        return to_django_response(bolt_resp)
-
-    return HttpResponse(status=404, content=b"Not Found")
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/django/index.html b/docs/reference/adapter/django/index.html deleted file mode 100644 index dfb6af63f..000000000 --- a/docs/reference/adapter/django/index.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - -slack_bolt.adapter.django API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.django

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.django.handler
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-        listener_runner = self.app.listener_runner
-        # This runner closes all thread-local connections in the thread when an execution completes
-        self.app.listener_runner.lazy_listener_runner = DjangoThreadLazyListenerRunner(
-            logger=listener_runner.logger,
-            executor=listener_runner.listener_executor,
-        )
-
-        if not isinstance(listener_runner, ThreadListenerRunner):
-            raise BoltError("Custom listener_runners are not compatible with this Django adapter.")
-
-        if app.process_before_response is True:
-            # As long as the app access Django models in the same thread,
-            # Django cleans the connections up for you.
-            self.app.logger.debug("App.process_before_response is set to True")
-            return
-
-        current_start_handler = listener_runner.listener_start_handler
-        if current_start_handler is not None and not isinstance(current_start_handler, DefaultListenerStartHandler):
-            # As we run release_thread_local_connections() before listener executions,
-            # it's okay to skip calling the same connection clean-up method at the listener completion.
-            message = """As you've already set app.listener_runner.listener_start_handler to your own one,
-            Bolt skipped to set it to slack_sdk.adapter.django.DjangoListenerStartHandler.
-
-            If you go with your own handler here, we highly recommend having the following lines of code
-            in your handle() method to clean up unmanaged stale/old database connections:
-
-            from django.db import close_old_connections
-            close_old_connections()
-            """
-            self.app.logger.info(message)
-        else:
-            # for proper management of thread-local Django DB connections
-            self.app.listener_runner.listener_start_handler = DjangoListenerStartHandler()
-            self.app.logger.debug("DjangoListenerStartHandler has been enabled")
-
-        current_completion_handler = listener_runner.listener_completion_handler
-        if current_completion_handler is not None and not isinstance(
-            current_completion_handler, DefaultListenerCompletionHandler
-        ):
-            # As we run release_thread_local_connections() before listener executions,
-            # it's okay to skip calling the same connection clean-up method at the listener completion.
-            message = """As you've already set app.listener_runner.listener_completion_handler to your own one,
-            Bolt skipped to set it to slack_sdk.adapter.django.DjangoListenerCompletionHandler.
-            """
-            self.app.logger.info(message)
-            return
-        # for proper management of thread-local Django DB connections
-        self.app.listener_runner.listener_completion_handler = DjangoListenerCompletionHandler()
-        self.app.logger.debug("DjangoListenerCompletionHandler has been enabled")
-
-    def handle(self, req: HttpRequest) -> HttpResponse:
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                if req.path == oauth_flow.install_path:
-                    bolt_resp = oauth_flow.handle_installation(to_bolt_request(req))
-                    return to_django_response(bolt_resp)
-                elif req.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = oauth_flow.handle_callback(to_bolt_request(req))
-                    return to_django_response(bolt_resp)
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(to_bolt_request(req))
-            return to_django_response(bolt_resp)
-
-        return HttpResponse(status=404, content=b"Not Found")
-
-
-

Methods

-
-
-def handle(self, req: django.http.request.HttpRequest) ‑> django.http.response.HttpResponse -
-
-
- -Expand source code - -
def handle(self, req: HttpRequest) -> HttpResponse:
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if req.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(to_bolt_request(req))
-                return to_django_response(bolt_resp)
-            elif req.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(to_bolt_request(req))
-                return to_django_response(bolt_resp)
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(to_bolt_request(req))
-        return to_django_response(bolt_resp)
-
-    return HttpResponse(status=404, content=b"Not Found")
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/falcon/async_resource.html b/docs/reference/adapter/falcon/async_resource.html deleted file mode 100644 index 0dbba1ad4..000000000 --- a/docs/reference/adapter/falcon/async_resource.html +++ /dev/null @@ -1,206 +0,0 @@ - - - - - - -slack_bolt.adapter.falcon.async_resource API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.falcon.async_resource

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSlackAppResource -(app: AsyncApp) -
-
-
- -Expand source code - -
class AsyncSlackAppResource:
-    """
-    For use with ASGI Falcon Apps.
-
-    from slack_bolt.async_app import AsyncApp
-    app = AsyncApp()
-
-    import falcon
-    app = falcon.asgi.App()
-    app.add_route("/slack/events", AsyncSlackAppResource(app))
-    """
-
-    def __init__(self, app: AsyncApp):
-        if falcon_version.__version__.startswith("2."):
-            raise BoltError("This ASGI compatible adapter requires Falcon version >= 3.0")
-
-        self.app = app
-
-    async def on_get(self, req: Request, resp: Response):
-        if self.app.oauth_flow is not None:
-            oauth_flow: AsyncOAuthFlow = self.app.oauth_flow
-            if req.path == oauth_flow.install_path:
-                bolt_resp = await oauth_flow.handle_installation(await self._to_bolt_request(req))
-                await self._write_response(bolt_resp, resp)
-                return
-            elif req.path == oauth_flow.redirect_uri_path:
-                bolt_resp = await oauth_flow.handle_callback(await self._to_bolt_request(req))
-                await self._write_response(bolt_resp, resp)
-                return
-
-        resp.status = HTTPStatus.NOT_FOUND
-        resp.content_type = MEDIA_TEXT
-        resp.text = "The page is not found..."
-
-    async def on_post(self, req: Request, resp: Response):
-        bolt_req = await self._to_bolt_request(req)
-        bolt_resp = await self.app.async_dispatch(bolt_req)
-        await self._write_response(bolt_resp, resp)
-
-    async def _to_bolt_request(self, req: Request) -> AsyncBoltRequest:
-        return AsyncBoltRequest(
-            body=(await 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()},
-        )
-
-    async def _write_response(self, bolt_resp: BoltResponse, resp: Response):
-        resp.text = bolt_resp.body
-        status = HTTPStatus(bolt_resp.status)
-        resp.status = str(f"{status.value} {status.phrase}")
-        resp.set_headers(bolt_resp.first_headers_without_set_cookie())
-        for cookie in bolt_resp.cookies():
-            for name, c in cookie.items():
-                expire_value = c.get("expires")
-                expire = datetime.strptime(expire_value, "%a, %d %b %Y %H:%M:%S %Z") if expire_value else None
-                resp.set_cookie(
-                    name=name,
-                    value=c.value,
-                    expires=expire,
-                    max_age=c.get("max-age"),
-                    domain=c.get("domain"),
-                    path=c.get("path"),
-                    secure=True,
-                    http_only=True,
-                )
-
-

For use with ASGI Falcon Apps.

-

from slack_bolt.async_app import AsyncApp -app = AsyncApp()

-

import falcon -app = falcon.asgi.App() -app.add_route("/slack/events", AsyncSlackAppResource(app))

-

Methods

-
-
-async def on_get(self, req: falcon.asgi.request.Request, resp: falcon.asgi.response.Response) -
-
-
- -Expand source code - -
async def on_get(self, req: Request, resp: Response):
-    if self.app.oauth_flow is not None:
-        oauth_flow: AsyncOAuthFlow = self.app.oauth_flow
-        if req.path == oauth_flow.install_path:
-            bolt_resp = await oauth_flow.handle_installation(await self._to_bolt_request(req))
-            await self._write_response(bolt_resp, resp)
-            return
-        elif req.path == oauth_flow.redirect_uri_path:
-            bolt_resp = await oauth_flow.handle_callback(await self._to_bolt_request(req))
-            await self._write_response(bolt_resp, resp)
-            return
-
-    resp.status = HTTPStatus.NOT_FOUND
-    resp.content_type = MEDIA_TEXT
-    resp.text = "The page is not found..."
-
-
-
-
-async def on_post(self, req: falcon.asgi.request.Request, resp: falcon.asgi.response.Response) -
-
-
- -Expand source code - -
async def on_post(self, req: Request, resp: Response):
-    bolt_req = await self._to_bolt_request(req)
-    bolt_resp = await self.app.async_dispatch(bolt_req)
-    await self._write_response(bolt_resp, resp)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/falcon/index.html b/docs/reference/adapter/falcon/index.html deleted file mode 100644 index bfc21828f..000000000 --- a/docs/reference/adapter/falcon/index.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - -slack_bolt.adapter.falcon API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.falcon

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.falcon.async_resource
-
-
-
-
slack_bolt.adapter.falcon.resource
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackAppResource -(app: App) -
-
-
- -Expand source code - -
class SlackAppResource:
-    """
-    from slack_bolt import App
-    app = App()
-
-    import falcon
-    api = application = falcon.API()
-    api.add_route("/slack/events", SlackAppResource(app))
-    """
-
-    def __init__(self, app: App):
-        self.app = app
-
-    def on_get(self, req: Request, resp: Response):
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if req.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(self._to_bolt_request(req))
-                self._write_response(bolt_resp, resp)
-                return
-            elif req.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(self._to_bolt_request(req))
-                self._write_response(bolt_resp, resp)
-                return
-
-        resp.status = HTTPStatus.NOT_FOUND
-        resp.content_type = MEDIA_TEXT
-        resp.text = "The page is not found..."
-
-    def on_post(self, req: Request, resp: Response):
-        bolt_req = self._to_bolt_request(req)
-        bolt_resp = self.app.dispatch(bolt_req)
-        self._write_response(bolt_resp, resp)
-
-    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 _write_response(self, bolt_resp: BoltResponse, resp: Response):
-        if falcon_version.__version__.startswith("2."):
-            # Falcon 4.x w/ mypy fails to correctly infer the str type here
-            resp.body = bolt_resp.body
-        else:
-            resp.text = bolt_resp.body
-
-        status = HTTPStatus(bolt_resp.status)
-        resp.status = str(f"{status.value} {status.phrase}")
-        resp.set_headers(bolt_resp.first_headers_without_set_cookie())
-        for cookie in bolt_resp.cookies():
-            for name, c in cookie.items():
-                expire_value = c.get("expires")
-                expire = datetime.strptime(expire_value, "%a, %d %b %Y %H:%M:%S %Z") if expire_value else None
-                resp.set_cookie(
-                    name=name,
-                    value=c.value,
-                    expires=expire,
-                    max_age=c.get("max-age"),
-                    domain=c.get("domain"),
-                    path=c.get("path"),
-                    secure=True,
-                    http_only=True,
-                )
-
-

from slack_bolt import App -app = App()

-

import falcon -api = application = falcon.API() -api.add_route("/slack/events", SlackAppResource(app))

-

Methods

-
-
-def on_get(self, req: falcon.request.Request, resp: falcon.response.Response) -
-
-
- -Expand source code - -
def on_get(self, req: Request, resp: Response):
-    if self.app.oauth_flow is not None:
-        oauth_flow: OAuthFlow = self.app.oauth_flow
-        if req.path == oauth_flow.install_path:
-            bolt_resp = oauth_flow.handle_installation(self._to_bolt_request(req))
-            self._write_response(bolt_resp, resp)
-            return
-        elif req.path == oauth_flow.redirect_uri_path:
-            bolt_resp = oauth_flow.handle_callback(self._to_bolt_request(req))
-            self._write_response(bolt_resp, resp)
-            return
-
-    resp.status = HTTPStatus.NOT_FOUND
-    resp.content_type = MEDIA_TEXT
-    resp.text = "The page is not found..."
-
-
-
-
-def on_post(self, req: falcon.request.Request, resp: falcon.response.Response) -
-
-
- -Expand source code - -
def on_post(self, req: Request, resp: Response):
-    bolt_req = self._to_bolt_request(req)
-    bolt_resp = self.app.dispatch(bolt_req)
-    self._write_response(bolt_resp, resp)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/falcon/resource.html b/docs/reference/adapter/falcon/resource.html deleted file mode 100644 index 13f9a2177..000000000 --- a/docs/reference/adapter/falcon/resource.html +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - -slack_bolt.adapter.falcon.resource API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.falcon.resource

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackAppResource -(app: App) -
-
-
- -Expand source code - -
class SlackAppResource:
-    """
-    from slack_bolt import App
-    app = App()
-
-    import falcon
-    api = application = falcon.API()
-    api.add_route("/slack/events", SlackAppResource(app))
-    """
-
-    def __init__(self, app: App):
-        self.app = app
-
-    def on_get(self, req: Request, resp: Response):
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if req.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(self._to_bolt_request(req))
-                self._write_response(bolt_resp, resp)
-                return
-            elif req.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(self._to_bolt_request(req))
-                self._write_response(bolt_resp, resp)
-                return
-
-        resp.status = HTTPStatus.NOT_FOUND
-        resp.content_type = MEDIA_TEXT
-        resp.text = "The page is not found..."
-
-    def on_post(self, req: Request, resp: Response):
-        bolt_req = self._to_bolt_request(req)
-        bolt_resp = self.app.dispatch(bolt_req)
-        self._write_response(bolt_resp, resp)
-
-    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 _write_response(self, bolt_resp: BoltResponse, resp: Response):
-        if falcon_version.__version__.startswith("2."):
-            # Falcon 4.x w/ mypy fails to correctly infer the str type here
-            resp.body = bolt_resp.body
-        else:
-            resp.text = bolt_resp.body
-
-        status = HTTPStatus(bolt_resp.status)
-        resp.status = str(f"{status.value} {status.phrase}")
-        resp.set_headers(bolt_resp.first_headers_without_set_cookie())
-        for cookie in bolt_resp.cookies():
-            for name, c in cookie.items():
-                expire_value = c.get("expires")
-                expire = datetime.strptime(expire_value, "%a, %d %b %Y %H:%M:%S %Z") if expire_value else None
-                resp.set_cookie(
-                    name=name,
-                    value=c.value,
-                    expires=expire,
-                    max_age=c.get("max-age"),
-                    domain=c.get("domain"),
-                    path=c.get("path"),
-                    secure=True,
-                    http_only=True,
-                )
-
-

from slack_bolt import App -app = App()

-

import falcon -api = application = falcon.API() -api.add_route("/slack/events", SlackAppResource(app))

-

Methods

-
-
-def on_get(self, req: falcon.request.Request, resp: falcon.response.Response) -
-
-
- -Expand source code - -
def on_get(self, req: Request, resp: Response):
-    if self.app.oauth_flow is not None:
-        oauth_flow: OAuthFlow = self.app.oauth_flow
-        if req.path == oauth_flow.install_path:
-            bolt_resp = oauth_flow.handle_installation(self._to_bolt_request(req))
-            self._write_response(bolt_resp, resp)
-            return
-        elif req.path == oauth_flow.redirect_uri_path:
-            bolt_resp = oauth_flow.handle_callback(self._to_bolt_request(req))
-            self._write_response(bolt_resp, resp)
-            return
-
-    resp.status = HTTPStatus.NOT_FOUND
-    resp.content_type = MEDIA_TEXT
-    resp.text = "The page is not found..."
-
-
-
-
-def on_post(self, req: falcon.request.Request, resp: falcon.response.Response) -
-
-
- -Expand source code - -
def on_post(self, req: Request, resp: Response):
-    bolt_req = self._to_bolt_request(req)
-    bolt_resp = self.app.dispatch(bolt_req)
-    self._write_response(bolt_resp, resp)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/fastapi/async_handler.html b/docs/reference/adapter/fastapi/async_handler.html deleted file mode 100644 index 6f6205e51..000000000 --- a/docs/reference/adapter/fastapi/async_handler.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - -slack_bolt.adapter.fastapi.async_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.fastapi.async_handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSlackRequestHandler -(app: AsyncApp) -
-
-
- -Expand source code - -
class AsyncSlackRequestHandler:
-    def __init__(self, app: AsyncApp):
-        self.app = app
-
-    async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> Response:
-        body = await req.body()
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: AsyncOAuthFlow = self.app.oauth_flow
-                if req.url.path == oauth_flow.install_path:
-                    bolt_resp = await oauth_flow.handle_installation(
-                        to_async_bolt_request(req, body, addition_context_properties)
-                    )
-                    return to_starlette_response(bolt_resp)
-                elif req.url.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = await oauth_flow.handle_callback(
-                        to_async_bolt_request(req, body, addition_context_properties)
-                    )
-                    return to_starlette_response(bolt_resp)
-        elif req.method == "POST":
-            bolt_resp = await self.app.async_dispatch(to_async_bolt_request(req, body, addition_context_properties))
-            return to_starlette_response(bolt_resp)
-
-        return Response(
-            status_code=404,
-            content="Not found",
-        )
-
-
-

Methods

-
-
-async def handle(self,
req: starlette.requests.Request,
addition_context_properties: Dict[str, Any] | None = None) ‑> starlette.responses.Response
-
-
-
- -Expand source code - -
async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> Response:
-    body = await req.body()
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: AsyncOAuthFlow = self.app.oauth_flow
-            if req.url.path == oauth_flow.install_path:
-                bolt_resp = await oauth_flow.handle_installation(
-                    to_async_bolt_request(req, body, addition_context_properties)
-                )
-                return to_starlette_response(bolt_resp)
-            elif req.url.path == oauth_flow.redirect_uri_path:
-                bolt_resp = await oauth_flow.handle_callback(
-                    to_async_bolt_request(req, body, addition_context_properties)
-                )
-                return to_starlette_response(bolt_resp)
-    elif req.method == "POST":
-        bolt_resp = await self.app.async_dispatch(to_async_bolt_request(req, body, addition_context_properties))
-        return to_starlette_response(bolt_resp)
-
-    return Response(
-        status_code=404,
-        content="Not found",
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/fastapi/index.html b/docs/reference/adapter/fastapi/index.html deleted file mode 100644 index 6ffb52f35..000000000 --- a/docs/reference/adapter/fastapi/index.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - -slack_bolt.adapter.fastapi API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.fastapi

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.fastapi.async_handler
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-
-    async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> Response:
-        body = await req.body()
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                if req.url.path == oauth_flow.install_path:
-                    bolt_resp = oauth_flow.handle_installation(to_bolt_request(req, body, addition_context_properties))
-                    return to_starlette_response(bolt_resp)
-                elif req.url.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = oauth_flow.handle_callback(to_bolt_request(req, body, addition_context_properties))
-                    return to_starlette_response(bolt_resp)
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(to_bolt_request(req, body, addition_context_properties))
-            return to_starlette_response(bolt_resp)
-
-        return Response(
-            status_code=404,
-            content="Not found",
-        )
-
-
-

Methods

-
-
-async def handle(self,
req: starlette.requests.Request,
addition_context_properties: Dict[str, Any] | None = None) ‑> starlette.responses.Response
-
-
-
- -Expand source code - -
async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> Response:
-    body = await req.body()
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if req.url.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(to_bolt_request(req, body, addition_context_properties))
-                return to_starlette_response(bolt_resp)
-            elif req.url.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(to_bolt_request(req, body, addition_context_properties))
-                return to_starlette_response(bolt_resp)
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(to_bolt_request(req, body, addition_context_properties))
-        return to_starlette_response(bolt_resp)
-
-    return Response(
-        status_code=404,
-        content="Not found",
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/flask/handler.html b/docs/reference/adapter/flask/handler.html deleted file mode 100644 index 489b80a90..000000000 --- a/docs/reference/adapter/flask/handler.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - - -slack_bolt.adapter.flask.handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.flask.handler

-
-
-
-
-
-
-
-
-

Functions

-
-
-def to_bolt_request(req: flask.wrappers.Request) ‑> BoltRequest -
-
-
- -Expand source code - -
def to_bolt_request(req: Request) -> BoltRequest:
-    return BoltRequest(
-        body=req.get_data(as_text=True),
-        query=req.query_string.decode("utf-8"),
-        headers=req.headers,  # type: ignore[arg-type]
-    )
-
-
-
-
-def to_flask_response(bolt_resp: BoltResponse) ‑> flask.wrappers.Response -
-
-
- -Expand source code - -
def to_flask_response(bolt_resp: BoltResponse) -> Response:
-    resp: Response = make_response(bolt_resp.body, bolt_resp.status)
-    for k, values in bolt_resp.headers.items():
-        if k.lower() == "content-type" and resp.headers.get("content-type") is not None:
-            # Remove the one set by Flask
-            resp.headers.pop("content-type")
-        for v in values:
-            resp.headers.add_header(k, v)
-    return resp
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-
-    def handle(self, req: Request) -> Response:
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                if req.path == oauth_flow.install_path:
-                    bolt_resp = oauth_flow.handle_installation(to_bolt_request(req))
-                    return to_flask_response(bolt_resp)
-                elif req.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = oauth_flow.handle_callback(to_bolt_request(req))
-                    return to_flask_response(bolt_resp)
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(to_bolt_request(req))
-            return to_flask_response(bolt_resp)
-
-        return make_response("Not Found", 404)
-
-
-

Methods

-
-
-def handle(self, req: flask.wrappers.Request) ‑> flask.wrappers.Response -
-
-
- -Expand source code - -
def handle(self, req: Request) -> Response:
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if req.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(to_bolt_request(req))
-                return to_flask_response(bolt_resp)
-            elif req.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(to_bolt_request(req))
-                return to_flask_response(bolt_resp)
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(to_bolt_request(req))
-        return to_flask_response(bolt_resp)
-
-    return make_response("Not Found", 404)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/flask/index.html b/docs/reference/adapter/flask/index.html deleted file mode 100644 index ee765fa1e..000000000 --- a/docs/reference/adapter/flask/index.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - -slack_bolt.adapter.flask API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.flask

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.flask.handler
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-
-    def handle(self, req: Request) -> Response:
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                if req.path == oauth_flow.install_path:
-                    bolt_resp = oauth_flow.handle_installation(to_bolt_request(req))
-                    return to_flask_response(bolt_resp)
-                elif req.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = oauth_flow.handle_callback(to_bolt_request(req))
-                    return to_flask_response(bolt_resp)
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(to_bolt_request(req))
-            return to_flask_response(bolt_resp)
-
-        return make_response("Not Found", 404)
-
-
-

Methods

-
-
-def handle(self, req: flask.wrappers.Request) ‑> flask.wrappers.Response -
-
-
- -Expand source code - -
def handle(self, req: Request) -> Response:
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if req.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(to_bolt_request(req))
-                return to_flask_response(bolt_resp)
-            elif req.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(to_bolt_request(req))
-                return to_flask_response(bolt_resp)
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(to_bolt_request(req))
-        return to_flask_response(bolt_resp)
-
-    return make_response("Not Found", 404)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/google_cloud_functions/handler.html b/docs/reference/adapter/google_cloud_functions/handler.html deleted file mode 100644 index 1d9b0da7f..000000000 --- a/docs/reference/adapter/google_cloud_functions/handler.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - -slack_bolt.adapter.google_cloud_functions.handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.google_cloud_functions.handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class NoopLazyListenerRunner -
-
-
- -Expand source code - -
class NoopLazyListenerRunner(LazyListenerRunner):
-    def start(self, function: Callable[..., None], request: BoltRequest) -> None:
-        raise BoltError(
-            "The google_cloud_functions adapter does not support lazy listeners. "
-            "Please consider either having a queue to pass the request to a different function or "
-            "rewriting your code not to use lazy listeners."
-        )
-
-
-

Ancestors

- -

Inherited members

- -
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-        # Note that lazy listener is not supported
-        self.app.listener_runner.lazy_listener_runner = NoopLazyListenerRunner()
-        if self.app.oauth_flow is not None:
-            self.app.oauth_flow.settings.redirect_uri_page_renderer.install_path = "?"
-
-    def handle(self, req: Request) -> Response:
-        if req.method == "GET" and self.app.oauth_flow is not None:
-            bolt_req = to_bolt_request(req)
-            if "code" in req.args or "error" in req.args or "state" in req.args:
-                bolt_resp = self.app.oauth_flow.handle_callback(bolt_req)
-                return to_flask_response(bolt_resp)
-            else:
-                bolt_resp = self.app.oauth_flow.handle_installation(bolt_req)
-                return to_flask_response(bolt_resp)
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(to_bolt_request(req))
-            return to_flask_response(bolt_resp)
-
-        return make_response("Not Found", 404)
-
-
-

Methods

-
-
-def handle(self, req: flask.wrappers.Request) ‑> flask.wrappers.Response -
-
-
- -Expand source code - -
def handle(self, req: Request) -> Response:
-    if req.method == "GET" and self.app.oauth_flow is not None:
-        bolt_req = to_bolt_request(req)
-        if "code" in req.args or "error" in req.args or "state" in req.args:
-            bolt_resp = self.app.oauth_flow.handle_callback(bolt_req)
-            return to_flask_response(bolt_resp)
-        else:
-            bolt_resp = self.app.oauth_flow.handle_installation(bolt_req)
-            return to_flask_response(bolt_resp)
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(to_bolt_request(req))
-        return to_flask_response(bolt_resp)
-
-    return make_response("Not Found", 404)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/google_cloud_functions/index.html b/docs/reference/adapter/google_cloud_functions/index.html deleted file mode 100644 index 790d210be..000000000 --- a/docs/reference/adapter/google_cloud_functions/index.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - -slack_bolt.adapter.google_cloud_functions API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.google_cloud_functions

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.google_cloud_functions.handler
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-        # Note that lazy listener is not supported
-        self.app.listener_runner.lazy_listener_runner = NoopLazyListenerRunner()
-        if self.app.oauth_flow is not None:
-            self.app.oauth_flow.settings.redirect_uri_page_renderer.install_path = "?"
-
-    def handle(self, req: Request) -> Response:
-        if req.method == "GET" and self.app.oauth_flow is not None:
-            bolt_req = to_bolt_request(req)
-            if "code" in req.args or "error" in req.args or "state" in req.args:
-                bolt_resp = self.app.oauth_flow.handle_callback(bolt_req)
-                return to_flask_response(bolt_resp)
-            else:
-                bolt_resp = self.app.oauth_flow.handle_installation(bolt_req)
-                return to_flask_response(bolt_resp)
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(to_bolt_request(req))
-            return to_flask_response(bolt_resp)
-
-        return make_response("Not Found", 404)
-
-
-

Methods

-
-
-def handle(self, req: flask.wrappers.Request) ‑> flask.wrappers.Response -
-
-
- -Expand source code - -
def handle(self, req: Request) -> Response:
-    if req.method == "GET" and self.app.oauth_flow is not None:
-        bolt_req = to_bolt_request(req)
-        if "code" in req.args or "error" in req.args or "state" in req.args:
-            bolt_resp = self.app.oauth_flow.handle_callback(bolt_req)
-            return to_flask_response(bolt_resp)
-        else:
-            bolt_resp = self.app.oauth_flow.handle_installation(bolt_req)
-            return to_flask_response(bolt_resp)
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(to_bolt_request(req))
-        return to_flask_response(bolt_resp)
-
-    return make_response("Not Found", 404)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/index.html b/docs/reference/adapter/index.html deleted file mode 100644 index 646c0ac81..000000000 --- a/docs/reference/adapter/index.html +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - -slack_bolt.adapter API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter

-
-
-

Adapter modules for running Bolt apps along with Web frameworks or Socket Mode.

-
-
-

Sub-modules

-
-
slack_bolt.adapter.aiohttp
-
-
-
-
slack_bolt.adapter.asgi
-
-
-
-
slack_bolt.adapter.aws_lambda
-
-
-
-
slack_bolt.adapter.bottle
-
-
-
-
slack_bolt.adapter.cherrypy
-
-
-
-
slack_bolt.adapter.django
-
-
-
-
slack_bolt.adapter.falcon
-
-
-
-
slack_bolt.adapter.fastapi
-
-
-
-
slack_bolt.adapter.flask
-
-
-
-
slack_bolt.adapter.google_cloud_functions
-
-
-
-
slack_bolt.adapter.pyramid
-
-
-
-
slack_bolt.adapter.sanic
-
-
-
-
slack_bolt.adapter.socket_mode
-
-

Socket Mode adapter package provides the following implementations. If you don't have strong reasons to use 3rd party library based adapters, we …

-
-
slack_bolt.adapter.starlette
-
-
-
-
slack_bolt.adapter.tornado
-
-
-
-
slack_bolt.adapter.wsgi
-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/pyramid/handler.html b/docs/reference/adapter/pyramid/handler.html deleted file mode 100644 index 4a4a68849..000000000 --- a/docs/reference/adapter/pyramid/handler.html +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - -slack_bolt.adapter.pyramid.handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.pyramid.handler

-
-
-
-
-
-
-
-
-

Functions

-
-
-def to_bolt_request(request: pyramid.request.Request) ‑> BoltRequest -
-
-
- -Expand source code - -
def to_bolt_request(request: Request) -> BoltRequest:
-    body: str = ""
-    if request.body is not None:
-        if isinstance(request.body, bytes):
-            body = request.body.decode("utf-8")
-        else:
-            body = request.body
-    bolt_req = BoltRequest(
-        body=body,
-        query=request.query_string,
-        headers=request.headers,
-    )
-    return bolt_req
-
-
-
-
-def to_pyramid_response(bolt_resp: BoltResponse) ‑> pyramid.response.Response -
-
-
- -Expand source code - -
def to_pyramid_response(bolt_resp: BoltResponse) -> Response:
-    headers: List[Tuple[str, str]] = []
-    for k, vs in bolt_resp.headers.items():
-        for v in vs:
-            headers.append((k, v))
-
-    return Response(
-        status=bolt_resp.status,
-        body=bolt_resp.body or "",
-        headerlist=headers,
-        charset="utf-8",
-    )
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-
-    def handle(self, request: Request) -> Response:
-        if request.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                if request.path == oauth_flow.install_path:
-                    bolt_req = _attach_pyramid_request_to_context(to_bolt_request(request), request)
-                    bolt_resp = oauth_flow.handle_installation(bolt_req)
-                    return to_pyramid_response(bolt_resp)
-                elif request.path == oauth_flow.redirect_uri_path:
-                    bolt_req = _attach_pyramid_request_to_context(to_bolt_request(request), request)
-                    bolt_resp = oauth_flow.handle_callback(bolt_req)
-                    return to_pyramid_response(bolt_resp)
-        elif request.method == "POST":
-            bolt_req = _attach_pyramid_request_to_context(to_bolt_request(request), request)
-            bolt_resp = self.app.dispatch(bolt_req)
-            return to_pyramid_response(bolt_resp)
-
-        return Response(status=404, body="Not found")
-
-
-

Methods

-
-
-def handle(self, request: pyramid.request.Request) ‑> pyramid.response.Response -
-
-
- -Expand source code - -
def handle(self, request: Request) -> Response:
-    if request.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if request.path == oauth_flow.install_path:
-                bolt_req = _attach_pyramid_request_to_context(to_bolt_request(request), request)
-                bolt_resp = oauth_flow.handle_installation(bolt_req)
-                return to_pyramid_response(bolt_resp)
-            elif request.path == oauth_flow.redirect_uri_path:
-                bolt_req = _attach_pyramid_request_to_context(to_bolt_request(request), request)
-                bolt_resp = oauth_flow.handle_callback(bolt_req)
-                return to_pyramid_response(bolt_resp)
-    elif request.method == "POST":
-        bolt_req = _attach_pyramid_request_to_context(to_bolt_request(request), request)
-        bolt_resp = self.app.dispatch(bolt_req)
-        return to_pyramid_response(bolt_resp)
-
-    return Response(status=404, body="Not found")
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/pyramid/index.html b/docs/reference/adapter/pyramid/index.html deleted file mode 100644 index 7f0903cb6..000000000 --- a/docs/reference/adapter/pyramid/index.html +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - -slack_bolt.adapter.pyramid API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.pyramid

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.pyramid.handler
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-
-    def handle(self, request: Request) -> Response:
-        if request.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                if request.path == oauth_flow.install_path:
-                    bolt_req = _attach_pyramid_request_to_context(to_bolt_request(request), request)
-                    bolt_resp = oauth_flow.handle_installation(bolt_req)
-                    return to_pyramid_response(bolt_resp)
-                elif request.path == oauth_flow.redirect_uri_path:
-                    bolt_req = _attach_pyramid_request_to_context(to_bolt_request(request), request)
-                    bolt_resp = oauth_flow.handle_callback(bolt_req)
-                    return to_pyramid_response(bolt_resp)
-        elif request.method == "POST":
-            bolt_req = _attach_pyramid_request_to_context(to_bolt_request(request), request)
-            bolt_resp = self.app.dispatch(bolt_req)
-            return to_pyramid_response(bolt_resp)
-
-        return Response(status=404, body="Not found")
-
-
-

Methods

-
-
-def handle(self, request: pyramid.request.Request) ‑> pyramid.response.Response -
-
-
- -Expand source code - -
def handle(self, request: Request) -> Response:
-    if request.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if request.path == oauth_flow.install_path:
-                bolt_req = _attach_pyramid_request_to_context(to_bolt_request(request), request)
-                bolt_resp = oauth_flow.handle_installation(bolt_req)
-                return to_pyramid_response(bolt_resp)
-            elif request.path == oauth_flow.redirect_uri_path:
-                bolt_req = _attach_pyramid_request_to_context(to_bolt_request(request), request)
-                bolt_resp = oauth_flow.handle_callback(bolt_req)
-                return to_pyramid_response(bolt_resp)
-    elif request.method == "POST":
-        bolt_req = _attach_pyramid_request_to_context(to_bolt_request(request), request)
-        bolt_resp = self.app.dispatch(bolt_req)
-        return to_pyramid_response(bolt_resp)
-
-    return Response(status=404, body="Not found")
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/sanic/async_handler.html b/docs/reference/adapter/sanic/async_handler.html deleted file mode 100644 index adabe53be..000000000 --- a/docs/reference/adapter/sanic/async_handler.html +++ /dev/null @@ -1,216 +0,0 @@ - - - - - - -slack_bolt.adapter.sanic.async_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.sanic.async_handler

-
-
-
-
-
-
-
-
-

Functions

-
-
-def to_async_bolt_request(req: sanic.request.types.Request,
addition_context_properties: Dict[str, Any] | None = None) ‑> AsyncBoltRequest
-
-
-
- -Expand source code - -
def to_async_bolt_request(req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> AsyncBoltRequest:
-    request = AsyncBoltRequest(
-        body=req.body.decode("utf-8"),
-        query=req.query_string,
-        headers=req.headers,  # type: ignore[arg-type]
-    )
-
-    if addition_context_properties is not None:
-        for k, v in addition_context_properties.items():
-            request.context[k] = v
-
-    return request
-
-
-
-
-def to_sanic_response(bolt_resp: BoltResponse) ‑> sanic.response.types.HTTPResponse -
-
-
- -Expand source code - -
def to_sanic_response(bolt_resp: BoltResponse) -> HTTPResponse:
-    resp = HTTPResponse(
-        status=bolt_resp.status,
-        body=bolt_resp.body,
-        headers=bolt_resp.first_headers_without_set_cookie(),
-    )
-
-    for cookie in bolt_resp.cookies():
-        for key, c in cookie.items():
-            expire_value = c.get("expires")
-            expires = datetime.strptime(expire_value, "%a, %d %b %Y %H:%M:%S %Z") if expire_value else None
-            max_age = int(c["max-age"]) if c.get("max-age") else None
-            path = str(c.get("path")) if c.get("path") else "/"
-            domain = str(c.get("domain")) if c.get("domain") else None
-            resp.add_cookie(
-                key=key,
-                value=c.value,
-                expires=expires,
-                path=path,
-                domain=domain,
-                max_age=max_age,
-                secure=True,
-                httponly=True,
-            )
-
-    return resp
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSlackRequestHandler -(app: AsyncApp) -
-
-
- -Expand source code - -
class AsyncSlackRequestHandler:
-    def __init__(self, app: AsyncApp):
-        self.app = app
-
-    async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> HTTPResponse:
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: AsyncOAuthFlow = self.app.oauth_flow
-                if req.path == oauth_flow.install_path:
-                    bolt_resp = await oauth_flow.handle_installation(to_async_bolt_request(req, addition_context_properties))
-                    return to_sanic_response(bolt_resp)
-                elif req.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = await oauth_flow.handle_callback(to_async_bolt_request(req, addition_context_properties))
-                    return to_sanic_response(bolt_resp)
-
-        elif req.method == "POST":
-            bolt_resp = await self.app.async_dispatch(to_async_bolt_request(req, addition_context_properties))
-            return to_sanic_response(bolt_resp)
-
-        return HTTPResponse(
-            status=404,
-            body="Not found",
-        )
-
-
-

Methods

-
-
-async def handle(self,
req: sanic.request.types.Request,
addition_context_properties: Dict[str, Any] | None = None) ‑> sanic.response.types.HTTPResponse
-
-
-
- -Expand source code - -
async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> HTTPResponse:
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: AsyncOAuthFlow = self.app.oauth_flow
-            if req.path == oauth_flow.install_path:
-                bolt_resp = await oauth_flow.handle_installation(to_async_bolt_request(req, addition_context_properties))
-                return to_sanic_response(bolt_resp)
-            elif req.path == oauth_flow.redirect_uri_path:
-                bolt_resp = await oauth_flow.handle_callback(to_async_bolt_request(req, addition_context_properties))
-                return to_sanic_response(bolt_resp)
-
-    elif req.method == "POST":
-        bolt_resp = await self.app.async_dispatch(to_async_bolt_request(req, addition_context_properties))
-        return to_sanic_response(bolt_resp)
-
-    return HTTPResponse(
-        status=404,
-        body="Not found",
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/sanic/index.html b/docs/reference/adapter/sanic/index.html deleted file mode 100644 index 558bb321c..000000000 --- a/docs/reference/adapter/sanic/index.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - -slack_bolt.adapter.sanic API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.sanic

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.sanic.async_handler
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSlackRequestHandler -(app: AsyncApp) -
-
-
- -Expand source code - -
class AsyncSlackRequestHandler:
-    def __init__(self, app: AsyncApp):
-        self.app = app
-
-    async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> HTTPResponse:
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: AsyncOAuthFlow = self.app.oauth_flow
-                if req.path == oauth_flow.install_path:
-                    bolt_resp = await oauth_flow.handle_installation(to_async_bolt_request(req, addition_context_properties))
-                    return to_sanic_response(bolt_resp)
-                elif req.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = await oauth_flow.handle_callback(to_async_bolt_request(req, addition_context_properties))
-                    return to_sanic_response(bolt_resp)
-
-        elif req.method == "POST":
-            bolt_resp = await self.app.async_dispatch(to_async_bolt_request(req, addition_context_properties))
-            return to_sanic_response(bolt_resp)
-
-        return HTTPResponse(
-            status=404,
-            body="Not found",
-        )
-
-
-

Methods

-
-
-async def handle(self,
req: sanic.request.types.Request,
addition_context_properties: Dict[str, Any] | None = None) ‑> sanic.response.types.HTTPResponse
-
-
-
- -Expand source code - -
async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> HTTPResponse:
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: AsyncOAuthFlow = self.app.oauth_flow
-            if req.path == oauth_flow.install_path:
-                bolt_resp = await oauth_flow.handle_installation(to_async_bolt_request(req, addition_context_properties))
-                return to_sanic_response(bolt_resp)
-            elif req.path == oauth_flow.redirect_uri_path:
-                bolt_resp = await oauth_flow.handle_callback(to_async_bolt_request(req, addition_context_properties))
-                return to_sanic_response(bolt_resp)
-
-    elif req.method == "POST":
-        bolt_resp = await self.app.async_dispatch(to_async_bolt_request(req, addition_context_properties))
-        return to_sanic_response(bolt_resp)
-
-    return HTTPResponse(
-        status=404,
-        body="Not found",
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/socket_mode/aiohttp/index.html b/docs/reference/adapter/socket_mode/aiohttp/index.html deleted file mode 100644 index cc91a3d06..000000000 --- a/docs/reference/adapter/socket_mode/aiohttp/index.html +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - -slack_bolt.adapter.socket_mode.aiohttp API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.socket_mode.aiohttp

-
-
-

aiohttp based implementation / asyncio compatible

-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSocketModeHandler -(app: AsyncApp,
app_token: str | None = None,
logger: logging.Logger | None = None,
web_client: slack_sdk.web.async_client.AsyncWebClient | None = None,
proxy: str | None = None,
ping_interval: float = 10,
loop: asyncio.events.AbstractEventLoop | None = None)
-
-
-
- -Expand source code - -
class AsyncSocketModeHandler(AsyncBaseSocketModeHandler):
-    app: AsyncApp
-    app_token: str
-    client: SocketModeClient
-
-    def __init__(
-        self,
-        app: AsyncApp,
-        app_token: Optional[str] = None,
-        logger: Optional[Logger] = None,
-        web_client: Optional[AsyncWebClient] = None,
-        proxy: Optional[str] = None,
-        ping_interval: float = 10,
-        loop: Optional[AbstractEventLoop] = None,
-    ):
-        self.app = app
-        self.app_token = app_token or os.environ["SLACK_APP_TOKEN"]
-        self.client = SocketModeClient(
-            app_token=self.app_token,
-            logger=logger if logger is not None else app.logger,
-            web_client=web_client if web_client is not None else app.client,
-            proxy=proxy,
-            ping_interval=ping_interval,
-            loop=loop,
-        )
-        self.client.socket_mode_request_listeners.append(self.handle)  # type: ignore[arg-type]
-
-    async def handle(self, client: SocketModeClient, req: SocketModeRequest) -> None:  # type: ignore[override]
-        start = time()
-        bolt_resp: BoltResponse = await run_async_bolt_app(self.app, req)
-        await send_async_response(client, req, bolt_resp, start)
-
-
-

Ancestors

- -

Class variables

-
-
var app_token : str
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class SocketModeHandler -(app: App,
app_token: str | None = None,
logger: logging.Logger | None = None,
web_client: slack_sdk.web.async_client.AsyncWebClient | None = None,
proxy: str | None = None,
ping_interval: float = 10)
-
-
-
- -Expand source code - -
class SocketModeHandler(AsyncBaseSocketModeHandler):
-    app: App
-    app_token: str
-    client: SocketModeClient
-
-    def __init__(
-        self,
-        app: App,
-        app_token: Optional[str] = None,
-        logger: Optional[Logger] = None,
-        web_client: Optional[AsyncWebClient] = None,
-        proxy: Optional[str] = None,
-        ping_interval: float = 10,
-    ):
-        """Socket Mode adapter for Bolt apps
-
-        Args:
-            app: The Bolt app
-            app_token: App-level token starting with `xapp-`
-            logger: Custom logger
-            web_client: custom `slack_sdk.web.WebClient` instance
-            proxy: HTTP proxy URL
-            ping_interval: The ping-pong internal (seconds)
-        """
-        self.app = app
-        self.app_token = app_token or os.environ["SLACK_APP_TOKEN"]
-        self.client = SocketModeClient(
-            app_token=self.app_token,
-            logger=logger if logger is not None else app.logger,
-            web_client=web_client if web_client is not None else app.client,  # type: ignore[arg-type]
-            proxy=proxy,
-            ping_interval=ping_interval,
-        )
-        self.client.socket_mode_request_listeners.append(self.handle)  # type: ignore[arg-type]
-
-    async def handle(self, client: SocketModeClient, req: SocketModeRequest) -> None:  # type: ignore[override]
-        start = time()
-        bolt_resp: BoltResponse = run_bolt_app(self.app, req)
-        await send_async_response(client, req, bolt_resp, start)
-
-

Socket Mode adapter for Bolt apps

-

Args

-
-
app
-
The Bolt app
-
app_token
-
App-level token starting with xapp-
-
logger
-
Custom logger
-
web_client
-
custom slack_sdk.web.WebClient instance
-
proxy
-
HTTP proxy URL
-
ping_interval
-
The ping-pong internal (seconds)
-
-

Ancestors

- -

Class variables

-
-
var app_token : str
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/socket_mode/async_base_handler.html b/docs/reference/adapter/socket_mode/async_base_handler.html deleted file mode 100644 index b00420c11..000000000 --- a/docs/reference/adapter/socket_mode/async_base_handler.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - -slack_bolt.adapter.socket_mode.async_base_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.socket_mode.async_base_handler

-
-
-

The base class of asyncio-based Socket Mode client implementation

-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncBaseSocketModeHandler -
-
-
- -Expand source code - -
class AsyncBaseSocketModeHandler:
-    app: Union[App, AsyncApp]
-    client: AsyncBaseSocketModeClient
-
-    async def handle(self, client: AsyncBaseSocketModeClient, req: SocketModeRequest) -> None:
-        """Handles Socket Mode envelope requests through a WebSocket connection.
-
-        Args:
-            client: this Socket Mode client instance
-            req: the request data
-        """
-        raise NotImplementedError()
-
-    async def connect_async(self):
-        """Establishes a new connection with the Socket Mode server"""
-        await self.client.connect()
-
-    async def disconnect_async(self):
-        """Disconnects the current WebSocket connection with the Socket Mode server"""
-        await self.client.disconnect()
-
-    async def close_async(self):
-        """Disconnects from the Socket Mode server and cleans the resources this instance holds up"""
-        await self.client.close()
-
-    async def start_async(self):
-        """Establishes a new connection and then starts infinite sleep
-        to prevent the termination of this process.
-        If you don't want to have the sleep, use `#connect()` method instead.
-        """
-        await self.connect_async()
-        if self.app.logger.level > logging.INFO:
-            print(get_boot_message())
-        else:
-            self.app.logger.info(get_boot_message())
-        await asyncio.sleep(float("inf"))
-
-
-

Subclasses

- -

Class variables

-
-
var appApp | AsyncApp
-
-

The type of the None singleton.

-
-
var client : slack_sdk.socket_mode.async_client.AsyncBaseSocketModeClient
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-async def close_async(self) -
-
-
- -Expand source code - -
async def close_async(self):
-    """Disconnects from the Socket Mode server and cleans the resources this instance holds up"""
-    await self.client.close()
-
-

Disconnects from the Socket Mode server and cleans the resources this instance holds up

-
-
-async def connect_async(self) -
-
-
- -Expand source code - -
async def connect_async(self):
-    """Establishes a new connection with the Socket Mode server"""
-    await self.client.connect()
-
-

Establishes a new connection with the Socket Mode server

-
-
-async def disconnect_async(self) -
-
-
- -Expand source code - -
async def disconnect_async(self):
-    """Disconnects the current WebSocket connection with the Socket Mode server"""
-    await self.client.disconnect()
-
-

Disconnects the current WebSocket connection with the Socket Mode server

-
-
-async def handle(self,
client: slack_sdk.socket_mode.async_client.AsyncBaseSocketModeClient,
req: slack_sdk.socket_mode.request.SocketModeRequest) ‑> None
-
-
-
- -Expand source code - -
async def handle(self, client: AsyncBaseSocketModeClient, req: SocketModeRequest) -> None:
-    """Handles Socket Mode envelope requests through a WebSocket connection.
-
-    Args:
-        client: this Socket Mode client instance
-        req: the request data
-    """
-    raise NotImplementedError()
-
-

Handles Socket Mode envelope requests through a WebSocket connection.

-

Args

-
-
client
-
this Socket Mode client instance
-
req
-
the request data
-
-
-
-async def start_async(self) -
-
-
- -Expand source code - -
async def start_async(self):
-    """Establishes a new connection and then starts infinite sleep
-    to prevent the termination of this process.
-    If you don't want to have the sleep, use `#connect()` method instead.
-    """
-    await self.connect_async()
-    if self.app.logger.level > logging.INFO:
-        print(get_boot_message())
-    else:
-        self.app.logger.info(get_boot_message())
-    await asyncio.sleep(float("inf"))
-
-

Establishes a new connection and then starts infinite sleep -to prevent the termination of this process. -If you don't want to have the sleep, use #connect() method instead.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/socket_mode/async_handler.html b/docs/reference/adapter/socket_mode/async_handler.html deleted file mode 100644 index 447ecf0ea..000000000 --- a/docs/reference/adapter/socket_mode/async_handler.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - -slack_bolt.adapter.socket_mode.async_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.socket_mode.async_handler

-
-
-

Default implementation is the aiohttp-based one.

-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSocketModeHandler -(app: AsyncApp,
app_token: str | None = None,
logger: logging.Logger | None = None,
web_client: slack_sdk.web.async_client.AsyncWebClient | None = None,
proxy: str | None = None,
ping_interval: float = 10,
loop: asyncio.events.AbstractEventLoop | None = None)
-
-
-
- -Expand source code - -
class AsyncSocketModeHandler(AsyncBaseSocketModeHandler):
-    app: AsyncApp
-    app_token: str
-    client: SocketModeClient
-
-    def __init__(
-        self,
-        app: AsyncApp,
-        app_token: Optional[str] = None,
-        logger: Optional[Logger] = None,
-        web_client: Optional[AsyncWebClient] = None,
-        proxy: Optional[str] = None,
-        ping_interval: float = 10,
-        loop: Optional[AbstractEventLoop] = None,
-    ):
-        self.app = app
-        self.app_token = app_token or os.environ["SLACK_APP_TOKEN"]
-        self.client = SocketModeClient(
-            app_token=self.app_token,
-            logger=logger if logger is not None else app.logger,
-            web_client=web_client if web_client is not None else app.client,
-            proxy=proxy,
-            ping_interval=ping_interval,
-            loop=loop,
-        )
-        self.client.socket_mode_request_listeners.append(self.handle)  # type: ignore[arg-type]
-
-    async def handle(self, client: SocketModeClient, req: SocketModeRequest) -> None:  # type: ignore[override]
-        start = time()
-        bolt_resp: BoltResponse = await run_async_bolt_app(self.app, req)
-        await send_async_response(client, req, bolt_resp, start)
-
-
-

Ancestors

- -

Class variables

-
-
var app_token : str
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/socket_mode/async_internals.html b/docs/reference/adapter/socket_mode/async_internals.html deleted file mode 100644 index c0b23b1de..000000000 --- a/docs/reference/adapter/socket_mode/async_internals.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - -slack_bolt.adapter.socket_mode.async_internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.socket_mode.async_internals

-
-
-

Internal functions

-
-
-
-
-
-
-

Functions

-
-
-async def run_async_bolt_app(app: AsyncApp,
req: slack_sdk.socket_mode.request.SocketModeRequest)
-
-
-
- -Expand source code - -
async def run_async_bolt_app(app: AsyncApp, req: SocketModeRequest):
-    bolt_req: AsyncBoltRequest = AsyncBoltRequest(mode="socket_mode", body=req.payload, headers=build_headers(req))
-    bolt_resp: BoltResponse = await app.async_dispatch(bolt_req)
-    return bolt_resp
-
-
-
-
-async def send_async_response(client: slack_sdk.socket_mode.async_client.AsyncBaseSocketModeClient,
req: slack_sdk.socket_mode.request.SocketModeRequest,
bolt_resp: BoltResponse,
start_time: float)
-
-
-
- -Expand source code - -
async def send_async_response(
-    client: AsyncBaseSocketModeClient,
-    req: SocketModeRequest,
-    bolt_resp: BoltResponse,
-    start_time: float,
-):
-    if bolt_resp.status == 200:
-        content_type = bolt_resp.headers.get("content-type", [""])[0]
-        if bolt_resp.body is None or len(bolt_resp.body) == 0:
-            await client.send_socket_mode_response(SocketModeResponse(envelope_id=req.envelope_id))
-        elif content_type.startswith("application/json"):
-            dict_body = json.loads(bolt_resp.body)
-            await client.send_socket_mode_response(SocketModeResponse(envelope_id=req.envelope_id, payload=dict_body))
-        else:
-            await client.send_socket_mode_response(
-                SocketModeResponse(
-                    envelope_id=req.envelope_id,
-                    payload={"text": bolt_resp.body},
-                )
-            )
-        if client.logger.level <= logging.DEBUG:
-            spent_time = int((time() - start_time) * 1000)
-            client.logger.debug(f"Response time: {spent_time} milliseconds")
-    else:
-        client.logger.info(f"Unsuccessful Bolt execution result (status: {bolt_resp.status}, body: {bolt_resp.body})")
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/socket_mode/base_handler.html b/docs/reference/adapter/socket_mode/base_handler.html deleted file mode 100644 index 450f9ac0e..000000000 --- a/docs/reference/adapter/socket_mode/base_handler.html +++ /dev/null @@ -1,258 +0,0 @@ - - - - - - -slack_bolt.adapter.socket_mode.base_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.socket_mode.base_handler

-
-
-

The base class of Socket Mode client implementation. -If you want to build asyncio-based ones, use AsyncBaseSocketModeHandler instead.

-
-
-
-
-
-
-
-
-

Classes

-
-
-class BaseSocketModeHandler -
-
-
- -Expand source code - -
class BaseSocketModeHandler:
-    app: App
-    client: BaseSocketModeClient
-
-    def handle(self, client: BaseSocketModeClient, req: SocketModeRequest) -> None:
-        """Handles Socket Mode envelope requests through a WebSocket connection.
-
-        Args:
-            client: this Socket Mode client instance
-            req: the request data
-        """
-        raise NotImplementedError()
-
-    def connect(self):
-        """Establishes a new connection with the Socket Mode server"""
-        self.client.connect()
-
-    def disconnect(self):
-        """Disconnects the current WebSocket connection with the Socket Mode server"""
-        self.client.disconnect()
-
-    def close(self):
-        """Disconnects from the Socket Mode server and cleans the resources this instance holds up"""
-        self.client.close()
-
-    def start(self):
-        """Establishes a new connection and then blocks the current thread
-        to prevent the termination of this process.
-        If you don't want to block the current thread, use `#connect()` method instead.
-        """
-        self.connect()
-        if self.app.logger.level > logging.INFO:
-            print(get_boot_message())
-        else:
-            self.app.logger.info(get_boot_message())
-
-        if sys.platform == "win32":
-            # Ctrl+C etc does not work on Windows OS
-            # see https://bugs.python.org/issue35935 for details
-            signal.signal(signal.SIGINT, signal.SIG_DFL)
-
-        Event().wait()
-
-
-

Subclasses

- -

Class variables

-
-
var appApp
-
-

The type of the None singleton.

-
-
var client : slack_sdk.socket_mode.client.BaseSocketModeClient
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def close(self) -
-
-
- -Expand source code - -
def close(self):
-    """Disconnects from the Socket Mode server and cleans the resources this instance holds up"""
-    self.client.close()
-
-

Disconnects from the Socket Mode server and cleans the resources this instance holds up

-
-
-def connect(self) -
-
-
- -Expand source code - -
def connect(self):
-    """Establishes a new connection with the Socket Mode server"""
-    self.client.connect()
-
-

Establishes a new connection with the Socket Mode server

-
-
-def disconnect(self) -
-
-
- -Expand source code - -
def disconnect(self):
-    """Disconnects the current WebSocket connection with the Socket Mode server"""
-    self.client.disconnect()
-
-

Disconnects the current WebSocket connection with the Socket Mode server

-
-
-def handle(self,
client: slack_sdk.socket_mode.client.BaseSocketModeClient,
req: slack_sdk.socket_mode.request.SocketModeRequest) ‑> None
-
-
-
- -Expand source code - -
def handle(self, client: BaseSocketModeClient, req: SocketModeRequest) -> None:
-    """Handles Socket Mode envelope requests through a WebSocket connection.
-
-    Args:
-        client: this Socket Mode client instance
-        req: the request data
-    """
-    raise NotImplementedError()
-
-

Handles Socket Mode envelope requests through a WebSocket connection.

-

Args

-
-
client
-
this Socket Mode client instance
-
req
-
the request data
-
-
-
-def start(self) -
-
-
- -Expand source code - -
def start(self):
-    """Establishes a new connection and then blocks the current thread
-    to prevent the termination of this process.
-    If you don't want to block the current thread, use `#connect()` method instead.
-    """
-    self.connect()
-    if self.app.logger.level > logging.INFO:
-        print(get_boot_message())
-    else:
-        self.app.logger.info(get_boot_message())
-
-    if sys.platform == "win32":
-        # Ctrl+C etc does not work on Windows OS
-        # see https://bugs.python.org/issue35935 for details
-        signal.signal(signal.SIGINT, signal.SIG_DFL)
-
-    Event().wait()
-
-

Establishes a new connection and then blocks the current thread -to prevent the termination of this process. -If you don't want to block the current thread, use #connect() method instead.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/socket_mode/builtin/index.html b/docs/reference/adapter/socket_mode/builtin/index.html deleted file mode 100644 index fc66eb203..000000000 --- a/docs/reference/adapter/socket_mode/builtin/index.html +++ /dev/null @@ -1,206 +0,0 @@ - - - - - - -slack_bolt.adapter.socket_mode.builtin API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.socket_mode.builtin

-
-
-

The built-in implementation, which does not have any external dependencies

-
-
-
-
-
-
-
-
-

Classes

-
-
-class SocketModeHandler -(app: App,
app_token: str | None = None,
logger: logging.Logger | None = None,
web_client: slack_sdk.web.client.WebClient | None = None,
proxy: str | None = None,
proxy_headers: Dict[str, str] | None = None,
auto_reconnect_enabled: bool = True,
trace_enabled: bool = False,
all_message_trace_enabled: bool = False,
ping_pong_trace_enabled: bool = False,
ping_interval: float = 10,
receive_buffer_size: int = 1024,
concurrency: int = 10)
-
-
-
- -Expand source code - -
class SocketModeHandler(BaseSocketModeHandler):
-    app: App
-    app_token: str
-    client: SocketModeClient
-
-    def __init__(
-        self,
-        app: App,
-        app_token: Optional[str] = None,
-        logger: Optional[Logger] = None,
-        web_client: Optional[WebClient] = None,
-        proxy: Optional[str] = None,
-        proxy_headers: Optional[Dict[str, str]] = None,
-        auto_reconnect_enabled: bool = True,
-        trace_enabled: bool = False,
-        all_message_trace_enabled: bool = False,
-        ping_pong_trace_enabled: bool = False,
-        ping_interval: float = 10,
-        receive_buffer_size: int = 1024,
-        concurrency: int = 10,
-    ):
-        """Socket Mode adapter for Bolt apps
-
-        Args:
-            app: The Bolt app
-            app_token: App-level token starting with `xapp-`
-            logger: Custom logger
-            web_client: custom `slack_sdk.web.WebClient` instance
-            proxy: HTTP proxy URL
-            proxy_headers: Additional request header for proxy connections
-            auto_reconnect_enabled: True if the auto-reconnect logic works
-            trace_enabled: True if trace-level logging is enabled
-            all_message_trace_enabled: True if trace-logging for all received WebSocket messages is enabled
-            ping_pong_trace_enabled: True if trace-logging for all ping-pong communications
-            ping_interval: The ping-pong internal (seconds)
-            receive_buffer_size: The data length for a single socket recv operation
-            concurrency: The size of the underlying thread pool
-        """
-        self.app = app
-        self.app_token = app_token or os.environ["SLACK_APP_TOKEN"]
-        self.client = SocketModeClient(
-            app_token=self.app_token,
-            logger=logger if logger is not None else app.logger,
-            web_client=web_client if web_client is not None else app.client,
-            proxy=proxy if proxy is not None else app.client.proxy,
-            proxy_headers=proxy_headers,
-            auto_reconnect_enabled=auto_reconnect_enabled,
-            trace_enabled=trace_enabled,
-            all_message_trace_enabled=all_message_trace_enabled,
-            ping_pong_trace_enabled=ping_pong_trace_enabled,
-            ping_interval=ping_interval,
-            receive_buffer_size=receive_buffer_size,
-            concurrency=concurrency,
-        )
-        self.client.socket_mode_request_listeners.append(self.handle)  # type: ignore[arg-type]
-
-    def handle(self, client: SocketModeClient, req: SocketModeRequest) -> None:  # type: ignore[override]
-        start = time()
-        bolt_resp: BoltResponse = run_bolt_app(self.app, req)
-        send_response(client, req, bolt_resp, start)
-
-

Socket Mode adapter for Bolt apps

-

Args

-
-
app
-
The Bolt app
-
app_token
-
App-level token starting with xapp-
-
logger
-
Custom logger
-
web_client
-
custom slack_sdk.web.WebClient instance
-
proxy
-
HTTP proxy URL
-
proxy_headers
-
Additional request header for proxy connections
-
auto_reconnect_enabled
-
True if the auto-reconnect logic works
-
trace_enabled
-
True if trace-level logging is enabled
-
all_message_trace_enabled
-
True if trace-logging for all received WebSocket messages is enabled
-
ping_pong_trace_enabled
-
True if trace-logging for all ping-pong communications
-
ping_interval
-
The ping-pong internal (seconds)
-
receive_buffer_size
-
The data length for a single socket recv operation
-
concurrency
-
The size of the underlying thread pool
-
-

Ancestors

- -

Class variables

-
-
var app_token : str
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/socket_mode/index.html b/docs/reference/adapter/socket_mode/index.html deleted file mode 100644 index 511ef4840..000000000 --- a/docs/reference/adapter/socket_mode/index.html +++ /dev/null @@ -1,266 +0,0 @@ - - - - - - -slack_bolt.adapter.socket_mode API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.socket_mode

-
-
-

Socket Mode adapter package provides the following implementations. If you don't have strong reasons to use 3rd party library based adapters, we recommend using the built-in client based one.

- -
-
-

Sub-modules

-
-
slack_bolt.adapter.socket_mode.aiohttp
-
-

aiohttp based implementation / asyncio compatible

-
-
slack_bolt.adapter.socket_mode.async_base_handler
-
-

The base class of asyncio-based Socket Mode client implementation

-
-
slack_bolt.adapter.socket_mode.async_handler
-
-

Default implementation is the aiohttp-based one.

-
-
slack_bolt.adapter.socket_mode.async_internals
-
-

Internal functions

-
-
slack_bolt.adapter.socket_mode.base_handler
-
-

The base class of Socket Mode client implementation. -If you want to build asyncio-based ones, use AsyncBaseSocketModeHandler instead.

-
-
slack_bolt.adapter.socket_mode.builtin
-
-

The built-in implementation, which does not have any external dependencies

-
-
slack_bolt.adapter.socket_mode.internals
-
-

Internal functions

-
-
slack_bolt.adapter.socket_mode.websocket_client
-
-

websocket-client based implementation

-
-
slack_bolt.adapter.socket_mode.websockets
-
-

websockets based implementation -/ asyncio compatible

-
-
-
-
-
-
-
-
-

Classes

-
-
-class SocketModeHandler -(app: App,
app_token: str | None = None,
logger: logging.Logger | None = None,
web_client: slack_sdk.web.client.WebClient | None = None,
proxy: str | None = None,
proxy_headers: Dict[str, str] | None = None,
auto_reconnect_enabled: bool = True,
trace_enabled: bool = False,
all_message_trace_enabled: bool = False,
ping_pong_trace_enabled: bool = False,
ping_interval: float = 10,
receive_buffer_size: int = 1024,
concurrency: int = 10)
-
-
-
- -Expand source code - -
class SocketModeHandler(BaseSocketModeHandler):
-    app: App
-    app_token: str
-    client: SocketModeClient
-
-    def __init__(
-        self,
-        app: App,
-        app_token: Optional[str] = None,
-        logger: Optional[Logger] = None,
-        web_client: Optional[WebClient] = None,
-        proxy: Optional[str] = None,
-        proxy_headers: Optional[Dict[str, str]] = None,
-        auto_reconnect_enabled: bool = True,
-        trace_enabled: bool = False,
-        all_message_trace_enabled: bool = False,
-        ping_pong_trace_enabled: bool = False,
-        ping_interval: float = 10,
-        receive_buffer_size: int = 1024,
-        concurrency: int = 10,
-    ):
-        """Socket Mode adapter for Bolt apps
-
-        Args:
-            app: The Bolt app
-            app_token: App-level token starting with `xapp-`
-            logger: Custom logger
-            web_client: custom `slack_sdk.web.WebClient` instance
-            proxy: HTTP proxy URL
-            proxy_headers: Additional request header for proxy connections
-            auto_reconnect_enabled: True if the auto-reconnect logic works
-            trace_enabled: True if trace-level logging is enabled
-            all_message_trace_enabled: True if trace-logging for all received WebSocket messages is enabled
-            ping_pong_trace_enabled: True if trace-logging for all ping-pong communications
-            ping_interval: The ping-pong internal (seconds)
-            receive_buffer_size: The data length for a single socket recv operation
-            concurrency: The size of the underlying thread pool
-        """
-        self.app = app
-        self.app_token = app_token or os.environ["SLACK_APP_TOKEN"]
-        self.client = SocketModeClient(
-            app_token=self.app_token,
-            logger=logger if logger is not None else app.logger,
-            web_client=web_client if web_client is not None else app.client,
-            proxy=proxy if proxy is not None else app.client.proxy,
-            proxy_headers=proxy_headers,
-            auto_reconnect_enabled=auto_reconnect_enabled,
-            trace_enabled=trace_enabled,
-            all_message_trace_enabled=all_message_trace_enabled,
-            ping_pong_trace_enabled=ping_pong_trace_enabled,
-            ping_interval=ping_interval,
-            receive_buffer_size=receive_buffer_size,
-            concurrency=concurrency,
-        )
-        self.client.socket_mode_request_listeners.append(self.handle)  # type: ignore[arg-type]
-
-    def handle(self, client: SocketModeClient, req: SocketModeRequest) -> None:  # type: ignore[override]
-        start = time()
-        bolt_resp: BoltResponse = run_bolt_app(self.app, req)
-        send_response(client, req, bolt_resp, start)
-
-

Socket Mode adapter for Bolt apps

-

Args

-
-
app
-
The Bolt app
-
app_token
-
App-level token starting with xapp-
-
logger
-
Custom logger
-
web_client
-
custom slack_sdk.web.WebClient instance
-
proxy
-
HTTP proxy URL
-
proxy_headers
-
Additional request header for proxy connections
-
auto_reconnect_enabled
-
True if the auto-reconnect logic works
-
trace_enabled
-
True if trace-level logging is enabled
-
all_message_trace_enabled
-
True if trace-logging for all received WebSocket messages is enabled
-
ping_pong_trace_enabled
-
True if trace-logging for all ping-pong communications
-
ping_interval
-
The ping-pong internal (seconds)
-
receive_buffer_size
-
The data length for a single socket recv operation
-
concurrency
-
The size of the underlying thread pool
-
-

Ancestors

- -

Class variables

-
-
var app_token : str
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/socket_mode/internals.html b/docs/reference/adapter/socket_mode/internals.html deleted file mode 100644 index ba7d2f226..000000000 --- a/docs/reference/adapter/socket_mode/internals.html +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - -slack_bolt.adapter.socket_mode.internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.socket_mode.internals

-
-
-

Internal functions

-
-
-
-
-
-
-

Functions

-
-
-def build_headers(req: slack_sdk.socket_mode.request.SocketModeRequest) ‑> Dict[str, str | Sequence[str]] | None -
-
-
- -Expand source code - -
def build_headers(req: SocketModeRequest) -> Optional[Dict[str, Union[str, Sequence[str]]]]:
-    # Mirror the HTTP mode retry headers so middleware/listeners can detect Events API retries
-    headers: Dict[str, Union[str, Sequence[str]]] = {}
-    if req.retry_attempt is not None:
-        headers["x-slack-retry-num"] = str(req.retry_attempt)
-    if req.retry_reason is not None:
-        headers["x-slack-retry-reason"] = req.retry_reason
-    return headers or None
-
-
-
-
-def run_bolt_app(app: App,
req: slack_sdk.socket_mode.request.SocketModeRequest)
-
-
-
- -Expand source code - -
def run_bolt_app(app: App, req: SocketModeRequest):
-    bolt_req: BoltRequest = BoltRequest(mode="socket_mode", body=req.payload, headers=build_headers(req))
-    bolt_resp: BoltResponse = app.dispatch(bolt_req)
-    return bolt_resp
-
-
-
-
-def send_response(client: slack_sdk.socket_mode.client.BaseSocketModeClient,
req: slack_sdk.socket_mode.request.SocketModeRequest,
bolt_resp: BoltResponse,
start_time: float)
-
-
-
- -Expand source code - -
def send_response(
-    client: BaseSocketModeClient,
-    req: SocketModeRequest,
-    bolt_resp: BoltResponse,
-    start_time: float,
-):
-    if bolt_resp.status == 200:
-        content_type = bolt_resp.headers.get("content-type", [""])[0]
-        if bolt_resp.body is None or len(bolt_resp.body) == 0:
-            client.send_socket_mode_response(SocketModeResponse(envelope_id=req.envelope_id))
-        elif content_type.startswith("application/json"):
-            dict_body = json.loads(bolt_resp.body)
-            client.send_socket_mode_response(SocketModeResponse(envelope_id=req.envelope_id, payload=dict_body))
-        else:
-            client.send_socket_mode_response(
-                SocketModeResponse(envelope_id=req.envelope_id, payload={"text": bolt_resp.body})
-            )
-
-        if client.logger.level <= logging.DEBUG:
-            spent_time = int((time() - start_time) * 1000)
-            client.logger.debug(f"Response time: {spent_time} milliseconds")
-    else:
-        client.logger.info(f"Unsuccessful Bolt execution result (status: {bolt_resp.status}, body: {bolt_resp.body})")
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/socket_mode/websocket_client/index.html b/docs/reference/adapter/socket_mode/websocket_client/index.html deleted file mode 100644 index e837ef19b..000000000 --- a/docs/reference/adapter/socket_mode/websocket_client/index.html +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - -slack_bolt.adapter.socket_mode.websocket_client API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.socket_mode.websocket_client

-
-
-

websocket-client based implementation

-
-
-
-
-
-
-
-
-

Classes

-
-
-class SocketModeHandler -(app: App,
app_token: str | None = None,
logger: logging.Logger | None = None,
web_client: slack_sdk.web.client.WebClient | None = None,
ping_interval: float = 10,
concurrency: int = 10,
http_proxy_host: str | None = None,
http_proxy_port: int | None = None,
http_proxy_auth: Tuple[str, str] | None = None,
proxy_type: str | None = None,
trace_enabled: bool = False)
-
-
-
- -Expand source code - -
class SocketModeHandler(BaseSocketModeHandler):
-    app: App
-    app_token: str
-    client: SocketModeClient
-
-    def __init__(
-        self,
-        app: App,
-        app_token: Optional[str] = None,
-        logger: Optional[Logger] = None,
-        web_client: Optional[WebClient] = None,
-        ping_interval: float = 10,
-        concurrency: int = 10,
-        http_proxy_host: Optional[str] = None,
-        http_proxy_port: Optional[int] = None,
-        http_proxy_auth: Optional[Tuple[str, str]] = None,
-        proxy_type: Optional[str] = None,
-        trace_enabled: bool = False,
-    ):
-        """Socket Mode adapter for Bolt apps
-
-        Args:
-            app: The Bolt app
-            app_token: App-level token starting with `xapp-`
-            logger: Custom logger
-            web_client: custom `slack_sdk.web.WebClient` instance
-            ping_interval: The ping-pong internal (seconds)
-            concurrency: The size of the underlying thread pool
-            http_proxy_host: HTTP proxy host
-            http_proxy_port: HTTP proxy port
-            http_proxy_auth: HTTP proxy authentication (username, password)
-            proxy_type: Proxy type
-            trace_enabled: True if trace-level logging is enabled
-        """
-        self.app = app
-        self.app_token = app_token or os.environ["SLACK_APP_TOKEN"]
-        self.client = SocketModeClient(
-            app_token=self.app_token,
-            logger=logger if logger is not None else app.logger,
-            web_client=web_client if web_client is not None else app.client,
-            ping_interval=ping_interval,
-            concurrency=concurrency,
-            http_proxy_host=http_proxy_host,
-            http_proxy_port=http_proxy_port,
-            http_proxy_auth=http_proxy_auth,
-            proxy_type=proxy_type,
-            trace_enabled=trace_enabled,
-        )
-        self.client.socket_mode_request_listeners.append(self.handle)  # type: ignore[arg-type]
-
-    def handle(self, client: SocketModeClient, req: SocketModeRequest) -> None:  # type: ignore[override]
-        start = time()
-        bolt_resp: BoltResponse = run_bolt_app(self.app, req)
-        send_response(client, req, bolt_resp, start)
-
-

Socket Mode adapter for Bolt apps

-

Args

-
-
app
-
The Bolt app
-
app_token
-
App-level token starting with xapp-
-
logger
-
Custom logger
-
web_client
-
custom slack_sdk.web.WebClient instance
-
ping_interval
-
The ping-pong internal (seconds)
-
concurrency
-
The size of the underlying thread pool
-
http_proxy_host
-
HTTP proxy host
-
http_proxy_port
-
HTTP proxy port
-
http_proxy_auth
-
HTTP proxy authentication (username, password)
-
proxy_type
-
Proxy type
-
trace_enabled
-
True if trace-level logging is enabled
-
-

Ancestors

- -

Class variables

-
-
var app_token : str
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/socket_mode/websockets/index.html b/docs/reference/adapter/socket_mode/websockets/index.html deleted file mode 100644 index 7f96f0021..000000000 --- a/docs/reference/adapter/socket_mode/websockets/index.html +++ /dev/null @@ -1,245 +0,0 @@ - - - - - - -slack_bolt.adapter.socket_mode.websockets API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.socket_mode.websockets

-
-
-

websockets based implementation -/ asyncio compatible

-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSocketModeHandler -(app: AsyncApp,
app_token: str | None = None,
logger: logging.Logger | None = None,
web_client: slack_sdk.web.async_client.AsyncWebClient | None = None,
ping_interval: float = 10)
-
-
-
- -Expand source code - -
class AsyncSocketModeHandler(AsyncBaseSocketModeHandler):
-    app: AsyncApp
-    app_token: str
-    client: SocketModeClient
-
-    def __init__(
-        self,
-        app: AsyncApp,
-        app_token: Optional[str] = None,
-        logger: Optional[Logger] = None,
-        web_client: Optional[AsyncWebClient] = None,
-        ping_interval: float = 10,
-    ):
-        self.app = app
-        self.app_token = app_token or os.environ["SLACK_APP_TOKEN"]
-        self.client = SocketModeClient(
-            app_token=self.app_token,
-            logger=logger if logger is not None else app.logger,
-            web_client=web_client if web_client is not None else app.client,
-            ping_interval=ping_interval,
-        )
-        self.client.socket_mode_request_listeners.append(self.handle)  # type: ignore[arg-type]
-
-    async def handle(self, client: SocketModeClient, req: SocketModeRequest) -> None:  # type: ignore[override]
-        start = time()
-        bolt_resp: BoltResponse = await run_async_bolt_app(self.app, req)
-        await send_async_response(client, req, bolt_resp, start)
-
-
-

Ancestors

- -

Class variables

-
-
var app_token : str
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class SocketModeHandler -(app: App,
app_token: str | None = None,
logger: logging.Logger | None = None,
web_client: slack_sdk.web.async_client.AsyncWebClient | None = None,
ping_interval: float = 10)
-
-
-
- -Expand source code - -
class SocketModeHandler(AsyncBaseSocketModeHandler):
-    app: App
-    app_token: str
-    client: SocketModeClient
-
-    def __init__(
-        self,
-        app: App,
-        app_token: Optional[str] = None,
-        logger: Optional[Logger] = None,
-        web_client: Optional[AsyncWebClient] = None,
-        ping_interval: float = 10,
-    ):
-        """Socket Mode adapter for Bolt apps.
-
-        Please note that this adapter does not support proxy configuration
-        as the underlying websockets module does not support proxy-wired connections.
-        If you use proxy, consider using one of the other Socket Mode adapters.
-
-        Args:
-            app: The Bolt app
-            app_token: App-level token starting with `xapp-`
-            logger: Custom logger
-            web_client: custom `slack_sdk.web.WebClient` instance
-            ping_interval: The ping-pong internal (seconds)
-        """
-        self.app = app
-        self.app_token = app_token or os.environ["SLACK_APP_TOKEN"]
-        self.client = SocketModeClient(
-            app_token=self.app_token,
-            logger=logger if logger is not None else app.logger,
-            web_client=web_client if web_client is not None else app.client,  # type: ignore[arg-type]
-            ping_interval=ping_interval,
-        )
-        self.client.socket_mode_request_listeners.append(self.handle)  # type: ignore[arg-type]
-
-    async def handle(self, client: SocketModeClient, req: SocketModeRequest) -> None:  # type: ignore[override]
-        start = time()
-        bolt_resp: BoltResponse = run_bolt_app(self.app, req)
-        await send_async_response(client, req, bolt_resp, start)
-
-

Socket Mode adapter for Bolt apps.

-

Please note that this adapter does not support proxy configuration -as the underlying websockets module does not support proxy-wired connections. -If you use proxy, consider using one of the other Socket Mode adapters.

-

Args

-
-
app
-
The Bolt app
-
app_token
-
App-level token starting with xapp-
-
logger
-
Custom logger
-
web_client
-
custom slack_sdk.web.WebClient instance
-
ping_interval
-
The ping-pong internal (seconds)
-
-

Ancestors

- -

Class variables

-
-
var app_token : str
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/adapter/starlette/async_handler.html b/docs/reference/adapter/starlette/async_handler.html deleted file mode 100644 index 91345eba3..000000000 --- a/docs/reference/adapter/starlette/async_handler.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - -slack_bolt.adapter.starlette.async_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.starlette.async_handler

-
-
-
-
-
-
-
-
-

Functions

-
-
-def to_async_bolt_request(req: starlette.requests.Request,
body: bytes,
addition_context_properties: Dict[str, Any] | None = None) ‑> AsyncBoltRequest
-
-
-
- -Expand source code - -
def to_async_bolt_request(
-    req: Request,
-    body: bytes,
-    addition_context_properties: Optional[Dict[str, Any]] = None,
-) -> AsyncBoltRequest:
-    request = AsyncBoltRequest(
-        body=body.decode("utf-8"),
-        query=req.query_params,  # type: ignore[arg-type]
-        headers=req.headers,  # type: ignore[arg-type]
-    )
-    if addition_context_properties is not None:
-        for k, v in addition_context_properties.items():
-            request.context[k] = v
-    return request
-
-
-
-
-def to_starlette_response(bolt_resp: BoltResponse) ‑> starlette.responses.Response -
-
-
- -Expand source code - -
def to_starlette_response(bolt_resp: BoltResponse) -> Response:
-    resp = Response(
-        status_code=bolt_resp.status,
-        content=bolt_resp.body,
-        headers=bolt_resp.first_headers_without_set_cookie(),
-    )
-    for cookie in bolt_resp.cookies():
-        for name, c in cookie.items():
-            resp.set_cookie(
-                key=name,
-                value=c.value,
-                max_age=c.get("max-age"),
-                expires=c.get("expires"),
-                path=c.get("path"),
-                domain=c.get("domain"),
-                secure=True,
-                httponly=True,
-            )
-    return resp
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSlackRequestHandler -(app: AsyncApp) -
-
-
- -Expand source code - -
class AsyncSlackRequestHandler:
-    def __init__(self, app: AsyncApp):
-        self.app = app
-
-    async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> Response:
-        body = await req.body()
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: AsyncOAuthFlow = self.app.oauth_flow
-                if req.url.path == oauth_flow.install_path:
-                    bolt_resp = await oauth_flow.handle_installation(
-                        to_async_bolt_request(req, body, addition_context_properties)
-                    )
-                    return to_starlette_response(bolt_resp)
-                elif req.url.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = await oauth_flow.handle_callback(
-                        to_async_bolt_request(req, body, addition_context_properties)
-                    )
-                    return to_starlette_response(bolt_resp)
-        elif req.method == "POST":
-            bolt_resp = await self.app.async_dispatch(to_async_bolt_request(req, body, addition_context_properties))
-            return to_starlette_response(bolt_resp)
-
-        return Response(
-            status_code=404,
-            content="Not found",
-        )
-
-
-

Methods

-
-
-async def handle(self,
req: starlette.requests.Request,
addition_context_properties: Dict[str, Any] | None = None) ‑> starlette.responses.Response
-
-
-
- -Expand source code - -
async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> Response:
-    body = await req.body()
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: AsyncOAuthFlow = self.app.oauth_flow
-            if req.url.path == oauth_flow.install_path:
-                bolt_resp = await oauth_flow.handle_installation(
-                    to_async_bolt_request(req, body, addition_context_properties)
-                )
-                return to_starlette_response(bolt_resp)
-            elif req.url.path == oauth_flow.redirect_uri_path:
-                bolt_resp = await oauth_flow.handle_callback(
-                    to_async_bolt_request(req, body, addition_context_properties)
-                )
-                return to_starlette_response(bolt_resp)
-    elif req.method == "POST":
-        bolt_resp = await self.app.async_dispatch(to_async_bolt_request(req, body, addition_context_properties))
-        return to_starlette_response(bolt_resp)
-
-    return Response(
-        status_code=404,
-        content="Not found",
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/starlette/handler.html b/docs/reference/adapter/starlette/handler.html deleted file mode 100644 index 5c74b71da..000000000 --- a/docs/reference/adapter/starlette/handler.html +++ /dev/null @@ -1,211 +0,0 @@ - - - - - - -slack_bolt.adapter.starlette.handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.starlette.handler

-
-
-
-
-
-
-
-
-

Functions

-
-
-def to_bolt_request(req: starlette.requests.Request,
body: bytes,
addition_context_properties: Dict[str, Any] | None = None) ‑> BoltRequest
-
-
-
- -Expand source code - -
def to_bolt_request(
-    req: Request,
-    body: bytes,
-    addition_context_properties: Optional[Dict[str, Any]] = None,
-) -> BoltRequest:
-    request = BoltRequest(
-        body=body.decode("utf-8"),
-        query=req.query_params,  # type: ignore[arg-type]
-        headers=req.headers,  # type: ignore[arg-type]
-    )
-    if addition_context_properties is not None:
-        for k, v in addition_context_properties.items():
-            request.context[k] = v
-    return request
-
-
-
-
-def to_starlette_response(bolt_resp: BoltResponse) ‑> starlette.responses.Response -
-
-
- -Expand source code - -
def to_starlette_response(bolt_resp: BoltResponse) -> Response:
-    resp = Response(
-        status_code=bolt_resp.status,
-        content=bolt_resp.body,
-        headers=bolt_resp.first_headers_without_set_cookie(),
-    )
-    for cookie in bolt_resp.cookies():
-        for name, c in cookie.items():
-            resp.set_cookie(
-                key=name,
-                value=c.value,
-                max_age=c.get("max-age"),
-                expires=c.get("expires"),
-                path=c.get("path"),
-                domain=c.get("domain"),
-                secure=True,
-                httponly=True,
-            )
-    return resp
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-
-    async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> Response:
-        body = await req.body()
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                if req.url.path == oauth_flow.install_path:
-                    bolt_resp = oauth_flow.handle_installation(to_bolt_request(req, body, addition_context_properties))
-                    return to_starlette_response(bolt_resp)
-                elif req.url.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = oauth_flow.handle_callback(to_bolt_request(req, body, addition_context_properties))
-                    return to_starlette_response(bolt_resp)
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(to_bolt_request(req, body, addition_context_properties))
-            return to_starlette_response(bolt_resp)
-
-        return Response(
-            status_code=404,
-            content="Not found",
-        )
-
-
-

Methods

-
-
-async def handle(self,
req: starlette.requests.Request,
addition_context_properties: Dict[str, Any] | None = None) ‑> starlette.responses.Response
-
-
-
- -Expand source code - -
async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> Response:
-    body = await req.body()
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if req.url.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(to_bolt_request(req, body, addition_context_properties))
-                return to_starlette_response(bolt_resp)
-            elif req.url.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(to_bolt_request(req, body, addition_context_properties))
-                return to_starlette_response(bolt_resp)
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(to_bolt_request(req, body, addition_context_properties))
-        return to_starlette_response(bolt_resp)
-
-    return Response(
-        status_code=404,
-        content="Not found",
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/starlette/index.html b/docs/reference/adapter/starlette/index.html deleted file mode 100644 index bdf5bf42a..000000000 --- a/docs/reference/adapter/starlette/index.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - -slack_bolt.adapter.starlette API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.starlette

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.starlette.async_handler
-
-
-
-
slack_bolt.adapter.starlette.handler
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App) -
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App):
-        self.app = app
-
-    async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> Response:
-        body = await req.body()
-        if req.method == "GET":
-            if self.app.oauth_flow is not None:
-                oauth_flow: OAuthFlow = self.app.oauth_flow
-                if req.url.path == oauth_flow.install_path:
-                    bolt_resp = oauth_flow.handle_installation(to_bolt_request(req, body, addition_context_properties))
-                    return to_starlette_response(bolt_resp)
-                elif req.url.path == oauth_flow.redirect_uri_path:
-                    bolt_resp = oauth_flow.handle_callback(to_bolt_request(req, body, addition_context_properties))
-                    return to_starlette_response(bolt_resp)
-        elif req.method == "POST":
-            bolt_resp = self.app.dispatch(to_bolt_request(req, body, addition_context_properties))
-            return to_starlette_response(bolt_resp)
-
-        return Response(
-            status_code=404,
-            content="Not found",
-        )
-
-
-

Methods

-
-
-async def handle(self,
req: starlette.requests.Request,
addition_context_properties: Dict[str, Any] | None = None) ‑> starlette.responses.Response
-
-
-
- -Expand source code - -
async def handle(self, req: Request, addition_context_properties: Optional[Dict[str, Any]] = None) -> Response:
-    body = await req.body()
-    if req.method == "GET":
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if req.url.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(to_bolt_request(req, body, addition_context_properties))
-                return to_starlette_response(bolt_resp)
-            elif req.url.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(to_bolt_request(req, body, addition_context_properties))
-                return to_starlette_response(bolt_resp)
-    elif req.method == "POST":
-        bolt_resp = self.app.dispatch(to_bolt_request(req, body, addition_context_properties))
-        return to_starlette_response(bolt_resp)
-
-    return Response(
-        status_code=404,
-        content="Not found",
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/tornado/async_handler.html b/docs/reference/adapter/tornado/async_handler.html deleted file mode 100644 index c274429de..000000000 --- a/docs/reference/adapter/tornado/async_handler.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - -slack_bolt.adapter.tornado.async_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.tornado.async_handler

-
-
-
-
-
-
-
-
-

Functions

-
-
-def to_async_bolt_request(req: tornado.httputil.HTTPServerRequest) ‑> AsyncBoltRequest -
-
-
- -Expand source code - -
def to_async_bolt_request(req: HTTPServerRequest) -> AsyncBoltRequest:
-    return AsyncBoltRequest(
-        body=req.body.decode("utf-8") if req.body else "",
-        query=req.query,
-        headers=req.headers,  # type: ignore[arg-type]
-    )
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSlackEventsHandler -(application: Application,
request: tornado.httputil.HTTPServerRequest,
**kwargs: Any)
-
-
-
- -Expand source code - -
class AsyncSlackEventsHandler(RequestHandler):
-    def initialize(self, app: AsyncApp):
-        self.app = app
-
-    async def post(self):
-        bolt_resp: BoltResponse = await self.app.async_dispatch(to_async_bolt_request(self.request))
-        set_response(self, bolt_resp)
-        return
-
-

Base class for HTTP request handlers.

-

Subclasses must define at least one of the methods defined in the -"Entry points" section below.

-

Applications should not construct RequestHandler objects -directly and subclasses should not override __init__ (override -~RequestHandler.initialize instead).

-

Ancestors

-
    -
  • tornado.web.RequestHandler
  • -
-

Methods

-
-
-def initialize(self,
app: AsyncApp)
-
-
-
- -Expand source code - -
def initialize(self, app: AsyncApp):
-    self.app = app
-
-
-
-
-async def post(self) -
-
-
- -Expand source code - -
async def post(self):
-    bolt_resp: BoltResponse = await self.app.async_dispatch(to_async_bolt_request(self.request))
-    set_response(self, bolt_resp)
-    return
-
-
-
-
-
-
-class AsyncSlackOAuthHandler -(application: Application,
request: tornado.httputil.HTTPServerRequest,
**kwargs: Any)
-
-
-
- -Expand source code - -
class AsyncSlackOAuthHandler(RequestHandler):
-    def initialize(self, app: AsyncApp):
-        self.app = app
-
-    async def get(self):
-        if self.app.oauth_flow is not None:
-            oauth_flow: AsyncOAuthFlow = self.app.oauth_flow
-            if self.request.path == oauth_flow.install_path:
-                bolt_resp = await oauth_flow.handle_installation(to_async_bolt_request(self.request))
-                set_response(self, bolt_resp)
-                return
-            elif self.request.path == oauth_flow.redirect_uri_path:
-                bolt_resp = await oauth_flow.handle_callback(to_async_bolt_request(self.request))
-                set_response(self, bolt_resp)
-                return
-        self.set_status(404)
-
-

Base class for HTTP request handlers.

-

Subclasses must define at least one of the methods defined in the -"Entry points" section below.

-

Applications should not construct RequestHandler objects -directly and subclasses should not override __init__ (override -~RequestHandler.initialize instead).

-

Ancestors

-
    -
  • tornado.web.RequestHandler
  • -
-

Methods

-
-
-async def get(self) -
-
-
- -Expand source code - -
async def get(self):
-    if self.app.oauth_flow is not None:
-        oauth_flow: AsyncOAuthFlow = self.app.oauth_flow
-        if self.request.path == oauth_flow.install_path:
-            bolt_resp = await oauth_flow.handle_installation(to_async_bolt_request(self.request))
-            set_response(self, bolt_resp)
-            return
-        elif self.request.path == oauth_flow.redirect_uri_path:
-            bolt_resp = await oauth_flow.handle_callback(to_async_bolt_request(self.request))
-            set_response(self, bolt_resp)
-            return
-    self.set_status(404)
-
-
-
-
-def initialize(self,
app: AsyncApp)
-
-
-
- -Expand source code - -
def initialize(self, app: AsyncApp):
-    self.app = app
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/tornado/handler.html b/docs/reference/adapter/tornado/handler.html deleted file mode 100644 index a69adb987..000000000 --- a/docs/reference/adapter/tornado/handler.html +++ /dev/null @@ -1,279 +0,0 @@ - - - - - - -slack_bolt.adapter.tornado.handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.tornado.handler

-
-
-
-
-
-
-
-
-

Functions

-
-
-def set_response(self, bolt_resp) ‑> None -
-
-
- -Expand source code - -
def set_response(self, bolt_resp) -> None:
-    self.set_status(bolt_resp.status)
-    self.write(bolt_resp.body)
-    for name, value in bolt_resp.first_headers_without_set_cookie().items():
-        self.set_header(name, value)
-    for cookie in bolt_resp.cookies():
-        for name, c in cookie.items():
-            expire_value = c.get("expires")
-            expire = datetime.strptime(expire_value, "%a, %d %b %Y %H:%M:%S %Z") if expire_value else None
-            self.set_cookie(
-                name=name,
-                value=c.value,
-                max_age=c.get("max-age"),
-                expires=expire,
-                path=c.get("path"),
-                domain=c.get("domain"),
-                secure=True,
-                httponly=True,
-            )
-
-
-
-
-def to_bolt_request(req: tornado.httputil.HTTPServerRequest) ‑> BoltRequest -
-
-
- -Expand source code - -
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,  # type: ignore[arg-type]
-    )
-
-
-
-
-
-
-

Classes

-
-
-class SlackEventsHandler -(application: Application,
request: tornado.httputil.HTTPServerRequest,
**kwargs: Any)
-
-
-
- -Expand source code - -
class SlackEventsHandler(RequestHandler):
-    def initialize(self, app: App):
-        self.app = app
-
-    def post(self):
-        bolt_resp: BoltResponse = self.app.dispatch(to_bolt_request(self.request))
-        set_response(self, bolt_resp)
-        return
-
-

Base class for HTTP request handlers.

-

Subclasses must define at least one of the methods defined in the -"Entry points" section below.

-

Applications should not construct RequestHandler objects -directly and subclasses should not override __init__ (override -~RequestHandler.initialize instead).

-

Ancestors

-
    -
  • tornado.web.RequestHandler
  • -
-

Methods

-
-
-def initialize(self,
app: App)
-
-
-
- -Expand source code - -
def initialize(self, app: App):
-    self.app = app
-
-
-
-
-def post(self) -
-
-
- -Expand source code - -
def post(self):
-    bolt_resp: BoltResponse = self.app.dispatch(to_bolt_request(self.request))
-    set_response(self, bolt_resp)
-    return
-
-
-
-
-
-
-class SlackOAuthHandler -(application: Application,
request: tornado.httputil.HTTPServerRequest,
**kwargs: Any)
-
-
-
- -Expand source code - -
class SlackOAuthHandler(RequestHandler):
-    def initialize(self, app: App):
-        self.app = app
-
-    def get(self):
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if self.request.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(to_bolt_request(self.request))
-                set_response(self, bolt_resp)
-                return
-            elif self.request.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(to_bolt_request(self.request))
-                set_response(self, bolt_resp)
-                return
-        self.set_status(404)
-
-

Base class for HTTP request handlers.

-

Subclasses must define at least one of the methods defined in the -"Entry points" section below.

-

Applications should not construct RequestHandler objects -directly and subclasses should not override __init__ (override -~RequestHandler.initialize instead).

-

Ancestors

-
    -
  • tornado.web.RequestHandler
  • -
-

Methods

-
-
-def get(self) -
-
-
- -Expand source code - -
def get(self):
-    if self.app.oauth_flow is not None:
-        oauth_flow: OAuthFlow = self.app.oauth_flow
-        if self.request.path == oauth_flow.install_path:
-            bolt_resp = oauth_flow.handle_installation(to_bolt_request(self.request))
-            set_response(self, bolt_resp)
-            return
-        elif self.request.path == oauth_flow.redirect_uri_path:
-            bolt_resp = oauth_flow.handle_callback(to_bolt_request(self.request))
-            set_response(self, bolt_resp)
-            return
-    self.set_status(404)
-
-
-
-
-def initialize(self,
app: App)
-
-
-
- -Expand source code - -
def initialize(self, app: App):
-    self.app = app
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/tornado/index.html b/docs/reference/adapter/tornado/index.html deleted file mode 100644 index a5bec4ffb..000000000 --- a/docs/reference/adapter/tornado/index.html +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - -slack_bolt.adapter.tornado API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.tornado

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.tornado.async_handler
-
-
-
-
slack_bolt.adapter.tornado.handler
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackEventsHandler -(application: Application,
request: tornado.httputil.HTTPServerRequest,
**kwargs: Any)
-
-
-
- -Expand source code - -
class SlackEventsHandler(RequestHandler):
-    def initialize(self, app: App):
-        self.app = app
-
-    def post(self):
-        bolt_resp: BoltResponse = self.app.dispatch(to_bolt_request(self.request))
-        set_response(self, bolt_resp)
-        return
-
-

Base class for HTTP request handlers.

-

Subclasses must define at least one of the methods defined in the -"Entry points" section below.

-

Applications should not construct RequestHandler objects -directly and subclasses should not override __init__ (override -~RequestHandler.initialize instead).

-

Ancestors

-
    -
  • tornado.web.RequestHandler
  • -
-

Methods

-
-
-def initialize(self,
app: App)
-
-
-
- -Expand source code - -
def initialize(self, app: App):
-    self.app = app
-
-
-
-
-def post(self) -
-
-
- -Expand source code - -
def post(self):
-    bolt_resp: BoltResponse = self.app.dispatch(to_bolt_request(self.request))
-    set_response(self, bolt_resp)
-    return
-
-
-
-
-
-
-class SlackOAuthHandler -(application: Application,
request: tornado.httputil.HTTPServerRequest,
**kwargs: Any)
-
-
-
- -Expand source code - -
class SlackOAuthHandler(RequestHandler):
-    def initialize(self, app: App):
-        self.app = app
-
-    def get(self):
-        if self.app.oauth_flow is not None:
-            oauth_flow: OAuthFlow = self.app.oauth_flow
-            if self.request.path == oauth_flow.install_path:
-                bolt_resp = oauth_flow.handle_installation(to_bolt_request(self.request))
-                set_response(self, bolt_resp)
-                return
-            elif self.request.path == oauth_flow.redirect_uri_path:
-                bolt_resp = oauth_flow.handle_callback(to_bolt_request(self.request))
-                set_response(self, bolt_resp)
-                return
-        self.set_status(404)
-
-

Base class for HTTP request handlers.

-

Subclasses must define at least one of the methods defined in the -"Entry points" section below.

-

Applications should not construct RequestHandler objects -directly and subclasses should not override __init__ (override -~RequestHandler.initialize instead).

-

Ancestors

-
    -
  • tornado.web.RequestHandler
  • -
-

Methods

-
-
-def get(self) -
-
-
- -Expand source code - -
def get(self):
-    if self.app.oauth_flow is not None:
-        oauth_flow: OAuthFlow = self.app.oauth_flow
-        if self.request.path == oauth_flow.install_path:
-            bolt_resp = oauth_flow.handle_installation(to_bolt_request(self.request))
-            set_response(self, bolt_resp)
-            return
-        elif self.request.path == oauth_flow.redirect_uri_path:
-            bolt_resp = oauth_flow.handle_callback(to_bolt_request(self.request))
-            set_response(self, bolt_resp)
-            return
-    self.set_status(404)
-
-
-
-
-def initialize(self,
app: App)
-
-
-
- -Expand source code - -
def initialize(self, app: App):
-    self.app = app
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/wsgi/handler.html b/docs/reference/adapter/wsgi/handler.html deleted file mode 100644 index a6ea85ca4..000000000 --- a/docs/reference/adapter/wsgi/handler.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - -slack_bolt.adapter.wsgi.handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.wsgi.handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App,
path: str = '/slack/events')
-
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App, path: str = "/slack/events"):
-        """Setup Bolt as a WSGI web framework, this will make your application compatible with WSGI web servers.
-        This can be used for production deployments.
-
-        With the default settings, `http://localhost:3000/slack/events`
-        Run Bolt with [gunicorn](https://gunicorn.org/)
-
-        # Python
-            app = App()
-
-            api = SlackRequestHandler(app)
-
-        # bash
-            export SLACK_SIGNING_SECRET=***
-
-            export SLACK_BOT_TOKEN=xoxb-***
-
-            gunicorn app:api -b 0.0.0.0:3000 --log-level debug
-
-        Args:
-            app: Your bolt application
-            path: The path to handle request from Slack (Default: `/slack/events`)
-        """
-        self.path = path
-        self.app = app
-
-    def dispatch(self, request: WsgiHttpRequest) -> BoltResponse:
-        return self.app.dispatch(
-            BoltRequest(body=request.get_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    def handle_installation(self, request: WsgiHttpRequest) -> BoltResponse:
-        return self.app.oauth_flow.handle_installation(  # type: ignore[union-attr]
-            BoltRequest(body=request.get_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    def handle_callback(self, request: WsgiHttpRequest) -> BoltResponse:
-        return self.app.oauth_flow.handle_callback(  # type: ignore[union-attr]
-            BoltRequest(body=request.get_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    def _get_http_response(self, request: WsgiHttpRequest) -> WsgiHttpResponse:
-        if request.method == "GET":
-            if self.app.oauth_flow is not None:
-                if request.path == self.app.oauth_flow.install_path:
-                    bolt_response = self.handle_installation(request)
-                    return WsgiHttpResponse(
-                        status=bolt_response.status, headers=bolt_response.headers, body=bolt_response.body
-                    )
-                elif request.path == self.app.oauth_flow.redirect_uri_path:
-                    bolt_response = self.handle_callback(request)
-                    return WsgiHttpResponse(
-                        status=bolt_response.status, headers=bolt_response.headers, body=bolt_response.body
-                    )
-        if request.method == "POST" and request.path == self.path:
-            bolt_response = self.dispatch(request)
-            return WsgiHttpResponse(status=bolt_response.status, headers=bolt_response.headers, body=bolt_response.body)
-        return WsgiHttpResponse(status=404, headers={"content-type": ["text/plain;charset=utf-8"]}, body="Not Found")
-
-    def __call__(
-        self,
-        environ: "WSGIEnvironment",
-        start_response: "StartResponse",
-    ) -> Iterable[bytes]:
-        request = WsgiHttpRequest(environ)
-        if request.protocol.startswith("HTTP"):
-            response: WsgiHttpResponse = self._get_http_response(
-                request=request,
-            )
-        else:
-            response = WsgiHttpResponse(
-                status=400, headers={"content-type": ["text/plain;charset=utf-8"]}, body="Bad Request"
-            )
-        start_response(response.status, response.get_headers())
-        return response.get_body()
-
-

Setup Bolt as a WSGI web framework, this will make your application compatible with WSGI web servers. -This can be used for production deployments.

-

With the default settings, http://localhost:3000/slack/events -Run Bolt with gunicorn

-

Python

-
app = App()
-
-api = SlackRequestHandler(app)
-
-

bash

-
export SLACK_SIGNING_SECRET=***
-
-export SLACK_BOT_TOKEN=xoxb-***
-
-gunicorn app:api -b 0.0.0.0:3000 --log-level debug
-
-

Args

-
-
app
-
Your bolt application
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
-

Methods

-
-
-def dispatch(self,
request: WsgiHttpRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def dispatch(self, request: WsgiHttpRequest) -> BoltResponse:
-    return self.app.dispatch(
-        BoltRequest(body=request.get_body(), query=request.query_string, headers=request.get_headers())
-    )
-
-
-
-
-def handle_callback(self,
request: WsgiHttpRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def handle_callback(self, request: WsgiHttpRequest) -> BoltResponse:
-    return self.app.oauth_flow.handle_callback(  # type: ignore[union-attr]
-        BoltRequest(body=request.get_body(), query=request.query_string, headers=request.get_headers())
-    )
-
-
-
-
-def handle_installation(self,
request: WsgiHttpRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def handle_installation(self, request: WsgiHttpRequest) -> BoltResponse:
-    return self.app.oauth_flow.handle_installation(  # type: ignore[union-attr]
-        BoltRequest(body=request.get_body(), query=request.query_string, headers=request.get_headers())
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/wsgi/http_request.html b/docs/reference/adapter/wsgi/http_request.html deleted file mode 100644 index 72c5f28be..000000000 --- a/docs/reference/adapter/wsgi/http_request.html +++ /dev/null @@ -1,379 +0,0 @@ - - - - - - -slack_bolt.adapter.wsgi.http_request API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.wsgi.http_request

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class WsgiHttpRequest -(environ: WSGIEnvironment) -
-
-
- -Expand source code - -
class WsgiHttpRequest:
-    """This Class uses the PEP 3333 standard to extract request information
-    from the WSGI web server running the application
-
-    PEP 3333: https://peps.python.org/pep-3333/
-    """
-
-    __slots__ = ("method", "path", "query_string", "protocol", "environ")
-
-    def __init__(self, environ: "WSGIEnvironment"):
-        self.method: str = environ.get("REQUEST_METHOD", "GET")
-        self.path: str = environ.get("PATH_INFO", "")
-        self.query_string: str = environ.get("QUERY_STRING", "")
-        self.protocol: str = environ.get("SERVER_PROTOCOL", "")
-        self.environ = environ
-
-    def get_headers(self) -> Dict[str, Union[str, Sequence[str]]]:
-        headers = {}
-        for key, value in self.environ.items():
-            if key in {"CONTENT_LENGTH", "CONTENT_TYPE"}:
-                name = key.lower().replace("_", "-")
-                headers[name] = value
-            if key.startswith("HTTP_"):
-                name = key[len("HTTP_"):].lower().replace("_", "-")  # fmt: skip
-                headers[name] = value
-        return headers
-
-    def get_body(self) -> str:
-        if "wsgi.input" not in self.environ:
-            return ""
-        content_length = int(self.environ.get("CONTENT_LENGTH") or 0)
-        return self.environ["wsgi.input"].read(content_length).decode(ENCODING)
-
-

This Class uses the PEP 3333 standard to extract request information -from the WSGI web server running the application

-

PEP 3333: https://peps.python.org/pep-3333/

-

Instance variables

-
-
var environ
-
-
- -Expand source code - -
class WsgiHttpRequest:
-    """This Class uses the PEP 3333 standard to extract request information
-    from the WSGI web server running the application
-
-    PEP 3333: https://peps.python.org/pep-3333/
-    """
-
-    __slots__ = ("method", "path", "query_string", "protocol", "environ")
-
-    def __init__(self, environ: "WSGIEnvironment"):
-        self.method: str = environ.get("REQUEST_METHOD", "GET")
-        self.path: str = environ.get("PATH_INFO", "")
-        self.query_string: str = environ.get("QUERY_STRING", "")
-        self.protocol: str = environ.get("SERVER_PROTOCOL", "")
-        self.environ = environ
-
-    def get_headers(self) -> Dict[str, Union[str, Sequence[str]]]:
-        headers = {}
-        for key, value in self.environ.items():
-            if key in {"CONTENT_LENGTH", "CONTENT_TYPE"}:
-                name = key.lower().replace("_", "-")
-                headers[name] = value
-            if key.startswith("HTTP_"):
-                name = key[len("HTTP_"):].lower().replace("_", "-")  # fmt: skip
-                headers[name] = value
-        return headers
-
-    def get_body(self) -> str:
-        if "wsgi.input" not in self.environ:
-            return ""
-        content_length = int(self.environ.get("CONTENT_LENGTH") or 0)
-        return self.environ["wsgi.input"].read(content_length).decode(ENCODING)
-
-
-
-
var method
-
-
- -Expand source code - -
class WsgiHttpRequest:
-    """This Class uses the PEP 3333 standard to extract request information
-    from the WSGI web server running the application
-
-    PEP 3333: https://peps.python.org/pep-3333/
-    """
-
-    __slots__ = ("method", "path", "query_string", "protocol", "environ")
-
-    def __init__(self, environ: "WSGIEnvironment"):
-        self.method: str = environ.get("REQUEST_METHOD", "GET")
-        self.path: str = environ.get("PATH_INFO", "")
-        self.query_string: str = environ.get("QUERY_STRING", "")
-        self.protocol: str = environ.get("SERVER_PROTOCOL", "")
-        self.environ = environ
-
-    def get_headers(self) -> Dict[str, Union[str, Sequence[str]]]:
-        headers = {}
-        for key, value in self.environ.items():
-            if key in {"CONTENT_LENGTH", "CONTENT_TYPE"}:
-                name = key.lower().replace("_", "-")
-                headers[name] = value
-            if key.startswith("HTTP_"):
-                name = key[len("HTTP_"):].lower().replace("_", "-")  # fmt: skip
-                headers[name] = value
-        return headers
-
-    def get_body(self) -> str:
-        if "wsgi.input" not in self.environ:
-            return ""
-        content_length = int(self.environ.get("CONTENT_LENGTH") or 0)
-        return self.environ["wsgi.input"].read(content_length).decode(ENCODING)
-
-
-
-
var path
-
-
- -Expand source code - -
class WsgiHttpRequest:
-    """This Class uses the PEP 3333 standard to extract request information
-    from the WSGI web server running the application
-
-    PEP 3333: https://peps.python.org/pep-3333/
-    """
-
-    __slots__ = ("method", "path", "query_string", "protocol", "environ")
-
-    def __init__(self, environ: "WSGIEnvironment"):
-        self.method: str = environ.get("REQUEST_METHOD", "GET")
-        self.path: str = environ.get("PATH_INFO", "")
-        self.query_string: str = environ.get("QUERY_STRING", "")
-        self.protocol: str = environ.get("SERVER_PROTOCOL", "")
-        self.environ = environ
-
-    def get_headers(self) -> Dict[str, Union[str, Sequence[str]]]:
-        headers = {}
-        for key, value in self.environ.items():
-            if key in {"CONTENT_LENGTH", "CONTENT_TYPE"}:
-                name = key.lower().replace("_", "-")
-                headers[name] = value
-            if key.startswith("HTTP_"):
-                name = key[len("HTTP_"):].lower().replace("_", "-")  # fmt: skip
-                headers[name] = value
-        return headers
-
-    def get_body(self) -> str:
-        if "wsgi.input" not in self.environ:
-            return ""
-        content_length = int(self.environ.get("CONTENT_LENGTH") or 0)
-        return self.environ["wsgi.input"].read(content_length).decode(ENCODING)
-
-
-
-
var protocol
-
-
- -Expand source code - -
class WsgiHttpRequest:
-    """This Class uses the PEP 3333 standard to extract request information
-    from the WSGI web server running the application
-
-    PEP 3333: https://peps.python.org/pep-3333/
-    """
-
-    __slots__ = ("method", "path", "query_string", "protocol", "environ")
-
-    def __init__(self, environ: "WSGIEnvironment"):
-        self.method: str = environ.get("REQUEST_METHOD", "GET")
-        self.path: str = environ.get("PATH_INFO", "")
-        self.query_string: str = environ.get("QUERY_STRING", "")
-        self.protocol: str = environ.get("SERVER_PROTOCOL", "")
-        self.environ = environ
-
-    def get_headers(self) -> Dict[str, Union[str, Sequence[str]]]:
-        headers = {}
-        for key, value in self.environ.items():
-            if key in {"CONTENT_LENGTH", "CONTENT_TYPE"}:
-                name = key.lower().replace("_", "-")
-                headers[name] = value
-            if key.startswith("HTTP_"):
-                name = key[len("HTTP_"):].lower().replace("_", "-")  # fmt: skip
-                headers[name] = value
-        return headers
-
-    def get_body(self) -> str:
-        if "wsgi.input" not in self.environ:
-            return ""
-        content_length = int(self.environ.get("CONTENT_LENGTH") or 0)
-        return self.environ["wsgi.input"].read(content_length).decode(ENCODING)
-
-
-
-
var query_string
-
-
- -Expand source code - -
class WsgiHttpRequest:
-    """This Class uses the PEP 3333 standard to extract request information
-    from the WSGI web server running the application
-
-    PEP 3333: https://peps.python.org/pep-3333/
-    """
-
-    __slots__ = ("method", "path", "query_string", "protocol", "environ")
-
-    def __init__(self, environ: "WSGIEnvironment"):
-        self.method: str = environ.get("REQUEST_METHOD", "GET")
-        self.path: str = environ.get("PATH_INFO", "")
-        self.query_string: str = environ.get("QUERY_STRING", "")
-        self.protocol: str = environ.get("SERVER_PROTOCOL", "")
-        self.environ = environ
-
-    def get_headers(self) -> Dict[str, Union[str, Sequence[str]]]:
-        headers = {}
-        for key, value in self.environ.items():
-            if key in {"CONTENT_LENGTH", "CONTENT_TYPE"}:
-                name = key.lower().replace("_", "-")
-                headers[name] = value
-            if key.startswith("HTTP_"):
-                name = key[len("HTTP_"):].lower().replace("_", "-")  # fmt: skip
-                headers[name] = value
-        return headers
-
-    def get_body(self) -> str:
-        if "wsgi.input" not in self.environ:
-            return ""
-        content_length = int(self.environ.get("CONTENT_LENGTH") or 0)
-        return self.environ["wsgi.input"].read(content_length).decode(ENCODING)
-
-
-
-
-

Methods

-
-
-def get_body(self) ‑> str -
-
-
- -Expand source code - -
def get_body(self) -> str:
-    if "wsgi.input" not in self.environ:
-        return ""
-    content_length = int(self.environ.get("CONTENT_LENGTH") or 0)
-    return self.environ["wsgi.input"].read(content_length).decode(ENCODING)
-
-
-
-
-def get_headers(self) ‑> Dict[str, str | Sequence[str]] -
-
-
- -Expand source code - -
def get_headers(self) -> Dict[str, Union[str, Sequence[str]]]:
-    headers = {}
-    for key, value in self.environ.items():
-        if key in {"CONTENT_LENGTH", "CONTENT_TYPE"}:
-            name = key.lower().replace("_", "-")
-            headers[name] = value
-        if key.startswith("HTTP_"):
-            name = key[len("HTTP_"):].lower().replace("_", "-")  # fmt: skip
-            headers[name] = value
-    return headers
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/wsgi/http_response.html b/docs/reference/adapter/wsgi/http_response.html deleted file mode 100644 index 726332c77..000000000 --- a/docs/reference/adapter/wsgi/http_response.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - -slack_bolt.adapter.wsgi.http_response API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.wsgi.http_response

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class WsgiHttpResponse -(status: int, headers: Dict[str, Sequence[str]] | None = None, body: str = '') -
-
-
- -Expand source code - -
class WsgiHttpResponse:
-    """This Class uses the PEP 3333 standard to adapt bolt response information
-    for the WSGI web server running the application
-
-    PEP 3333: https://peps.python.org/pep-3333/
-    """
-
-    __slots__ = ("status", "_headers", "_body")
-
-    def __init__(self, status: int, headers: Optional[Dict[str, Sequence[str]]] = None, body: str = ""):
-        _status = HTTPStatus(status)
-        self.status = f"{_status.value} {_status.phrase}"
-        self._headers = headers or {}
-        self._body = bytes(body, ENCODING)
-
-    def get_headers(self) -> List[Tuple[str, str]]:
-        headers: List[Tuple[str, str]] = []
-        for key, values in self._headers.items():
-            if key.lower() == "content-length":
-                continue
-            for v in values:
-                headers.append((key, v))
-
-        headers.append(("content-length", str(len(self._body))))
-        return headers
-
-    def get_body(self) -> Iterable[bytes]:
-        return [self._body]
-
-

This Class uses the PEP 3333 standard to adapt bolt response information -for the WSGI web server running the application

-

PEP 3333: https://peps.python.org/pep-3333/

-

Instance variables

-
-
var status
-
-
- -Expand source code - -
class WsgiHttpResponse:
-    """This Class uses the PEP 3333 standard to adapt bolt response information
-    for the WSGI web server running the application
-
-    PEP 3333: https://peps.python.org/pep-3333/
-    """
-
-    __slots__ = ("status", "_headers", "_body")
-
-    def __init__(self, status: int, headers: Optional[Dict[str, Sequence[str]]] = None, body: str = ""):
-        _status = HTTPStatus(status)
-        self.status = f"{_status.value} {_status.phrase}"
-        self._headers = headers or {}
-        self._body = bytes(body, ENCODING)
-
-    def get_headers(self) -> List[Tuple[str, str]]:
-        headers: List[Tuple[str, str]] = []
-        for key, values in self._headers.items():
-            if key.lower() == "content-length":
-                continue
-            for v in values:
-                headers.append((key, v))
-
-        headers.append(("content-length", str(len(self._body))))
-        return headers
-
-    def get_body(self) -> Iterable[bytes]:
-        return [self._body]
-
-
-
-
-

Methods

-
-
-def get_body(self) ‑> Iterable[bytes] -
-
-
- -Expand source code - -
def get_body(self) -> Iterable[bytes]:
-    return [self._body]
-
-
-
-
-def get_headers(self) ‑> List[Tuple[str, str]] -
-
-
- -Expand source code - -
def get_headers(self) -> List[Tuple[str, str]]:
-    headers: List[Tuple[str, str]] = []
-    for key, values in self._headers.items():
-        if key.lower() == "content-length":
-            continue
-        for v in values:
-            headers.append((key, v))
-
-    headers.append(("content-length", str(len(self._body))))
-    return headers
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/wsgi/index.html b/docs/reference/adapter/wsgi/index.html deleted file mode 100644 index 186d1adf6..000000000 --- a/docs/reference/adapter/wsgi/index.html +++ /dev/null @@ -1,266 +0,0 @@ - - - - - - -slack_bolt.adapter.wsgi API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.wsgi

-
-
-
-
-

Sub-modules

-
-
slack_bolt.adapter.wsgi.handler
-
-
-
-
slack_bolt.adapter.wsgi.http_request
-
-
-
-
slack_bolt.adapter.wsgi.http_response
-
-
-
-
slack_bolt.adapter.wsgi.internals
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SlackRequestHandler -(app: App,
path: str = '/slack/events')
-
-
-
- -Expand source code - -
class SlackRequestHandler:
-    def __init__(self, app: App, path: str = "/slack/events"):
-        """Setup Bolt as a WSGI web framework, this will make your application compatible with WSGI web servers.
-        This can be used for production deployments.
-
-        With the default settings, `http://localhost:3000/slack/events`
-        Run Bolt with [gunicorn](https://gunicorn.org/)
-
-        # Python
-            app = App()
-
-            api = SlackRequestHandler(app)
-
-        # bash
-            export SLACK_SIGNING_SECRET=***
-
-            export SLACK_BOT_TOKEN=xoxb-***
-
-            gunicorn app:api -b 0.0.0.0:3000 --log-level debug
-
-        Args:
-            app: Your bolt application
-            path: The path to handle request from Slack (Default: `/slack/events`)
-        """
-        self.path = path
-        self.app = app
-
-    def dispatch(self, request: WsgiHttpRequest) -> BoltResponse:
-        return self.app.dispatch(
-            BoltRequest(body=request.get_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    def handle_installation(self, request: WsgiHttpRequest) -> BoltResponse:
-        return self.app.oauth_flow.handle_installation(  # type: ignore[union-attr]
-            BoltRequest(body=request.get_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    def handle_callback(self, request: WsgiHttpRequest) -> BoltResponse:
-        return self.app.oauth_flow.handle_callback(  # type: ignore[union-attr]
-            BoltRequest(body=request.get_body(), query=request.query_string, headers=request.get_headers())
-        )
-
-    def _get_http_response(self, request: WsgiHttpRequest) -> WsgiHttpResponse:
-        if request.method == "GET":
-            if self.app.oauth_flow is not None:
-                if request.path == self.app.oauth_flow.install_path:
-                    bolt_response = self.handle_installation(request)
-                    return WsgiHttpResponse(
-                        status=bolt_response.status, headers=bolt_response.headers, body=bolt_response.body
-                    )
-                elif request.path == self.app.oauth_flow.redirect_uri_path:
-                    bolt_response = self.handle_callback(request)
-                    return WsgiHttpResponse(
-                        status=bolt_response.status, headers=bolt_response.headers, body=bolt_response.body
-                    )
-        if request.method == "POST" and request.path == self.path:
-            bolt_response = self.dispatch(request)
-            return WsgiHttpResponse(status=bolt_response.status, headers=bolt_response.headers, body=bolt_response.body)
-        return WsgiHttpResponse(status=404, headers={"content-type": ["text/plain;charset=utf-8"]}, body="Not Found")
-
-    def __call__(
-        self,
-        environ: "WSGIEnvironment",
-        start_response: "StartResponse",
-    ) -> Iterable[bytes]:
-        request = WsgiHttpRequest(environ)
-        if request.protocol.startswith("HTTP"):
-            response: WsgiHttpResponse = self._get_http_response(
-                request=request,
-            )
-        else:
-            response = WsgiHttpResponse(
-                status=400, headers={"content-type": ["text/plain;charset=utf-8"]}, body="Bad Request"
-            )
-        start_response(response.status, response.get_headers())
-        return response.get_body()
-
-

Setup Bolt as a WSGI web framework, this will make your application compatible with WSGI web servers. -This can be used for production deployments.

-

With the default settings, http://localhost:3000/slack/events -Run Bolt with gunicorn

-

Python

-
app = App()
-
-api = SlackRequestHandler(app)
-
-

bash

-
export SLACK_SIGNING_SECRET=***
-
-export SLACK_BOT_TOKEN=xoxb-***
-
-gunicorn app:api -b 0.0.0.0:3000 --log-level debug
-
-

Args

-
-
app
-
Your bolt application
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
-

Methods

-
-
-def dispatch(self,
request: WsgiHttpRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def dispatch(self, request: WsgiHttpRequest) -> BoltResponse:
-    return self.app.dispatch(
-        BoltRequest(body=request.get_body(), query=request.query_string, headers=request.get_headers())
-    )
-
-
-
-
-def handle_callback(self,
request: WsgiHttpRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def handle_callback(self, request: WsgiHttpRequest) -> BoltResponse:
-    return self.app.oauth_flow.handle_callback(  # type: ignore[union-attr]
-        BoltRequest(body=request.get_body(), query=request.query_string, headers=request.get_headers())
-    )
-
-
-
-
-def handle_installation(self,
request: WsgiHttpRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def handle_installation(self, request: WsgiHttpRequest) -> BoltResponse:
-    return self.app.oauth_flow.handle_installation(  # type: ignore[union-attr]
-        BoltRequest(body=request.get_body(), query=request.query_string, headers=request.get_headers())
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/adapter/wsgi/internals.html b/docs/reference/adapter/wsgi/internals.html deleted file mode 100644 index 7fdfa267f..000000000 --- a/docs/reference/adapter/wsgi/internals.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - -slack_bolt.adapter.wsgi.internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.adapter.wsgi.internals

-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/app/app.html b/docs/reference/app/app.html deleted file mode 100644 index 737597548..000000000 --- a/docs/reference/app/app.html +++ /dev/null @@ -1,3288 +0,0 @@ - - - - - - -slack_bolt.app.app API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.app.app

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class App -(*,
logger: logging.Logger | None = None,
name: str | None = None,
process_before_response: bool = False,
raise_error_for_unhandled_request: bool = False,
signing_secret: str | None = None,
token: str | None = None,
token_verification_enabled: bool = True,
client: slack_sdk.web.client.WebClient | None = None,
before_authorize: Middleware | Callable[..., Any] | None = None,
authorize: Callable[..., AuthorizeResult] | None = None,
user_facing_authorize_error_message: str | None = None,
installation_store: slack_sdk.oauth.installation_store.installation_store.InstallationStore | None = None,
installation_store_bot_only: bool | None = None,
request_verification_enabled: bool = True,
ignoring_self_events_enabled: bool = True,
ignoring_self_assistant_message_events_enabled: bool = True,
ssl_check_enabled: bool = True,
url_verification_enabled: bool = True,
attaching_function_token_enabled: bool = True,
oauth_settings: OAuthSettings | None = None,
oauth_flow: OAuthFlow | None = None,
verification_token: str | None = None,
listener_executor: concurrent.futures._base.Executor | None = None,
assistant_thread_context_store: AssistantThreadContextStore | None = None,
attaching_conversation_kwargs_enabled: bool = True)
-
-
-
- -Expand source code - -
class App:
-    def __init__(
-        self,
-        *,
-        logger: Optional[logging.Logger] = None,
-        # Used in logger
-        name: Optional[str] = None,
-        # Set True when you run this app on a FaaS platform
-        process_before_response: bool = False,
-        # Set True if you want to handle an unhandled request as an exception
-        raise_error_for_unhandled_request: bool = False,
-        # Basic Information > Credentials > Signing Secret
-        signing_secret: Optional[str] = None,
-        # for single-workspace apps
-        token: Optional[str] = None,
-        token_verification_enabled: bool = True,
-        client: Optional[WebClient] = None,
-        # for multi-workspace apps
-        before_authorize: Optional[Union[Middleware, Callable[..., Any]]] = None,
-        authorize: Optional[Callable[..., AuthorizeResult]] = None,
-        user_facing_authorize_error_message: Optional[str] = None,
-        installation_store: Optional[InstallationStore] = None,
-        # for either only bot scope usage or v1.0.x compatibility
-        installation_store_bot_only: Optional[bool] = None,
-        # for customizing the built-in middleware
-        request_verification_enabled: bool = True,
-        ignoring_self_events_enabled: bool = True,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-        ssl_check_enabled: bool = True,
-        url_verification_enabled: bool = True,
-        attaching_function_token_enabled: bool = True,
-        # for the OAuth flow
-        oauth_settings: Optional[OAuthSettings] = None,
-        oauth_flow: Optional[OAuthFlow] = None,
-        # No need to set (the value is used only in response to ssl_check requests)
-        verification_token: Optional[str] = None,
-        # Set this one only when you want to customize the executor
-        listener_executor: Optional[Executor] = None,
-        # for AI Agents & Assistants
-        assistant_thread_context_store: Optional[AssistantThreadContextStore] = None,
-        attaching_conversation_kwargs_enabled: bool = True,
-    ):
-        """Bolt App that provides functionalities to register middleware/listeners.
-
-            import os
-            from slack_bolt import App
-
-            # Initializes your app with your bot token and signing secret
-            app = App(
-                token=os.environ.get("SLACK_BOT_TOKEN"),
-                signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
-            )
-
-            # Listens to incoming messages that contain "hello"
-            @app.message("hello")
-            def message_hello(message, say):
-                # say() sends a message to the channel where the event was triggered
-                say(f"Hey there <@{message['user']}>!")
-
-            # Start your app
-            if __name__ == "__main__":
-                app.start(port=int(os.environ.get("PORT", 3000)))
-
-        Refer to https://docs.slack.dev/tools/bolt-python/creating-an-app for details.
-
-        If you would like to build an OAuth app for enabling the app to run with multiple workspaces,
-        refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app.
-
-        Args:
-            logger: The custom logger that can be used in this app.
-            name: The application name that will be used in logging. If absent, the source file name will be used.
-            process_before_response: True if this app runs on Function as a Service. (Default: False)
-            raise_error_for_unhandled_request: True if you want to raise exceptions for unhandled requests
-                and use @app.error listeners instead of
-                the built-in handler, which pints warning logs and returns 404 to Slack (Default: False)
-            signing_secret: The Signing Secret value used for verifying requests from Slack.
-            token: The bot/user access token required only for single-workspace app.
-            token_verification_enabled: Verifies the validity of the given token if True.
-            client: The singleton `slack_sdk.WebClient` instance for this app.
-            before_authorize: A global middleware that can be executed right before authorize function
-            authorize: The function to authorize an incoming request from Slack
-                by checking if there is a team/user in the installation data.
-            user_facing_authorize_error_message: The user-facing error message to display
-                when the app is installed but the installation is not managed by this app's installation store
-            installation_store: The module offering save/find operations of installation data
-            installation_store_bot_only: Use `InstallationStore#find_bot()` if True (Default: False)
-            request_verification_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `RequestVerification` is a built-in middleware that verifies the signature in HTTP Mode requests.
-                Make sure if it's safe enough when you turn a built-in middleware off.
-                We strongly recommend using RequestVerification for better security.
-                If you have a proxy that verifies request signature in front of the Bolt app,
-                it's totally fine to disable RequestVerification to avoid duplication of work.
-                Don't turn it off just for easiness of development.
-            ignoring_self_events_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `IgnoringSelfEvents` is a built-in middleware that enables Bolt apps to easily skip the events
-                generated by this app's bot user (this is useful for avoiding code error causing an infinite loop).
-            ignoring_self_assistant_message_events_enabled: False if you would like to disable the built-in middleware.
-                `IgnoringSelfEvents` for this app's bot user message events within an assistant thread
-                This is useful for avoiding code error causing an infinite loop; Default: True
-            url_verification_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `UrlVerification` is a built-in middleware that handles url_verification requests
-                that verify the endpoint for Events API in HTTP Mode requests.
-            attaching_function_token_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `AttachingFunctionToken` is a built-in middleware that injects the just-in-time workflow-execution tokens
-                when your app receives `function_executed` or interactivity events scoped to a custom step.
-            ssl_check_enabled: bool = False if you would like to disable the built-in middleware (Default: True).
-                `SslCheck` is a built-in middleware that handles ssl_check requests from Slack.
-            oauth_settings: The settings related to Slack app installation flow (OAuth flow)
-            oauth_flow: Instantiated `slack_bolt.oauth.OAuthFlow`. This is always prioritized over oauth_settings.
-            verification_token: Deprecated verification mechanism. This can be used only for ssl_check requests.
-            listener_executor: Custom executor to run background tasks. If absent, the default `ThreadPoolExecutor` will
-                be used.
-            assistant_thread_context_store: Custom AssistantThreadContext store (Default: the built-in implementation,
-                which uses a parent message's metadata to store the latest context)
-        """
-        if signing_secret is None:
-            signing_secret = os.environ.get("SLACK_SIGNING_SECRET", "")
-        token = token or os.environ.get("SLACK_BOT_TOKEN")
-
-        self._name: str = name or inspect.stack()[1].filename.split(os.path.sep)[-1]
-        self._signing_secret: str = signing_secret
-
-        self._verification_token: Optional[str] = verification_token or os.environ.get("SLACK_VERIFICATION_TOKEN", None)
-        # If a logger is explicitly passed when initializing, the logger works as the base logger.
-        # The base logger's logging settings will be propagated to all the loggers created by bolt-python.
-        self._base_logger = logger
-        # The framework logger is supposed to be used for the internal logging.
-        # Also, it's accessible via `app.logger` as the app's singleton logger.
-        self._framework_logger = logger or get_bolt_logger(App)
-        self._raise_error_for_unhandled_request = raise_error_for_unhandled_request
-
-        self._token: Optional[str] = token
-
-        if client is not None:
-            if not isinstance(client, WebClient):
-                raise BoltError(error_client_invalid_type())
-            self._client = client
-            self._token = client.token
-            if token is not None:
-                self._framework_logger.warning(warning_client_prioritized_and_token_skipped())
-        else:
-            self._client = create_web_client(
-                # NOTE: the token here can be None
-                token=token,
-                logger=self._framework_logger,
-            )
-
-        # --------------------------------------
-        # Authorize & OAuthFlow initialization
-        # --------------------------------------
-
-        self._before_authorize: Optional[Middleware] = None
-        if before_authorize is not None:
-            if callable(before_authorize):
-                self._before_authorize = CustomMiddleware(
-                    app_name=self._name,
-                    func=before_authorize,
-                    base_logger=self._framework_logger,
-                )
-            elif isinstance(before_authorize, Middleware):
-                self._before_authorize = before_authorize
-
-        self._authorize: Optional[Authorize] = None
-        if authorize is not None:
-            if isinstance(authorize, Authorize):
-                # As long as an advanced developer understands what they're doing,
-                # bolt-python should not prevent customizing authorize middleware
-                self._authorize = authorize
-            else:
-                if oauth_settings is not None or oauth_flow is not None:
-                    # If the given authorize is a simple function,
-                    # it does not work along with installation_store.
-                    raise BoltError(error_authorize_conflicts())
-                self._authorize = CallableAuthorize(logger=self._framework_logger, func=authorize)
-
-        self._installation_store: Optional[InstallationStore] = installation_store
-        if self._installation_store is not None and self._authorize is None:
-            settings = oauth_flow.settings if oauth_flow is not None else oauth_settings
-            self._authorize = InstallationStoreAuthorize(
-                installation_store=self._installation_store,
-                client_id=settings.client_id if settings is not None else None,
-                client_secret=settings.client_secret if settings is not None else None,
-                logger=self._framework_logger,
-                bot_only=installation_store_bot_only or False,
-                client=self._client,  # for proxy use cases etc.
-                user_token_resolution=(settings.user_token_resolution if settings is not None else "authed_user"),
-            )
-
-        self._oauth_flow: Optional[OAuthFlow] = None
-
-        if (
-            oauth_settings is None
-            and os.environ.get("SLACK_CLIENT_ID") is not None
-            and os.environ.get("SLACK_CLIENT_SECRET") is not None
-        ):
-            # initialize with the default settings
-            oauth_settings = OAuthSettings()
-
-            if oauth_flow is None and installation_store is None:
-                # show info-level log for avoiding confusions
-                self._framework_logger.info(info_default_oauth_settings_loaded())
-
-        if oauth_flow is not None:
-            self._oauth_flow = oauth_flow
-            installation_store = select_consistent_installation_store(
-                client_id=self._oauth_flow.client_id,
-                app_store=self._installation_store,
-                oauth_flow_store=self._oauth_flow.settings.installation_store,
-                logger=self._framework_logger,
-            )
-            self._installation_store = installation_store
-            if installation_store is not None:
-                self._oauth_flow.settings.installation_store = installation_store
-
-            if self._oauth_flow._client is None:
-                self._oauth_flow._client = self._client
-            if self._authorize is None:
-                self._authorize = self._oauth_flow.settings.authorize
-        elif oauth_settings is not None:
-            installation_store = select_consistent_installation_store(
-                client_id=oauth_settings.client_id,
-                app_store=self._installation_store,
-                oauth_flow_store=oauth_settings.installation_store,
-                logger=self._framework_logger,
-            )
-            self._installation_store = installation_store
-            if installation_store is not None:
-                oauth_settings.installation_store = installation_store
-            self._oauth_flow = OAuthFlow(client=self.client, logger=self.logger, settings=oauth_settings)
-            if self._authorize is None:
-                self._authorize = self._oauth_flow.settings.authorize
-            self._authorize.token_rotation_expiration_minutes = oauth_settings.token_rotation_expiration_minutes  # type: ignore[attr-defined] # noqa: E501
-
-        if (self._installation_store is not None or self._authorize is not None) and self._token is not None:
-            self._token = None
-            self._framework_logger.warning(warning_token_skipped())
-
-        # after setting bot_only here, __init__ cannot replace authorize function
-        if installation_store_bot_only is not None and self._oauth_flow is not None:
-            app_bot_only = installation_store_bot_only or False
-            oauth_flow_bot_only = self._oauth_flow.settings.installation_store_bot_only
-            if app_bot_only != oauth_flow_bot_only:
-                self.logger.warning(warning_bot_only_conflicts())
-                self._oauth_flow.settings.installation_store_bot_only = app_bot_only
-                self._authorize.bot_only = app_bot_only  # type: ignore[union-attr]
-
-        self._tokens_revocation_listeners: Optional[TokenRevocationListeners] = None
-        if self._installation_store is not None:
-            self._tokens_revocation_listeners = TokenRevocationListeners(self._installation_store)
-
-        # --------------------------------------
-        # Middleware Initialization
-        # --------------------------------------
-
-        self._middleware_list: List[Middleware] = []
-        self._listeners: List[Listener] = []
-
-        if listener_executor is None:
-            listener_executor = ThreadPoolExecutor(max_workers=5)
-
-        self._assistant_thread_context_store = assistant_thread_context_store
-        self._attaching_conversation_kwargs_enabled = attaching_conversation_kwargs_enabled
-
-        self._process_before_response = process_before_response
-        self._listener_runner = ThreadListenerRunner(
-            logger=self._framework_logger,
-            process_before_response=process_before_response,
-            listener_error_handler=DefaultListenerErrorHandler(logger=self._framework_logger),
-            listener_start_handler=DefaultListenerStartHandler(logger=self._framework_logger),
-            listener_completion_handler=DefaultListenerCompletionHandler(logger=self._framework_logger),
-            listener_executor=listener_executor,
-            lazy_listener_runner=ThreadLazyListenerRunner(
-                logger=self._framework_logger,
-                executor=listener_executor,
-            ),
-        )
-        self._middleware_error_handler: MiddlewareErrorHandler = DefaultMiddlewareErrorHandler(
-            logger=self._framework_logger,
-        )
-
-        self._init_middleware_list_done = False
-        self._init_middleware_list(
-            token_verification_enabled=token_verification_enabled,
-            request_verification_enabled=request_verification_enabled,
-            ignoring_self_events_enabled=ignoring_self_events_enabled,
-            ignoring_self_assistant_message_events_enabled=ignoring_self_assistant_message_events_enabled,
-            ssl_check_enabled=ssl_check_enabled,
-            url_verification_enabled=url_verification_enabled,
-            attaching_function_token_enabled=attaching_function_token_enabled,
-            user_facing_authorize_error_message=user_facing_authorize_error_message,
-        )
-
-    def _init_middleware_list(
-        self,
-        token_verification_enabled: bool = True,
-        request_verification_enabled: bool = True,
-        ignoring_self_events_enabled: bool = True,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-        ssl_check_enabled: bool = True,
-        url_verification_enabled: bool = True,
-        attaching_function_token_enabled: bool = True,
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        if self._init_middleware_list_done:
-            return
-        if ssl_check_enabled is True:
-            self._middleware_list.append(
-                SslCheck(
-                    verification_token=self._verification_token,
-                    base_logger=self._base_logger,
-                )
-            )
-        if request_verification_enabled is True:
-            self._middleware_list.append(RequestVerification(self._signing_secret, base_logger=self._base_logger))
-
-        if self._before_authorize is not None:
-            self._middleware_list.append(self._before_authorize)
-
-        # As authorize is required for making a Bolt app function, we don't offer the flag to disable this
-        if self._oauth_flow is None:
-            if self._token is not None:
-                try:
-                    auth_test_result = None
-                    if token_verification_enabled:
-                        # This API call is for eagerly validating the token
-                        auth_test_result = self._client.auth_test(token=self._token)
-                    self._middleware_list.append(
-                        SingleTeamAuthorization(
-                            auth_test_result=auth_test_result,
-                            base_logger=self._base_logger,
-                            user_facing_authorize_error_message=user_facing_authorize_error_message,
-                        )
-                    )
-                except SlackApiError as err:
-                    raise BoltError(error_auth_test_failure(err.response))
-            elif self._authorize is not None:
-                self._middleware_list.append(
-                    MultiTeamsAuthorization(
-                        authorize=self._authorize,
-                        base_logger=self._base_logger,
-                        user_facing_authorize_error_message=user_facing_authorize_error_message,
-                    )
-                )
-            else:
-                raise BoltError(error_token_required())
-        elif self._authorize is not None:
-            self._middleware_list.append(
-                MultiTeamsAuthorization(
-                    authorize=self._authorize,
-                    base_logger=self._base_logger,
-                    user_token_resolution=self._oauth_flow.settings.user_token_resolution,
-                    user_facing_authorize_error_message=user_facing_authorize_error_message,
-                )
-            )
-        else:
-            raise BoltError(error_oauth_flow_or_authorize_required())
-
-        if ignoring_self_events_enabled is True:
-            self._middleware_list.append(
-                IgnoringSelfEvents(
-                    base_logger=self._base_logger,
-                    ignoring_self_assistant_message_events_enabled=ignoring_self_assistant_message_events_enabled,
-                )
-            )
-        if url_verification_enabled is True:
-            self._middleware_list.append(UrlVerification(base_logger=self._base_logger))
-        if attaching_function_token_enabled is True:
-            self._middleware_list.append(AttachingFunctionToken())
-        self._init_middleware_list_done = True
-
-    # -------------------------
-    # accessors
-
-    @property
-    def name(self) -> str:
-        """The name of this app (default: the filename)"""
-        return self._name
-
-    @property
-    def oauth_flow(self) -> Optional[OAuthFlow]:
-        """Configured `OAuthFlow` object if exists."""
-        return self._oauth_flow
-
-    @property
-    def logger(self) -> logging.Logger:
-        """The logger this app uses."""
-        return self._framework_logger
-
-    @property
-    def client(self) -> WebClient:
-        """The singleton `slack_sdk.WebClient` instance in this app."""
-        return self._client
-
-    @property
-    def installation_store(self) -> Optional[InstallationStore]:
-        """The `slack_sdk.oauth.InstallationStore` that can be used in the `authorize` middleware."""
-        return self._installation_store
-
-    @property
-    def listener_runner(self) -> ThreadListenerRunner:
-        """The thread executor for asynchronously running listeners."""
-        return self._listener_runner
-
-    @property
-    def process_before_response(self) -> bool:
-        return self._process_before_response or False
-
-    # -------------------------
-    # standalone server
-
-    def start(
-        self,
-        port: int = 3000,
-        path: str = "/slack/events",
-        http_server_logger_enabled: bool = True,
-    ) -> None:
-        """Starts a web server for local development.
-
-            # With the default settings, `http://localhost:3000/slack/events`
-            # is available for handling incoming requests from Slack
-            app.start()
-
-        This method internally starts a Web server process built with the `http.server` module.
-        For production, consider using a production-ready WSGI server such as Gunicorn.
-
-        Args:
-            port: The port to listen on (Default: 3000)
-            path: The path to handle request from Slack (Default: `/slack/events`)
-            http_server_logger_enabled: The flag to enable http.server logging if True (Default: True)
-        """
-        self._development_server = SlackAppDevelopmentServer(
-            port=port,
-            path=path,
-            app=self,
-            oauth_flow=self.oauth_flow,
-            http_server_logger_enabled=http_server_logger_enabled,
-        )
-        self._development_server.start()
-
-    # -------------------------
-    # main dispatcher
-
-    def dispatch(self, req: BoltRequest) -> BoltResponse:
-        """Applies all middleware and dispatches an incoming request from Slack to the right code path.
-
-        Args:
-            req: An incoming request from Slack
-
-        Returns:
-            The response generated by this Bolt app
-        """
-        starting_time = time.time()
-        self._init_context(req)
-
-        resp: Optional[BoltResponse] = BoltResponse(status=200, body="")
-        middleware_state = {"next_called": False}
-
-        def middleware_next():
-            middleware_state["next_called"] = True
-
-        try:
-            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)  # type: ignore[arg-type]
-                if not middleware_state["next_called"]:
-                    if resp is None:
-                        # next() method was not called without providing the response to return to Slack
-                        # This should not be an intentional handling in usual use cases.
-                        resp = BoltResponse(status=404, body={"error": "no next() calls in middleware"})
-                        if self._raise_error_for_unhandled_request is True:
-                            try:
-                                raise BoltUnhandledRequestError(
-                                    request=req,
-                                    current_response=resp,
-                                    last_global_middleware_name=middleware.name,
-                                )
-                            except BoltUnhandledRequestError as e:
-                                self._listener_runner.listener_error_handler.handle(
-                                    error=e,
-                                    request=req,
-                                    response=resp,
-                                )
-                            return resp
-                        self._framework_logger.warning(warning_unhandled_by_global_middleware(middleware.name, req))
-                        return resp
-                    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):  # type: ignore[arg-type]
-                    # run all the middleware attached to this listener first
-                    middleware_resp, next_was_not_called = listener.run_middleware(
-                        req=req, resp=resp  # type: ignore[arg-type]
-                    )
-                    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,  # type: ignore[arg-type]
-                        listener_name=listener_name,
-                        listener=listener,
-                    )
-                    if listener_response is not None:
-                        return listener_response
-
-            if resp is None:
-                resp = BoltResponse(status=404, body={"error": "unhandled request"})
-            if self._raise_error_for_unhandled_request is True:
-                try:
-                    raise BoltUnhandledRequestError(
-                        request=req,
-                        current_response=resp,
-                    )
-                except BoltUnhandledRequestError as e:
-                    self._listener_runner.listener_error_handler.handle(
-                        error=e,
-                        request=req,
-                        response=resp,
-                    )
-                return resp
-            return self._handle_unmatched_requests(req, resp)
-        except Exception as error:
-            resp = BoltResponse(status=500, body="")
-            self._middleware_error_handler.handle(
-                error=error,
-                request=req,
-                response=resp,
-            )
-            return resp
-
-    def _handle_unmatched_requests(self, req: BoltRequest, resp: BoltResponse) -> BoltResponse:
-        self._framework_logger.warning(warning_unhandled_request(req))
-        return resp
-
-    # -------------------------
-    # middleware
-
-    def use(self, *args) -> Optional[Callable]:
-        """Registers a new global middleware to this app. This method can be used as either a decorator or a method.
-
-        Refer to `App#middleware()` method's docstring for details."""
-        return self.middleware(*args)
-
-    def middleware(self, *args) -> Optional[Callable]:
-        """Registers a new middleware to this app.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.middleware
-            def middleware_func(logger, body, next):
-                logger.info(f"request body: {body}")
-                next()
-
-            # Pass a function to this method
-            app.middleware(middleware_func)
-
-        Refer to https://docs.slack.dev/tools/bolt-python/concepts/global-middleware for details.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            *args: A function that works as a global middleware.
-        """
-        if len(args) > 0:
-            middleware_or_callable = args[0]
-            if isinstance(middleware_or_callable, Middleware):
-                middleware: Middleware = middleware_or_callable
-                self._middleware_list.append(middleware)
-                if isinstance(middleware, Assistant) and middleware.thread_context_store is not None:
-                    self._assistant_thread_context_store = middleware.thread_context_store
-            elif callable(middleware_or_callable):
-                self._middleware_list.append(
-                    CustomMiddleware(
-                        app_name=self.name,
-                        func=middleware_or_callable,
-                        base_logger=self._base_logger,
-                    )
-                )
-                return middleware_or_callable
-            else:
-                raise BoltError(f"Unexpected type for a middleware ({type(middleware_or_callable)})")
-        return None
-
-    # -------------------------
-    # AI Agents & Assistants
-
-    def assistant(self, assistant: Assistant) -> Optional[Callable]:
-        return self.middleware(assistant)
-
-    # -------------------------
-    # Workflows: Steps from apps
-
-    def step(
-        self,
-        callback_id: Union[str, Pattern, WorkflowStep, WorkflowStepBuilder],
-        edit: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-        save: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-        execute: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Registers a new step from app listener.
-
-        Unlike others, this method doesn't behave as a decorator.
-        If you want to register a step from app by a decorator, use `WorkflowStepBuilder`'s methods.
-
-            # Create a new WorkflowStep instance
-            from slack_bolt.workflows.step import WorkflowStep
-            ws = WorkflowStep(
-                callback_id="add_task",
-                edit=edit,
-                save=save,
-                execute=execute,
-            )
-            # Pass Step to set up listeners
-            app.step(ws)
-
-        Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        For further information about WorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            callback_id: The Callback ID for this step from app
-            edit: The function for displaying a modal in the Workflow Builder
-            save: The function for handling configuration in the Workflow Builder
-            execute: The function for handling the step execution
-        """
-        warnings.warn(
-            (
-                "Steps from apps for legacy workflows are now deprecated. "
-                "Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/"
-            ),
-            category=DeprecationWarning,
-        )
-        step = callback_id
-        if isinstance(callback_id, (str, Pattern)):
-            step = WorkflowStep(
-                callback_id=callback_id,
-                edit=edit,  # type: ignore[arg-type]
-                save=save,  # type: ignore[arg-type]
-                execute=execute,  # type: ignore[arg-type]
-                base_logger=self._base_logger,
-            )
-        elif isinstance(step, WorkflowStepBuilder):
-            step = step.build(base_logger=self._base_logger)
-        elif not isinstance(step, WorkflowStep):
-            raise BoltError(f"Invalid step object ({type(step)})")
-
-        self.use(WorkflowStepMiddleware(step))
-
-    # -------------------------
-    # global error handler
-
-    def error(self, func: Callable[..., Optional[BoltResponse]]) -> Callable[..., Optional[BoltResponse]]:
-        """Updates the global error handler. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.error
-            def custom_error_handler(error, body, logger):
-                logger.exception(f"Error: {error}")
-                logger.info(f"Request body: {body}")
-
-            # Pass a function to this method
-            app.error(custom_error_handler)
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            func: The function that is supposed to be executed
-                when getting an unhandled error in Bolt app.
-        """
-        self._listener_runner.listener_error_handler = CustomListenerErrorHandler(
-            logger=self._framework_logger,
-            func=func,
-        )
-        self._middleware_error_handler = CustomMiddlewareErrorHandler(
-            logger=self._framework_logger,
-            func=func,
-        )
-        return func
-
-    # -------------------------
-    # events
-
-    def event(
-        self,
-        event: Union[
-            str,
-            Pattern,
-            Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]],
-        ],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new event listener. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.event("team_join")
-            def ask_for_introduction(event, say):
-                welcome_channel_id = "C12345"
-                user_id = event["user"]
-                text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-                say(text=text, channel=welcome_channel_id)
-
-            # Pass a function to this method
-            app.event("team_join")(ask_for_introduction)
-
-        Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            event: The conditions that match a request payload.
-                If you pass a dict for this, you can have type, subtype in the constraint.
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.event(event, base_logger=self._base_logger)
-            if self._attaching_conversation_kwargs_enabled:
-                middleware.insert(0, AttachingConversationKwargs(self._assistant_thread_context_store))
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-        return __call__
-
-    def message(
-        self,
-        keyword: Union[str, Pattern] = "",
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new message event listener. This method can be used as either a decorator or a method.
-        Check the `App#event` method's docstring for details.
-
-            # Use this method as a decorator
-            @app.message(":wave:")
-            def say_hello(message, say):
-                user = message['user']
-                say(f"Hi there, <@{user}>!")
-
-            # Pass a function to this method
-            app.message(":wave:")(say_hello)
-
-        Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            keyword: The keyword to match
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-        matchers = list(matchers) if matchers else []
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            constraints = {
-                "type": "message",
-                "subtype": (
-                    # In most cases, new message events come with no subtype.
-                    None,
-                    # As of Jan 2021, most bot messages no longer have the subtype bot_message.
-                    # By contrast, messages posted using classic app's bot token still have the subtype.
-                    "bot_message",
-                    # If an end-user posts a message with "Also send to #channel" checked,
-                    # the message event comes with this subtype.
-                    "thread_broadcast",
-                    # If an end-user posts a message with attached files,
-                    # the message event comes with this subtype.
-                    "file_share",
-                ),
-            }
-            primary_matcher = builtin_matchers.message_event(
-                keyword=keyword, constraints=constraints, base_logger=self._base_logger
-            )
-            if self._attaching_conversation_kwargs_enabled:
-                middleware.insert(0, AttachingConversationKwargs(self._assistant_thread_context_store))
-            middleware.insert(0, MessageListenerMatches(keyword))
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-        return __call__
-
-    def function(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-        auto_acknowledge: bool = True,
-        ack_timeout: int = 3,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new Function listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.function("reverse")
-            def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail):
-                try:
-                    ack()
-                    string_to_reverse = inputs["stringToReverse"]
-                    complete(outputs={"reverseString": string_to_reverse[::-1]})
-                except Exception as e:
-                    fail(f"Cannot reverse string (error: {e})")
-                    raise e
-
-            # Pass a function to this method
-            app.function("reverse")(reverse_string)
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            callback_id: The callback id to identify the function
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        if auto_acknowledge is True:
-            if ack_timeout != 3:
-                self._framework_logger.warning(warning_ack_timeout_has_no_effect(callback_id, ack_timeout))
-
-        matchers = list(matchers) if matchers else []
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.function_executed(callback_id=callback_id, base_logger=self._base_logger)
-            return self._register_listener(functions, primary_matcher, matchers, middleware, auto_acknowledge, ack_timeout)
-
-        return __call__
-
-    # -------------------------
-    # slash commands
-
-    def command(
-        self,
-        command: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new slash command listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.command("/echo")
-            def repeat_text(ack, say, command):
-                # Acknowledge command request
-                ack()
-                say(f"{command['text']}")
-
-            # Pass a function to this method
-            app.command("/echo")(repeat_text)
-
-        Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            command: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.command(command, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # shortcut
-
-    def shortcut(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new shortcut listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.shortcut("open_modal")
-            def open_modal(ack, body, client):
-                # Acknowledge the command request
-                ack()
-                # Call views_open with the built-in client
-                client.views_open(
-                    # Pass a valid trigger_id within 3 seconds of receiving it
-                    trigger_id=body["trigger_id"],
-                    # View payload
-                    view={ ... }
-                )
-
-            # Pass a function to this method
-            app.shortcut("open_modal")(open_modal)
-
-        Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload.
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.shortcut(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def global_shortcut(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new global shortcut listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.global_shortcut(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def message_shortcut(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new message shortcut listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.message_shortcut(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # action
-
-    def action(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new action listener. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.action("approve_button")
-            def update_message(ack):
-                ack()
-
-            # Pass a function to this method
-            app.action("approve_button")(update_message)
-
-        * Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`.
-        * Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`.
-        * Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.action(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def block_action(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `block_actions` action listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.block_action(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def attachment_action(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `interactive_message` action listener.
-        Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.attachment_action(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_submission(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `dialog_submission` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_submission(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_cancellation(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `dialog_cancellation` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_cancellation(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # view
-
-    def view(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `view_submission`/`view_closed` event listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.view("view_1")
-            def handle_submission(ack, body, client, view):
-                # Assume there's an input block with `block_c` as the block_id and `dreamy_input`
-                hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-                user = body["user"]["id"]
-                # Validate the inputs
-                errors = {}
-                if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-                    errors["block_c"] = "The value must be longer than 5 characters"
-                if len(errors) > 0:
-                    ack(response_action="errors", errors=errors)
-                    return
-                # Acknowledge the view_submission event and close the modal
-                ack()
-                # Do whatever you want with the input data - here we're saving it to a DB
-
-            # Pass a function to this method
-            app.view("view_1")(handle_submission)
-
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def view_submission(
-        self,
-        constraints: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `view_submission` listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for
-        details.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view_submission(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def view_closed(
-        self,
-        constraints: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `view_closed` listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view_closed(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # options
-
-    def options(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new options listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.options("menu_selection")
-            def show_menu_options(ack):
-                options = [
-                    {
-                        "text": {"type": "plain_text", "text": "Option 1"},
-                        "value": "1-1",
-                    },
-                    {
-                        "text": {"type": "plain_text", "text": "Option 2"},
-                        "value": "1-2",
-                    },
-                ]
-                ack(options=options)
-
-            # Pass a function to this method
-            app.options("menu_selection")(show_menu_options)
-
-        Refer to the following documents for details:
-
-        * https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select
-        * https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.options(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def block_suggestion(
-        self,
-        action_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `block_suggestion` listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.block_suggestion(action_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_suggestion(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `dialog_suggestion` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_suggestion(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # built-in listener functions
-
-    def default_tokens_revoked_event_listener(
-        self,
-    ) -> Callable[..., Optional[BoltResponse]]:
-        if self._tokens_revocation_listeners is None:
-            raise BoltError(error_installation_store_required_for_builtin_listeners())
-        return self._tokens_revocation_listeners.handle_tokens_revoked_events
-
-    def default_app_uninstalled_event_listener(
-        self,
-    ) -> Callable[..., Optional[BoltResponse]]:
-        if self._tokens_revocation_listeners is None:
-            raise BoltError(error_installation_store_required_for_builtin_listeners())
-        return self._tokens_revocation_listeners.handle_app_uninstalled_events
-
-    def enable_token_revocation_listeners(self) -> None:
-        self.event("tokens_revoked")(self.default_tokens_revoked_event_listener())
-        self.event("app_uninstalled")(self.default_app_uninstalled_event_listener())
-
-    # -------------------------
-
-    def _init_context(self, req: BoltRequest):
-        req.context["logger"] = get_bolt_app_logger(app_name=self.name, base_logger=self._base_logger)
-        req.context["token"] = self._token
-        # Prior to version 1.15, when the token is static, self._client was passed to `req.context`.
-        # The intention was to avoid creating a new instance per request
-        # in the interest of runtime performance/memory footprint optimization.
-        # However, developers may want to replace the token held by req.context.client in some situations.
-        # In this case, this behavior can result in thread-unsafe data modification on `self._client`.
-        # (`self._client` a.k.a. `app.client` is a singleton object per an App instance)
-        # Thus, we've changed the behavior to create a new instance per request regardless of token argument
-        # in the App initialization starting v1.15.
-        # The overhead brought by this change is slight so that we believe that it is ignorable in any cases.
-        client_per_request: WebClient = WebClient(
-            token=self._token,  # this can be None, and it can be set later on
-            base_url=self._client.base_url,
-            timeout=self._client.timeout,
-            ssl=self._client.ssl,
-            proxy=self._client.proxy,
-            headers=self._client.headers,
-            team_id=req.context.team_id,
-            logger=self._client.logger,
-            retry_handlers=self._client.retry_handlers.copy() if self._client.retry_handlers is not None else None,
-        )
-        req.context["client"] = client_per_request
-
-        # Most apps do not need this "listener_runner" instance.
-        # It is intended for apps that start lazy listeners from their custom global middleware.
-        req.context["listener_runner"] = self.listener_runner
-
-    @staticmethod
-    def _to_listener_functions(
-        kwargs: dict,
-    ) -> Optional[Sequence[Callable[..., Optional[BoltResponse]]]]:
-        if kwargs:
-            functions = [kwargs["ack"]]
-            for sub in kwargs["lazy"]:
-                functions.append(sub)
-            return functions
-        return None
-
-    def _register_listener(
-        self,
-        functions: Sequence[Callable[..., Optional[BoltResponse]]],
-        primary_matcher: ListenerMatcher,
-        matchers: Optional[Sequence[Callable[..., bool]]],
-        middleware: Optional[Sequence[Union[Callable, Middleware]]],
-        auto_acknowledgement: bool = False,
-        ack_timeout: int = 3,
-    ) -> Optional[Callable[..., Optional[BoltResponse]]]:
-        value_to_return = None
-        if not isinstance(functions, list):
-            functions = list(functions)
-        if len(functions) == 1:
-            # In the case where the function is registered using decorator,
-            # the registration should return the original function.
-            value_to_return = functions[0]
-
-        listener_matchers: List[ListenerMatcher] = [
-            CustomListenerMatcher(app_name=self.name, func=f, base_logger=self._base_logger) for f in (matchers or [])
-        ]
-        listener_matchers.insert(0, primary_matcher)
-        listener_middleware = []
-        for m in middleware or []:
-            if isinstance(m, Middleware):
-                listener_middleware.append(m)
-            elif callable(m):
-                listener_middleware.append(CustomMiddleware(app_name=self.name, func=m, base_logger=self._base_logger))
-            else:
-                raise ValueError(error_unexpected_listener_middleware(type(m)))
-
-        self._listeners.append(
-            CustomListener(
-                app_name=self.name,
-                ack_function=functions.pop(0),
-                lazy_functions=functions,  # type: ignore[arg-type]
-                matchers=listener_matchers,
-                middleware=listener_middleware,
-                auto_acknowledgement=auto_acknowledgement,
-                ack_timeout=ack_timeout,
-                base_logger=self._base_logger,
-            )
-        )
-        return value_to_return
-
-

Bolt App that provides functionalities to register middleware/listeners.

-
import os
-from slack_bolt import App
-
-# Initializes your app with your bot token and signing secret
-app = App(
-    token=os.environ.get("SLACK_BOT_TOKEN"),
-    signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
-)
-
-# Listens to incoming messages that contain "hello"
-@app.message("hello")
-def message_hello(message, say):
-    # say() sends a message to the channel where the event was triggered
-    say(f"Hey there <@{message['user']}>!")
-
-# Start your app
-if __name__ == "__main__":
-    app.start(port=int(os.environ.get("PORT", 3000)))
-
-

Refer to https://docs.slack.dev/tools/bolt-python/creating-an-app for details.

-

If you would like to build an OAuth app for enabling the app to run with multiple workspaces, -refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app.

-

Args

-
-
logger
-
The custom logger that can be used in this app.
-
name
-
The application name that will be used in logging. If absent, the source file name will be used.
-
process_before_response
-
True if this app runs on Function as a Service. (Default: False)
-
raise_error_for_unhandled_request
-
True if you want to raise exceptions for unhandled requests -and use @app.error listeners instead of -the built-in handler, which pints warning logs and returns 404 to Slack (Default: False)
-
signing_secret
-
The Signing Secret value used for verifying requests from Slack.
-
token
-
The bot/user access token required only for single-workspace app.
-
token_verification_enabled
-
Verifies the validity of the given token if True.
-
client
-
The singleton slack_sdk.WebClient instance for this app.
-
before_authorize
-
A global middleware that can be executed right before authorize function
-
authorize
-
The function to authorize an incoming request from Slack -by checking if there is a team/user in the installation data.
-
user_facing_authorize_error_message
-
The user-facing error message to display -when the app is installed but the installation is not managed by this app's installation store
-
installation_store
-
The module offering save/find operations of installation data
-
installation_store_bot_only
-
Use InstallationStore#find_bot() if True (Default: False)
-
request_verification_enabled
-
False if you would like to disable the built-in middleware (Default: True). -RequestVerification is a built-in middleware that verifies the signature in HTTP Mode requests. -Make sure if it's safe enough when you turn a built-in middleware off. -We strongly recommend using RequestVerification for better security. -If you have a proxy that verifies request signature in front of the Bolt app, -it's totally fine to disable RequestVerification to avoid duplication of work. -Don't turn it off just for easiness of development.
-
ignoring_self_events_enabled
-
False if you would like to disable the built-in middleware (Default: True). -IgnoringSelfEvents is a built-in middleware that enables Bolt apps to easily skip the events -generated by this app's bot user (this is useful for avoiding code error causing an infinite loop).
-
ignoring_self_assistant_message_events_enabled
-
False if you would like to disable the built-in middleware. -IgnoringSelfEvents for this app's bot user message events within an assistant thread -This is useful for avoiding code error causing an infinite loop; Default: True
-
url_verification_enabled
-
False if you would like to disable the built-in middleware (Default: True). -UrlVerification is a built-in middleware that handles url_verification requests -that verify the endpoint for Events API in HTTP Mode requests.
-
attaching_function_token_enabled
-
False if you would like to disable the built-in middleware (Default: True). -AttachingFunctionToken is a built-in middleware that injects the just-in-time workflow-execution tokens -when your app receives function_executed or interactivity events scoped to a custom step.
-
ssl_check_enabled
-
bool = False if you would like to disable the built-in middleware (Default: True). -SslCheck is a built-in middleware that handles ssl_check requests from Slack.
-
oauth_settings
-
The settings related to Slack app installation flow (OAuth flow)
-
oauth_flow
-
Instantiated OAuthFlow. This is always prioritized over oauth_settings.
-
verification_token
-
Deprecated verification mechanism. This can be used only for ssl_check requests.
-
listener_executor
-
Custom executor to run background tasks. If absent, the default ThreadPoolExecutor will -be used.
-
assistant_thread_context_store
-
Custom AssistantThreadContext store (Default: the built-in implementation, -which uses a parent message's metadata to store the latest context)
-
-

Instance variables

-
-
prop client : slack_sdk.web.client.WebClient
-
-
- -Expand source code - -
@property
-def client(self) -> WebClient:
-    """The singleton `slack_sdk.WebClient` instance in this app."""
-    return self._client
-
-

The singleton slack_sdk.WebClient instance in this app.

-
-
prop installation_store : slack_sdk.oauth.installation_store.installation_store.InstallationStore | None
-
-
- -Expand source code - -
@property
-def installation_store(self) -> Optional[InstallationStore]:
-    """The `slack_sdk.oauth.InstallationStore` that can be used in the `authorize` middleware."""
-    return self._installation_store
-
-

The slack_sdk.oauth.InstallationStore that can be used in the authorize middleware.

-
-
prop listener_runnerThreadListenerRunner
-
-
- -Expand source code - -
@property
-def listener_runner(self) -> ThreadListenerRunner:
-    """The thread executor for asynchronously running listeners."""
-    return self._listener_runner
-
-

The thread executor for asynchronously running listeners.

-
-
prop logger : logging.Logger
-
-
- -Expand source code - -
@property
-def logger(self) -> logging.Logger:
-    """The logger this app uses."""
-    return self._framework_logger
-
-

The logger this app uses.

-
-
prop name : str
-
-
- -Expand source code - -
@property
-def name(self) -> str:
-    """The name of this app (default: the filename)"""
-    return self._name
-
-

The name of this app (default: the filename)

-
-
prop oauth_flowOAuthFlow | None
-
-
- -Expand source code - -
@property
-def oauth_flow(self) -> Optional[OAuthFlow]:
-    """Configured `OAuthFlow` object if exists."""
-    return self._oauth_flow
-
-

Configured OAuthFlow object if exists.

-
-
prop process_before_response : bool
-
-
- -Expand source code - -
@property
-def process_before_response(self) -> bool:
-    return self._process_before_response or False
-
-
-
-
-

Methods

-
-
-def action(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def action(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new action listener. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.action("approve_button")
-        def update_message(ack):
-            ack()
-
-        # Pass a function to this method
-        app.action("approve_button")(update_message)
-
-    * Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`.
-    * Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`.
-    * Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.action(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new action listener. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.action("approve_button")
-def update_message(ack):
-    ack()
-
-# Pass a function to this method
-app.action("approve_button")(update_message)
-
- -

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def assistant(self,
assistant: Assistant) ‑> Callable | None
-
-
-
- -Expand source code - -
def assistant(self, assistant: Assistant) -> Optional[Callable]:
-    return self.middleware(assistant)
-
-
-
-
-def attachment_action(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def attachment_action(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `interactive_message` action listener.
-    Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.attachment_action(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new interactive_message action listener. -Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details.

-
-
-def block_action(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def block_action(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `block_actions` action listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.block_action(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new block_actions action listener. -Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.

-
-
-def block_suggestion(self,
action_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def block_suggestion(
-    self,
-    action_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `block_suggestion` listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.block_suggestion(action_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new block_suggestion listener.

-
-
-def command(self,
command: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def command(
-    self,
-    command: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new slash command listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.command("/echo")
-        def repeat_text(ack, say, command):
-            # Acknowledge command request
-            ack()
-            say(f"{command['text']}")
-
-        # Pass a function to this method
-        app.command("/echo")(repeat_text)
-
-    Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        command: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.command(command, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new slash command listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.command("/echo")
-def repeat_text(ack, say, command):
-    # Acknowledge command request
-    ack()
-    say(f"{command['text']}")
-
-# Pass a function to this method
-app.command("/echo")(repeat_text)
-
-

Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
command
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def default_app_uninstalled_event_listener(self) ‑> Callable[..., BoltResponse | None] -
-
-
- -Expand source code - -
def default_app_uninstalled_event_listener(
-    self,
-) -> Callable[..., Optional[BoltResponse]]:
-    if self._tokens_revocation_listeners is None:
-        raise BoltError(error_installation_store_required_for_builtin_listeners())
-    return self._tokens_revocation_listeners.handle_app_uninstalled_events
-
-
-
-
-def default_tokens_revoked_event_listener(self) ‑> Callable[..., BoltResponse | None] -
-
-
- -Expand source code - -
def default_tokens_revoked_event_listener(
-    self,
-) -> Callable[..., Optional[BoltResponse]]:
-    if self._tokens_revocation_listeners is None:
-        raise BoltError(error_installation_store_required_for_builtin_listeners())
-    return self._tokens_revocation_listeners.handle_tokens_revoked_events
-
-
-
-
-def dialog_cancellation(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def dialog_cancellation(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `dialog_cancellation` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_cancellation(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_cancellation listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dialog_submission(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def dialog_submission(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `dialog_submission` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_submission(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_submission listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dialog_suggestion(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def dialog_suggestion(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `dialog_suggestion` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_suggestion(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_suggestion listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dispatch(self,
req: BoltRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def dispatch(self, req: BoltRequest) -> BoltResponse:
-    """Applies all middleware and dispatches an incoming request from Slack to the right code path.
-
-    Args:
-        req: An incoming request from Slack
-
-    Returns:
-        The response generated by this Bolt app
-    """
-    starting_time = time.time()
-    self._init_context(req)
-
-    resp: Optional[BoltResponse] = BoltResponse(status=200, body="")
-    middleware_state = {"next_called": False}
-
-    def middleware_next():
-        middleware_state["next_called"] = True
-
-    try:
-        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)  # type: ignore[arg-type]
-            if not middleware_state["next_called"]:
-                if resp is None:
-                    # next() method was not called without providing the response to return to Slack
-                    # This should not be an intentional handling in usual use cases.
-                    resp = BoltResponse(status=404, body={"error": "no next() calls in middleware"})
-                    if self._raise_error_for_unhandled_request is True:
-                        try:
-                            raise BoltUnhandledRequestError(
-                                request=req,
-                                current_response=resp,
-                                last_global_middleware_name=middleware.name,
-                            )
-                        except BoltUnhandledRequestError as e:
-                            self._listener_runner.listener_error_handler.handle(
-                                error=e,
-                                request=req,
-                                response=resp,
-                            )
-                        return resp
-                    self._framework_logger.warning(warning_unhandled_by_global_middleware(middleware.name, req))
-                    return resp
-                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):  # type: ignore[arg-type]
-                # run all the middleware attached to this listener first
-                middleware_resp, next_was_not_called = listener.run_middleware(
-                    req=req, resp=resp  # type: ignore[arg-type]
-                )
-                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,  # type: ignore[arg-type]
-                    listener_name=listener_name,
-                    listener=listener,
-                )
-                if listener_response is not None:
-                    return listener_response
-
-        if resp is None:
-            resp = BoltResponse(status=404, body={"error": "unhandled request"})
-        if self._raise_error_for_unhandled_request is True:
-            try:
-                raise BoltUnhandledRequestError(
-                    request=req,
-                    current_response=resp,
-                )
-            except BoltUnhandledRequestError as e:
-                self._listener_runner.listener_error_handler.handle(
-                    error=e,
-                    request=req,
-                    response=resp,
-                )
-            return resp
-        return self._handle_unmatched_requests(req, resp)
-    except Exception as error:
-        resp = BoltResponse(status=500, body="")
-        self._middleware_error_handler.handle(
-            error=error,
-            request=req,
-            response=resp,
-        )
-        return resp
-
-

Applies all middleware and dispatches an incoming request from Slack to the right code path.

-

Args

-
-
req
-
An incoming request from Slack
-
-

Returns

-

The response generated by this Bolt app

-
-
-def enable_token_revocation_listeners(self) ‑> None -
-
-
- -Expand source code - -
def enable_token_revocation_listeners(self) -> None:
-    self.event("tokens_revoked")(self.default_tokens_revoked_event_listener())
-    self.event("app_uninstalled")(self.default_app_uninstalled_event_listener())
-
-
-
-
-def error(self,
func: Callable[..., BoltResponse | None]) ‑> Callable[..., BoltResponse | None]
-
-
-
- -Expand source code - -
def error(self, func: Callable[..., Optional[BoltResponse]]) -> Callable[..., Optional[BoltResponse]]:
-    """Updates the global error handler. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.error
-        def custom_error_handler(error, body, logger):
-            logger.exception(f"Error: {error}")
-            logger.info(f"Request body: {body}")
-
-        # Pass a function to this method
-        app.error(custom_error_handler)
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        func: The function that is supposed to be executed
-            when getting an unhandled error in Bolt app.
-    """
-    self._listener_runner.listener_error_handler = CustomListenerErrorHandler(
-        logger=self._framework_logger,
-        func=func,
-    )
-    self._middleware_error_handler = CustomMiddlewareErrorHandler(
-        logger=self._framework_logger,
-        func=func,
-    )
-    return func
-
-

Updates the global error handler. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.error
-def custom_error_handler(error, body, logger):
-    logger.exception(f"Error: {error}")
-    logger.info(f"Request body: {body}")
-
-# Pass a function to this method
-app.error(custom_error_handler)
-
-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
func
-
The function that is supposed to be executed -when getting an unhandled error in Bolt app.
-
-
-
-def event(self,
event: str | Pattern | Dict[str, str | Sequence[str | Pattern | None] | None],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def event(
-    self,
-    event: Union[
-        str,
-        Pattern,
-        Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]],
-    ],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new event listener. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.event("team_join")
-        def ask_for_introduction(event, say):
-            welcome_channel_id = "C12345"
-            user_id = event["user"]
-            text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-            say(text=text, channel=welcome_channel_id)
-
-        # Pass a function to this method
-        app.event("team_join")(ask_for_introduction)
-
-    Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        event: The conditions that match a request payload.
-            If you pass a dict for this, you can have type, subtype in the constraint.
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.event(event, base_logger=self._base_logger)
-        if self._attaching_conversation_kwargs_enabled:
-            middleware.insert(0, AttachingConversationKwargs(self._assistant_thread_context_store))
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-    return __call__
-
-

Registers a new event listener. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.event("team_join")
-def ask_for_introduction(event, say):
-    welcome_channel_id = "C12345"
-    user_id = event["user"]
-    text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-    say(text=text, channel=welcome_channel_id)
-
-# Pass a function to this method
-app.event("team_join")(ask_for_introduction)
-
-

Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
event
-
The conditions that match a request payload. -If you pass a dict for this, you can have type, subtype in the constraint.
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def function(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None,
auto_acknowledge: bool = True,
ack_timeout: int = 3) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def function(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    auto_acknowledge: bool = True,
-    ack_timeout: int = 3,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new Function listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.function("reverse")
-        def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail):
-            try:
-                ack()
-                string_to_reverse = inputs["stringToReverse"]
-                complete(outputs={"reverseString": string_to_reverse[::-1]})
-            except Exception as e:
-                fail(f"Cannot reverse string (error: {e})")
-                raise e
-
-        # Pass a function to this method
-        app.function("reverse")(reverse_string)
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        callback_id: The callback id to identify the function
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    if auto_acknowledge is True:
-        if ack_timeout != 3:
-            self._framework_logger.warning(warning_ack_timeout_has_no_effect(callback_id, ack_timeout))
-
-    matchers = list(matchers) if matchers else []
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.function_executed(callback_id=callback_id, base_logger=self._base_logger)
-        return self._register_listener(functions, primary_matcher, matchers, middleware, auto_acknowledge, ack_timeout)
-
-    return __call__
-
-

Registers a new Function listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.function("reverse")
-def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail):
-    try:
-        ack()
-        string_to_reverse = inputs["stringToReverse"]
-        complete(outputs={"reverseString": string_to_reverse[::-1]})
-    except Exception as e:
-        fail(f"Cannot reverse string (error: {e})")
-        raise e
-
-# Pass a function to this method
-app.function("reverse")(reverse_string)
-
-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
callback_id
-
The callback id to identify the function
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def global_shortcut(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def global_shortcut(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new global shortcut listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.global_shortcut(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new global shortcut listener.

-
-
-def message(self,
keyword: str | Pattern = '',
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def message(
-    self,
-    keyword: Union[str, Pattern] = "",
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new message event listener. This method can be used as either a decorator or a method.
-    Check the `App#event` method's docstring for details.
-
-        # Use this method as a decorator
-        @app.message(":wave:")
-        def say_hello(message, say):
-            user = message['user']
-            say(f"Hi there, <@{user}>!")
-
-        # Pass a function to this method
-        app.message(":wave:")(say_hello)
-
-    Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        keyword: The keyword to match
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-    matchers = list(matchers) if matchers else []
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        constraints = {
-            "type": "message",
-            "subtype": (
-                # In most cases, new message events come with no subtype.
-                None,
-                # As of Jan 2021, most bot messages no longer have the subtype bot_message.
-                # By contrast, messages posted using classic app's bot token still have the subtype.
-                "bot_message",
-                # If an end-user posts a message with "Also send to #channel" checked,
-                # the message event comes with this subtype.
-                "thread_broadcast",
-                # If an end-user posts a message with attached files,
-                # the message event comes with this subtype.
-                "file_share",
-            ),
-        }
-        primary_matcher = builtin_matchers.message_event(
-            keyword=keyword, constraints=constraints, base_logger=self._base_logger
-        )
-        if self._attaching_conversation_kwargs_enabled:
-            middleware.insert(0, AttachingConversationKwargs(self._assistant_thread_context_store))
-        middleware.insert(0, MessageListenerMatches(keyword))
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-    return __call__
-
-

Registers a new message event listener. This method can be used as either a decorator or a method. -Check the App#event method's docstring for details.

-
# Use this method as a decorator
-@app.message(":wave:")
-def say_hello(message, say):
-    user = message['user']
-    say(f"Hi there, <@{user}>!")
-
-# Pass a function to this method
-app.message(":wave:")(say_hello)
-
-

Refer to https://docs.slack.dev/reference/events/message/ for details of message events.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
keyword
-
The keyword to match
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def message_shortcut(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def message_shortcut(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new message shortcut listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.message_shortcut(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new message shortcut listener.

-
-
-def middleware(self, *args) ‑> Callable | None -
-
-
- -Expand source code - -
def middleware(self, *args) -> Optional[Callable]:
-    """Registers a new middleware to this app.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.middleware
-        def middleware_func(logger, body, next):
-            logger.info(f"request body: {body}")
-            next()
-
-        # Pass a function to this method
-        app.middleware(middleware_func)
-
-    Refer to https://docs.slack.dev/tools/bolt-python/concepts/global-middleware for details.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        *args: A function that works as a global middleware.
-    """
-    if len(args) > 0:
-        middleware_or_callable = args[0]
-        if isinstance(middleware_or_callable, Middleware):
-            middleware: Middleware = middleware_or_callable
-            self._middleware_list.append(middleware)
-            if isinstance(middleware, Assistant) and middleware.thread_context_store is not None:
-                self._assistant_thread_context_store = middleware.thread_context_store
-        elif callable(middleware_or_callable):
-            self._middleware_list.append(
-                CustomMiddleware(
-                    app_name=self.name,
-                    func=middleware_or_callable,
-                    base_logger=self._base_logger,
-                )
-            )
-            return middleware_or_callable
-        else:
-            raise BoltError(f"Unexpected type for a middleware ({type(middleware_or_callable)})")
-    return None
-
-

Registers a new middleware to this app. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.middleware
-def middleware_func(logger, body, next):
-    logger.info(f"request body: {body}")
-    next()
-
-# Pass a function to this method
-app.middleware(middleware_func)
-
-

Refer to https://docs.slack.dev/tools/bolt-python/concepts/global-middleware for details.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
*args
-
A function that works as a global middleware.
-
-
-
-def options(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def options(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new options listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.options("menu_selection")
-        def show_menu_options(ack):
-            options = [
-                {
-                    "text": {"type": "plain_text", "text": "Option 1"},
-                    "value": "1-1",
-                },
-                {
-                    "text": {"type": "plain_text", "text": "Option 2"},
-                    "value": "1-2",
-                },
-            ]
-            ack(options=options)
-
-        # Pass a function to this method
-        app.options("menu_selection")(show_menu_options)
-
-    Refer to the following documents for details:
-
-    * https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select
-    * https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.options(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new options listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.options("menu_selection")
-def show_menu_options(ack):
-    options = [
-        {
-            "text": {"type": "plain_text", "text": "Option 1"},
-            "value": "1-1",
-        },
-        {
-            "text": {"type": "plain_text", "text": "Option 2"},
-            "value": "1-2",
-        },
-    ]
-    ack(options=options)
-
-# Pass a function to this method
-app.options("menu_selection")(show_menu_options)
-
-

Refer to the following documents for details:

- -

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def shortcut(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def shortcut(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new shortcut listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.shortcut("open_modal")
-        def open_modal(ack, body, client):
-            # Acknowledge the command request
-            ack()
-            # Call views_open with the built-in client
-            client.views_open(
-                # Pass a valid trigger_id within 3 seconds of receiving it
-                trigger_id=body["trigger_id"],
-                # View payload
-                view={ ... }
-            )
-
-        # Pass a function to this method
-        app.shortcut("open_modal")(open_modal)
-
-    Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload.
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.shortcut(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new shortcut listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.shortcut("open_modal")
-def open_modal(ack, body, client):
-    # Acknowledge the command request
-    ack()
-    # Call views_open with the built-in client
-    client.views_open(
-        # Pass a valid trigger_id within 3 seconds of receiving it
-        trigger_id=body["trigger_id"],
-        # View payload
-        view={ ... }
-    )
-
-# Pass a function to this method
-app.shortcut("open_modal")(open_modal)
-
-

Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload.
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def start(self,
port: int = 3000,
path: str = '/slack/events',
http_server_logger_enabled: bool = True) ‑> None
-
-
-
- -Expand source code - -
def start(
-    self,
-    port: int = 3000,
-    path: str = "/slack/events",
-    http_server_logger_enabled: bool = True,
-) -> None:
-    """Starts a web server for local development.
-
-        # With the default settings, `http://localhost:3000/slack/events`
-        # is available for handling incoming requests from Slack
-        app.start()
-
-    This method internally starts a Web server process built with the `http.server` module.
-    For production, consider using a production-ready WSGI server such as Gunicorn.
-
-    Args:
-        port: The port to listen on (Default: 3000)
-        path: The path to handle request from Slack (Default: `/slack/events`)
-        http_server_logger_enabled: The flag to enable http.server logging if True (Default: True)
-    """
-    self._development_server = SlackAppDevelopmentServer(
-        port=port,
-        path=path,
-        app=self,
-        oauth_flow=self.oauth_flow,
-        http_server_logger_enabled=http_server_logger_enabled,
-    )
-    self._development_server.start()
-
-

Starts a web server for local development.

-
# With the default settings, `http://localhost:3000/slack/events`
-# is available for handling incoming requests from Slack
-app.start()
-
-

This method internally starts a Web server process built with the http.server module. -For production, consider using a production-ready WSGI server such as Gunicorn.

-

Args

-
-
port
-
The port to listen on (Default: 3000)
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
http_server_logger_enabled
-
The flag to enable http.server logging if True (Default: True)
-
-
-
-def step(self,
callback_id: str | Pattern | WorkflowStep | WorkflowStepBuilder,
edit: Callable[..., BoltResponse | None] | Listener | Sequence[Callable] | None = None,
save: Callable[..., BoltResponse | None] | Listener | Sequence[Callable] | None = None,
execute: Callable[..., BoltResponse | None] | Listener | Sequence[Callable] | None = None)
-
-
-
- -Expand source code - -
def step(
-    self,
-    callback_id: Union[str, Pattern, WorkflowStep, WorkflowStepBuilder],
-    edit: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-    save: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-    execute: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-):
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Registers a new step from app listener.
-
-    Unlike others, this method doesn't behave as a decorator.
-    If you want to register a step from app by a decorator, use `WorkflowStepBuilder`'s methods.
-
-        # Create a new WorkflowStep instance
-        from slack_bolt.workflows.step import WorkflowStep
-        ws = WorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        # Pass Step to set up listeners
-        app.step(ws)
-
-    Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    For further information about WorkflowStep specific function arguments
-    such as `configure`, `update`, `complete`, and `fail`,
-    refer to `slack_bolt.workflows.step.utilities` API documents.
-
-    Args:
-        callback_id: The Callback ID for this step from app
-        edit: The function for displaying a modal in the Workflow Builder
-        save: The function for handling configuration in the Workflow Builder
-        execute: The function for handling the step execution
-    """
-    warnings.warn(
-        (
-            "Steps from apps for legacy workflows are now deprecated. "
-            "Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/"
-        ),
-        category=DeprecationWarning,
-    )
-    step = callback_id
-    if isinstance(callback_id, (str, Pattern)):
-        step = WorkflowStep(
-            callback_id=callback_id,
-            edit=edit,  # type: ignore[arg-type]
-            save=save,  # type: ignore[arg-type]
-            execute=execute,  # type: ignore[arg-type]
-            base_logger=self._base_logger,
-        )
-    elif isinstance(step, WorkflowStepBuilder):
-        step = step.build(base_logger=self._base_logger)
-    elif not isinstance(step, WorkflowStep):
-        raise BoltError(f"Invalid step object ({type(step)})")
-
-    self.use(WorkflowStepMiddleware(step))
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Registers a new step from app listener.

-

Unlike others, this method doesn't behave as a decorator. -If you want to register a step from app by a decorator, use WorkflowStepBuilder's methods.

-
# Create a new WorkflowStep instance
-from slack_bolt.workflows.step import WorkflowStep
-ws = WorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-# Pass Step to set up listeners
-app.step(ws)
-
-

Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

For further information about WorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
callback_id
-
The Callback ID for this step from app
-
edit
-
The function for displaying a modal in the Workflow Builder
-
save
-
The function for handling configuration in the Workflow Builder
-
execute
-
The function for handling the step execution
-
-
-
-def use(self, *args) ‑> Callable | None -
-
-
- -Expand source code - -
def use(self, *args) -> Optional[Callable]:
-    """Registers a new global middleware to this app. This method can be used as either a decorator or a method.
-
-    Refer to `App#middleware()` method's docstring for details."""
-    return self.middleware(*args)
-
-

Registers a new global middleware to this app. This method can be used as either a decorator or a method.

-

Refer to App#middleware() method's docstring for details.

-
-
-def view(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def view(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `view_submission`/`view_closed` event listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.view("view_1")
-        def handle_submission(ack, body, client, view):
-            # Assume there's an input block with `block_c` as the block_id and `dreamy_input`
-            hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-            user = body["user"]["id"]
-            # Validate the inputs
-            errors = {}
-            if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-                errors["block_c"] = "The value must be longer than 5 characters"
-            if len(errors) > 0:
-                ack(response_action="errors", errors=errors)
-                return
-            # Acknowledge the view_submission event and close the modal
-            ack()
-            # Do whatever you want with the input data - here we're saving it to a DB
-
-        # Pass a function to this method
-        app.view("view_1")(handle_submission)
-
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new view_submission/view_closed event listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.view("view_1")
-def handle_submission(ack, body, client, view):
-    # Assume there's an input block with <code>block\_c</code> as the block_id and <code>dreamy\_input</code>
-    hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-    user = body["user"]["id"]
-    # Validate the inputs
-    errors = {}
-    if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-        errors["block_c"] = "The value must be longer than 5 characters"
-    if len(errors) > 0:
-        ack(response_action="errors", errors=errors)
-        return
-    # Acknowledge the view_submission event and close the modal
-    ack()
-    # Do whatever you want with the input data - here we're saving it to a DB
-
-# Pass a function to this method
-app.view("view_1")(handle_submission)
-
-

Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def view_closed(self,
constraints: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def view_closed(
-    self,
-    constraints: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `view_closed` listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view_closed(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
- -
-
-def view_submission(self,
constraints: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def view_submission(
-    self,
-    constraints: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `view_submission` listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for
-    details.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view_submission(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new view_submission listener. -Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for -details.

-
-
-
-
-class SlackAppDevelopmentServer -(port: int,
path: str,
app: App,
oauth_flow: OAuthFlow | None = None,
http_server_logger_enabled: bool = True)
-
-
-
- -Expand source code - -
class SlackAppDevelopmentServer:
-    def __init__(
-        self,
-        port: int,
-        path: str,
-        app: App,
-        oauth_flow: Optional[OAuthFlow] = None,
-        http_server_logger_enabled: bool = True,
-    ):
-        """Slack App Development Server
-
-        This is a thin wrapper of http.server.HTTPServer and is good enough
-        for your local development or prototyping.
-
-        However, as mentioned in Python official documents, using http.server module in production
-        is not recommended. Please consider using an adapter (refer to slack_bolt.adapter.*)
-        along with a production-grade server when running the app for end users.
-        https://docs.python.org/3/library/http.server.html#http.server.HTTPServer
-
-        Args:
-            port: the port number
-            path: the path to receive incoming requests
-            app: the `App` instance to execute
-            oauth_flow: the `OAuthFlow` instance to use for OAuth flow
-            http_server_logger_enabled: The flag to turn on/off http.server's logging
-        """
-        self._port: int = port
-        self._bolt_endpoint_path: str = path
-        self._bolt_app: App = app
-        self._bolt_oauth_flow: Optional[OAuthFlow] = oauth_flow
-        self._http_server_logger_enabled = http_server_logger_enabled
-
-        _port: int = self._port
-        _bolt_endpoint_path: str = self._bolt_endpoint_path
-        _bolt_app: App = self._bolt_app
-        _bolt_oauth_flow: Optional[OAuthFlow] = self._bolt_oauth_flow
-        _http_server_logger_enabled = self._http_server_logger_enabled
-
-        class SlackAppHandler(SimpleHTTPRequestHandler):
-            def log_message(self, format: str, *args: Any) -> None:
-                if _http_server_logger_enabled is True:
-                    super().log_message(format, *args)
-
-            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,
-                            # email.message.Message's mapping interface is dict compatible
-                            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,
-                            # email.message.Message's mapping interface is dict compatible
-                            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 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,
-                    # email.message.Message's mapping interface is dict compatible
-                    headers=self.headers,
-                )
-                bolt_resp: BoltResponse = _bolt_app.dispatch(bolt_req)
-                self._send_bolt_response(bolt_resp)
-
-            def _send_bolt_response(self, bolt_resp: BoltResponse):
-                self._send_response(
-                    status=bolt_resp.status,
-                    headers=bolt_resp.headers,
-                    body=bolt_resp.body,
-                )
-
-            def _send_response(
-                self,
-                status: int,
-                headers: Dict[str, Sequence[str]],
-                body: Union[str, dict] = "",
-            ):
-                self.send_response(status)
-
-                response_body = body if isinstance(body, str) else json.dumps(body)
-                body_bytes = response_body.encode("utf-8")
-
-                for k, vs in headers.items():
-                    for v in vs:
-                        self.send_header(k, v)
-                self.send_header("Content-Length", str(len(body_bytes)))
-                self.end_headers()
-                self.wfile.write(body_bytes)
-
-        self._server = HTTPServer(("0.0.0.0", self._port), SlackAppHandler)
-
-    def start(self) -> None:
-        """Starts a new web server process."""
-        if self._bolt_app.logger.level > logging.INFO:
-            print(get_boot_message(development_server=True))
-        else:
-            self._bolt_app.logger.info(get_boot_message(development_server=True))
-
-        try:
-            self._server.serve_forever(0.05)
-        finally:
-            self._server.server_close()
-
-

Slack App Development Server

-

This is a thin wrapper of http.server.HTTPServer and is good enough -for your local development or prototyping.

-

However, as mentioned in Python official documents, using http.server module in production -is not recommended. Please consider using an adapter (refer to slack_bolt.adapter.*) -along with a production-grade server when running the app for end users. -https://docs.python.org/3/library/http.server.html#http.server.HTTPServer

-

Args

-
-
port
-
the port number
-
path
-
the path to receive incoming requests
-
app
-
the App instance to execute
-
oauth_flow
-
the OAuthFlow instance to use for OAuth flow
-
http_server_logger_enabled
-
The flag to turn on/off http.server's logging
-
-

Methods

-
-
-def start(self) ‑> None -
-
-
- -Expand source code - -
def start(self) -> None:
-    """Starts a new web server process."""
-    if self._bolt_app.logger.level > logging.INFO:
-        print(get_boot_message(development_server=True))
-    else:
-        self._bolt_app.logger.info(get_boot_message(development_server=True))
-
-    try:
-        self._server.serve_forever(0.05)
-    finally:
-        self._server.server_close()
-
-

Starts a new web server process.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/app/async_app.html b/docs/reference/app/async_app.html deleted file mode 100644 index cf4c651cb..000000000 --- a/docs/reference/app/async_app.html +++ /dev/null @@ -1,3214 +0,0 @@ - - - - - - -slack_bolt.app.async_app API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.app.async_app

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncApp -(*,
logger: logging.Logger | None = None,
name: str | None = None,
process_before_response: bool = False,
raise_error_for_unhandled_request: bool = False,
signing_secret: str | None = None,
token: str | None = None,
client: slack_sdk.web.async_client.AsyncWebClient | None = None,
before_authorize: AsyncMiddleware | Callable[..., Awaitable[Any]] | None = None,
authorize: Callable[..., Awaitable[AuthorizeResult]] | None = None,
user_facing_authorize_error_message: str | None = None,
installation_store: slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore | None = None,
installation_store_bot_only: bool | None = None,
request_verification_enabled: bool = True,
ignoring_self_events_enabled: bool = True,
ignoring_self_assistant_message_events_enabled: bool = True,
ssl_check_enabled: bool = True,
url_verification_enabled: bool = True,
attaching_function_token_enabled: bool = True,
oauth_settings: AsyncOAuthSettings | None = None,
oauth_flow: AsyncOAuthFlow | None = None,
verification_token: str | None = None,
assistant_thread_context_store: AsyncAssistantThreadContextStore | None = None,
attaching_conversation_kwargs_enabled: bool = True)
-
-
-
- -Expand source code - -
class AsyncApp:
-    def __init__(
-        self,
-        *,
-        logger: Optional[logging.Logger] = None,
-        # Used in logger
-        name: Optional[str] = None,
-        # Set True when you run this app on a FaaS platform
-        process_before_response: bool = False,
-        # Set True if you want to handle an unhandled request as an exception
-        raise_error_for_unhandled_request: bool = False,
-        # Basic Information > Credentials > Signing Secret
-        signing_secret: Optional[str] = None,
-        # for single-workspace apps
-        token: Optional[str] = None,
-        client: Optional[AsyncWebClient] = None,
-        # for multi-workspace apps
-        before_authorize: Optional[Union[AsyncMiddleware, Callable[..., Awaitable[Any]]]] = None,
-        authorize: Optional[Callable[..., Awaitable[AuthorizeResult]]] = None,
-        user_facing_authorize_error_message: Optional[str] = None,
-        installation_store: Optional[AsyncInstallationStore] = None,
-        # for either only bot scope usage or v1.0.x compatibility
-        installation_store_bot_only: Optional[bool] = None,
-        # for customizing the built-in middleware
-        request_verification_enabled: bool = True,
-        ignoring_self_events_enabled: bool = True,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-        ssl_check_enabled: bool = True,
-        url_verification_enabled: bool = True,
-        attaching_function_token_enabled: bool = True,
-        # for the OAuth flow
-        oauth_settings: Optional[AsyncOAuthSettings] = None,
-        oauth_flow: Optional[AsyncOAuthFlow] = None,
-        # No need to set (the value is used only in response to ssl_check requests)
-        verification_token: Optional[str] = None,
-        # for AI Agents & Assistants
-        assistant_thread_context_store: Optional[AsyncAssistantThreadContextStore] = None,
-        attaching_conversation_kwargs_enabled: bool = True,
-    ):
-        """Bolt App that provides functionalities to register middleware/listeners.
-
-            import os
-            from slack_bolt.async_app import AsyncApp
-
-            # Initializes your app with your bot token and signing secret
-            app = AsyncApp(
-                token=os.environ.get("SLACK_BOT_TOKEN"),
-                signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
-            )
-
-            # Listens to incoming messages that contain "hello"
-            @app.message("hello")
-            async def message_hello(message, say):  # async function
-                # say() sends a message to the channel where the event was triggered
-                await say(f"Hey there <@{message['user']}>!")
-
-            # Start your app
-            if __name__ == "__main__":
-                app.start(port=int(os.environ.get("PORT", 3000)))
-
-        Refer to https://docs.slack.dev/tools/bolt-python/concepts/async for details.
-
-        If you would like to build an OAuth app for enabling the app to run with multiple workspaces,
-        refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app.
-
-        Args:
-            logger: The custom logger that can be used in this app.
-            name: The application name that will be used in logging. If absent, the source file name will be used.
-            process_before_response: True if this app runs on Function as a Service. (Default: False)
-            raise_error_for_unhandled_request: True if you want to raise exceptions for unhandled requests
-                and use @app.error listeners instead of
-                the built-in handler, which pints warning logs and returns 404 to Slack (Default: False)
-            signing_secret: The Signing Secret value used for verifying requests from Slack.
-            token: The bot/user access token required only for single-workspace app.
-            client: The singleton `slack_sdk.web.async_client.AsyncWebClient` instance for this app.
-            before_authorize: A global middleware that can be executed right before authorize function
-            authorize: The function to authorize an incoming request from Slack
-                by checking if there is a team/user in the installation data.
-            user_facing_authorize_error_message: The user-facing error message to display
-                when the app is installed but the installation is not managed by this app's installation store
-            installation_store: The module offering save/find operations of installation data
-            installation_store_bot_only: Use `AsyncInstallationStore#async_find_bot()` if True (Default: False)
-            request_verification_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `AsyncRequestVerification` is a built-in middleware that verifies the signature in HTTP Mode requests.
-                Make sure if it's safe enough when you turn a built-in middleware off.
-                We strongly recommend using RequestVerification for better security.
-                If you have a proxy that verifies request signature in front of the Bolt app,
-                it's totally fine to disable RequestVerification to avoid duplication of work.
-                Don't turn it off just for easiness of development.
-            ignoring_self_events_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `AsyncIgnoringSelfEvents` is a built-in middleware that enables Bolt apps to easily skip the events
-                generated by this app's bot user (this is useful for avoiding code error causing an infinite loop).
-            ignoring_self_assistant_message_events_enabled: False if you would like to disable the built-in middleware.
-                `IgnoringSelfEvents` for this app's bot user message events within an assistant thread
-                This is useful for avoiding code error causing an infinite loop; Default: True
-            url_verification_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `AsyncUrlVerification` is a built-in middleware that handles url_verification requests
-                that verify the endpoint for Events API in HTTP Mode requests.
-            ssl_check_enabled: bool = False if you would like to disable the built-in middleware (Default: True).
-                `AsyncSslCheck` is a built-in middleware that handles ssl_check requests from Slack.
-            attaching_function_token_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `AsyncAttachingFunctionToken` is a built-in middleware that injects the just-in-time workflow-execution token
-                when your app receives `function_executed` or interactivity events scoped to a custom step.
-            oauth_settings: The settings related to Slack app installation flow (OAuth flow)
-            oauth_flow: Instantiated `slack_bolt.oauth.AsyncOAuthFlow`. This is always prioritized over oauth_settings.
-            verification_token: Deprecated verification mechanism. This can be used only for ssl_check requests.
-            assistant_thread_context_store: Custom AssistantThreadContext store (Default: the built-in implementation,
-                which uses a parent message's metadata to store the latest context)
-        """
-        if signing_secret is None:
-            signing_secret = os.environ.get("SLACK_SIGNING_SECRET", "")
-        token = token or os.environ.get("SLACK_BOT_TOKEN")
-
-        self._name: str = name or inspect.stack()[1].filename.split(os.path.sep)[-1]
-        self._signing_secret: str = signing_secret
-        self._verification_token: Optional[str] = verification_token or os.environ.get("SLACK_VERIFICATION_TOKEN", None)
-        # If a logger is explicitly passed when initializing, the logger works as the base logger.
-        # The base logger's logging settings will be propagated to all the loggers created by bolt-python.
-        self._base_logger = logger
-        # The framework logger is supposed to be used for the internal logging.
-        # Also, it's accessible via `app.logger` as the app's singleton logger.
-        self._framework_logger = logger or get_bolt_logger(AsyncApp)
-        self._raise_error_for_unhandled_request = raise_error_for_unhandled_request
-
-        self._token: Optional[str] = token
-
-        if client is not None:
-            if not isinstance(client, AsyncWebClient):
-                raise BoltError(error_client_invalid_type_async())
-            self._async_client = client
-            self._token = client.token
-            if token is not None:
-                self._framework_logger.warning(warning_client_prioritized_and_token_skipped())
-        else:
-            self._async_client = create_async_web_client(
-                # NOTE: the token here can be None
-                token=token,
-                logger=self._framework_logger,
-            )
-
-        # --------------------------------------
-        # Authorize & OAuthFlow initialization
-        # --------------------------------------
-
-        self._async_before_authorize: Optional[AsyncMiddleware] = None
-        if before_authorize is not None:
-            if callable(before_authorize):
-                self._async_before_authorize = AsyncCustomMiddleware(
-                    app_name=self._name,
-                    func=before_authorize,
-                    base_logger=self._framework_logger,
-                )
-            elif isinstance(before_authorize, AsyncMiddleware):
-                self._async_before_authorize = before_authorize
-
-        self._async_authorize: Optional[AsyncAuthorize] = None
-        if authorize is not None:
-            if isinstance(authorize, AsyncAuthorize):
-                # As long as an advanced developer understands what they're doing,
-                # bolt-python should not prevent customizing authorize middleware
-                self._async_authorize = authorize
-            else:
-                if oauth_settings is not None or oauth_flow is not None:
-                    # If the given authorize is a simple function,
-                    # it does not work along with installation_store.
-                    raise BoltError(error_authorize_conflicts())
-                self._async_authorize = AsyncCallableAuthorize(logger=self._framework_logger, func=authorize)
-
-        self._async_installation_store: Optional[AsyncInstallationStore] = installation_store
-        if self._async_installation_store is not None and self._async_authorize is None:
-            settings = oauth_flow.settings if oauth_flow is not None else oauth_settings
-            self._async_authorize = AsyncInstallationStoreAuthorize(
-                installation_store=self._async_installation_store,
-                client_id=settings.client_id if settings is not None else None,
-                client_secret=settings.client_secret if settings is not None else None,
-                logger=self._framework_logger,
-                bot_only=installation_store_bot_only or False,
-                client=self._async_client,  # for proxy use cases etc.
-                user_token_resolution=(settings.user_token_resolution if settings is not None else "authed_user"),
-            )
-
-        self._async_oauth_flow: Optional[AsyncOAuthFlow] = None
-
-        if (
-            oauth_settings is None
-            and os.environ.get("SLACK_CLIENT_ID") is not None
-            and os.environ.get("SLACK_CLIENT_SECRET") is not None
-        ):
-            # initialize with the default settings
-            oauth_settings = AsyncOAuthSettings()
-
-            if oauth_flow is None and installation_store is None:
-                # show info-level log for avoiding confusions
-                self._framework_logger.info(info_default_oauth_settings_loaded())
-
-        if oauth_flow:
-            if not isinstance(oauth_flow, AsyncOAuthFlow):
-                raise BoltError(error_oauth_flow_invalid_type_async())
-
-            self._async_oauth_flow = oauth_flow
-            installation_store = select_consistent_installation_store(
-                client_id=self._async_oauth_flow.client_id,
-                app_store=self._async_installation_store,
-                oauth_flow_store=self._async_oauth_flow.settings.installation_store,
-                logger=self._framework_logger,
-            )
-            self._async_installation_store = installation_store
-            if installation_store is not None:
-                self._async_oauth_flow.settings.installation_store = installation_store
-
-            if self._async_oauth_flow._async_client is None:
-                self._async_oauth_flow._async_client = self._async_client
-            if self._async_authorize is None:
-                self._async_authorize = self._async_oauth_flow.settings.authorize
-        elif oauth_settings is not None:
-            if not isinstance(oauth_settings, AsyncOAuthSettings):
-                raise BoltError(error_oauth_settings_invalid_type_async())
-
-            installation_store = select_consistent_installation_store(
-                client_id=oauth_settings.client_id,
-                app_store=self._async_installation_store,
-                oauth_flow_store=oauth_settings.installation_store,
-                logger=self._framework_logger,
-            )
-            self._async_installation_store = installation_store
-            if installation_store is not None:
-                oauth_settings.installation_store = installation_store
-
-            self._async_oauth_flow = AsyncOAuthFlow(client=self._async_client, logger=self.logger, settings=oauth_settings)
-            if self._async_authorize is None:
-                self._async_authorize = self._async_oauth_flow.settings.authorize
-            self._async_authorize.token_rotation_expiration_minutes = oauth_settings.token_rotation_expiration_minutes  # type: ignore[attr-defined] # noqa: E501
-
-        if (self._async_installation_store is not None or self._async_authorize is not None) and self._token is not None:
-            self._token = None
-            self._framework_logger.warning(warning_token_skipped())
-
-        # after setting bot_only here, __init__ cannot replace authorize function
-        if installation_store_bot_only is not None and self._async_oauth_flow is not None:
-            app_bot_only = installation_store_bot_only or False
-            oauth_flow_bot_only = self._async_oauth_flow.settings.installation_store_bot_only
-            if app_bot_only != oauth_flow_bot_only:
-                self.logger.warning(warning_bot_only_conflicts())
-                self._async_oauth_flow.settings.installation_store_bot_only = app_bot_only
-                self._async_authorize.bot_only = app_bot_only  # type: ignore[union-attr]
-
-        self._async_tokens_revocation_listeners: Optional[AsyncTokenRevocationListeners] = None
-        if self._async_installation_store is not None:
-            self._async_tokens_revocation_listeners = AsyncTokenRevocationListeners(self._async_installation_store)
-
-        # --------------------------------------
-        # Middleware Initialization
-        # --------------------------------------
-
-        self._async_middleware_list: List[AsyncMiddleware] = []
-        self._async_listeners: List[AsyncListener] = []
-
-        self._assistant_thread_context_store = assistant_thread_context_store
-        self._attaching_conversation_kwargs_enabled = attaching_conversation_kwargs_enabled
-
-        self._process_before_response = process_before_response
-        self._async_listener_runner = AsyncioListenerRunner(
-            logger=self._framework_logger,
-            process_before_response=process_before_response,
-            listener_error_handler=AsyncDefaultListenerErrorHandler(logger=self._framework_logger),
-            listener_start_handler=AsyncDefaultListenerStartHandler(logger=self._framework_logger),
-            listener_completion_handler=AsyncDefaultListenerCompletionHandler(logger=self._framework_logger),
-            lazy_listener_runner=AsyncioLazyListenerRunner(
-                logger=self._framework_logger,
-            ),
-        )
-        self._async_middleware_error_handler: AsyncMiddlewareErrorHandler = AsyncDefaultMiddlewareErrorHandler(
-            logger=self._framework_logger,
-        )
-
-        self._init_middleware_list_done = False
-        self._init_async_middleware_list(
-            request_verification_enabled=request_verification_enabled,
-            ignoring_self_events_enabled=ignoring_self_events_enabled,
-            ignoring_self_assistant_message_events_enabled=ignoring_self_assistant_message_events_enabled,
-            ssl_check_enabled=ssl_check_enabled,
-            url_verification_enabled=url_verification_enabled,
-            attaching_function_token_enabled=attaching_function_token_enabled,
-            user_facing_authorize_error_message=user_facing_authorize_error_message,
-        )
-
-        self._server: Optional[AsyncSlackAppServer] = None
-
-    def _init_async_middleware_list(
-        self,
-        request_verification_enabled: bool = True,
-        ignoring_self_events_enabled: bool = True,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-        ssl_check_enabled: bool = True,
-        url_verification_enabled: bool = True,
-        attaching_function_token_enabled: bool = True,
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        if self._init_middleware_list_done:
-            return
-        if ssl_check_enabled is True:
-            self._async_middleware_list.append(
-                AsyncSslCheck(
-                    verification_token=self._verification_token,
-                    base_logger=self._base_logger,
-                )
-            )
-        if request_verification_enabled is True:
-            self._async_middleware_list.append(AsyncRequestVerification(self._signing_secret, base_logger=self._base_logger))
-
-        if self._async_before_authorize is not None:
-            self._async_middleware_list.append(self._async_before_authorize)
-
-        # As authorize is required for making a Bolt app function, we don't offer the flag to disable this
-        if self._async_oauth_flow is None:
-            if self._token:
-                self._async_middleware_list.append(
-                    AsyncSingleTeamAuthorization(
-                        base_logger=self._base_logger,
-                        user_facing_authorize_error_message=user_facing_authorize_error_message,
-                    )
-                )
-            elif self._async_authorize is not None:
-                self._async_middleware_list.append(
-                    AsyncMultiTeamsAuthorization(
-                        authorize=self._async_authorize,
-                        base_logger=self._base_logger,
-                        user_facing_authorize_error_message=user_facing_authorize_error_message,
-                    )
-                )
-            else:
-                raise BoltError(error_token_required())
-        elif self._async_authorize is not None:
-            self._async_middleware_list.append(
-                AsyncMultiTeamsAuthorization(
-                    authorize=self._async_authorize,
-                    base_logger=self._base_logger,
-                    user_token_resolution=self._async_oauth_flow.settings.user_token_resolution,
-                    user_facing_authorize_error_message=user_facing_authorize_error_message,
-                )
-            )
-        else:
-            raise BoltError(error_oauth_flow_or_authorize_required())
-
-        if ignoring_self_events_enabled is True:
-            self._async_middleware_list.append(
-                AsyncIgnoringSelfEvents(
-                    base_logger=self._base_logger,
-                    ignoring_self_assistant_message_events_enabled=ignoring_self_assistant_message_events_enabled,
-                )
-            )
-        if url_verification_enabled is True:
-            self._async_middleware_list.append(AsyncUrlVerification(base_logger=self._base_logger))
-        if attaching_function_token_enabled is True:
-            self._async_middleware_list.append(AsyncAttachingFunctionToken())
-        self._init_middleware_list_done = True
-
-    # -------------------------
-    # accessors
-
-    @property
-    def name(self) -> str:
-        """The name of this app (default: the filename)"""
-        return self._name
-
-    @property
-    def oauth_flow(self) -> Optional[AsyncOAuthFlow]:
-        """Configured `OAuthFlow` object if exists."""
-        return self._async_oauth_flow
-
-    @property
-    def client(self) -> AsyncWebClient:
-        """The singleton `slack_sdk.web.async_client.AsyncWebClient` instance in this app."""
-        return self._async_client
-
-    @property
-    def logger(self) -> logging.Logger:
-        """The logger this app uses."""
-        return self._framework_logger
-
-    @property
-    def installation_store(self) -> Optional[AsyncInstallationStore]:
-        """The `slack_sdk.oauth.AsyncInstallationStore` that can be used in the `authorize` middleware."""
-        return self._async_installation_store
-
-    @property
-    def listener_runner(self) -> AsyncioListenerRunner:
-        """The asyncio-based executor for asynchronously running listeners."""
-        return self._async_listener_runner
-
-    @property
-    def process_before_response(self) -> bool:
-        return self._process_before_response or False
-
-    # -------------------------
-    # standalone server
-
-    from .async_server import AsyncSlackAppServer
-
-    def server(
-        self,
-        port: int = 3000,
-        path: str = "/slack/events",
-        host: Optional[str] = None,
-    ) -> AsyncSlackAppServer:
-        """Configure a web server using AIOHTTP.
-        Refer to https://docs.aiohttp.org/ for more details about AIOHTTP.
-
-        Args:
-            port: The port to listen on (Default: 3000)
-            path: The path to handle request from Slack (Default: `/slack/events`)
-            host: The hostname to serve the web endpoints. (Default: 0.0.0.0)
-        """
-        if self._server is None or self._server.port != port or self._server.path != path:
-            self._server = AsyncSlackAppServer(
-                port=port,
-                path=path,
-                app=self,
-                host=host,
-            )
-        return self._server
-
-    def web_app(self, path: str = "/slack/events", port: int = 3000) -> web.Application:
-        """Returns a `web.Application` instance for aiohttp-devtools users.
-
-            from slack_bolt.async_app import AsyncApp
-            app = AsyncApp()
-
-            @app.event("app_mention")
-            async def event_test(body, say, logger):
-                logger.info(body)
-                await say("What's up?")
-
-            def app_factory():
-                return app.web_app()
-
-            # adev runserver --port 3000 --app-factory app_factory async_app.py
-
-        Args:
-            path: The path to receive incoming requests from Slack
-            port: The port to listen on (Default: 3000)
-        """
-        return self.server(path=path, port=port).web_app
-
-    def start(self, port: int = 3000, path: str = "/slack/events", host: Optional[str] = None) -> None:
-        """Start a web server using AIOHTTP.
-        Refer to https://docs.aiohttp.org/ for more details about AIOHTTP.
-
-        Args:
-            port: The port to listen on (Default: 3000)
-            path: The path to handle request from Slack (Default: `/slack/events`)
-            host: The hostname to serve the web endpoints. (Default: 0.0.0.0)
-        """
-        self.server(port=port, path=path, host=host).start()
-
-    # -------------------------
-    # main dispatcher
-
-    async def async_dispatch(self, req: AsyncBoltRequest) -> BoltResponse:
-        """Applies all middleware and dispatches an incoming request from Slack to the right code path.
-
-        Args:
-            req: An incoming request from Slack.
-
-        Returns:
-            The response generated by this Bolt app.
-        """
-        starting_time = time.time()
-        self._init_context(req)
-
-        resp: Optional[BoltResponse] = BoltResponse(status=200, body="")
-        middleware_state = {"next_called": False}
-
-        async def async_middleware_next():
-            middleware_state["next_called"] = True
-
-        try:
-            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  # type: ignore[arg-type]
-                )
-                if not middleware_state["next_called"]:
-                    if resp is None:
-                        # next() method was not called without providing the response to return to Slack
-                        # This should not be an intentional handling in usual use cases.
-                        resp = BoltResponse(status=404, body={"error": "no next() calls in middleware"})
-                        if self._raise_error_for_unhandled_request is True:
-                            try:
-                                raise BoltUnhandledRequestError(
-                                    request=req,
-                                    current_response=resp,
-                                    last_global_middleware_name=middleware.name,
-                                )
-                            except BoltUnhandledRequestError as e:
-                                await self._async_listener_runner.listener_error_handler.handle(
-                                    error=e,
-                                    request=req,
-                                    response=resp,
-                                )
-                            return resp
-                        self._framework_logger.warning(warning_unhandled_by_global_middleware(middleware.name, req))
-                        return resp
-                    return resp
-
-            for listener in self._async_listeners:
-                listener_name = get_name_for_callable(listener.ack_function)
-                self._framework_logger.debug(debug_checking_listener(listener_name))
-                if await listener.async_matches(req=req, resp=resp):  # type: ignore[arg-type]
-                    # run all the middleware attached to this listener first
-                    middleware_resp, next_was_not_called = await listener.run_async_middleware(
-                        req=req, resp=resp  # type: ignore[arg-type]
-                    )
-                    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] = await self._async_listener_runner.run(
-                        request=req,
-                        response=resp,  # type: ignore[arg-type]
-                        listener_name=listener_name,
-                        listener=listener,
-                    )
-                    if listener_response is not None:
-                        return listener_response
-
-            if resp is None:
-                resp = BoltResponse(status=404, body={"error": "unhandled request"})
-            if self._raise_error_for_unhandled_request is True:
-                try:
-                    raise BoltUnhandledRequestError(
-                        request=req,
-                        current_response=resp,
-                    )
-                except BoltUnhandledRequestError as e:
-                    await self._async_listener_runner.listener_error_handler.handle(
-                        error=e,
-                        request=req,
-                        response=resp,
-                    )
-                return resp
-            return self._handle_unmatched_requests(req, resp)
-
-        except Exception as error:
-            resp = BoltResponse(status=500, body="")
-            await self._async_middleware_error_handler.handle(
-                error=error,
-                request=req,
-                response=resp,
-            )
-            return resp
-
-    def _handle_unmatched_requests(self, req: AsyncBoltRequest, resp: BoltResponse) -> BoltResponse:
-        self._framework_logger.warning(warning_unhandled_request(req))
-        return resp
-
-    # -------------------------
-    # middleware
-
-    def use(self, *args) -> Optional[Callable]:
-        """Refer to `AsyncApp#middleware()` method's docstring for details."""
-        return self.middleware(*args)
-
-    def middleware(self, *args) -> Optional[Callable]:
-        """Registers a new middleware to this app.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.middleware
-            async def middleware_func(logger, body, next):
-                logger.info(f"request body: {body}")
-                await next()
-
-            # Pass a function to this method
-            app.middleware(middleware_func)
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            *args: A function that works as a global middleware.
-        """
-        if len(args) > 0:
-            middleware_or_callable = args[0]
-            if isinstance(middleware_or_callable, AsyncMiddleware):
-                middleware: AsyncMiddleware = middleware_or_callable
-                self._async_middleware_list.append(middleware)
-                if isinstance(middleware, AsyncAssistant) and middleware.thread_context_store is not None:
-                    self._assistant_thread_context_store = middleware.thread_context_store
-            elif callable(middleware_or_callable):
-                self._async_middleware_list.append(
-                    AsyncCustomMiddleware(
-                        app_name=self.name,
-                        func=middleware_or_callable,
-                        base_logger=self._base_logger,
-                    )
-                )
-                return middleware_or_callable
-            else:
-                raise BoltError(f"Unexpected type for a middleware ({type(middleware_or_callable)})")
-        return None
-
-    def assistant(self, assistant: AsyncAssistant) -> Optional[Callable]:
-        return self.middleware(assistant)
-
-    # -------------------------
-    # Workflows: Steps from apps
-
-    def step(
-        self,
-        callback_id: Union[str, Pattern, AsyncWorkflowStep, AsyncWorkflowStepBuilder],
-        edit: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None,
-        save: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None,
-        execute: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Registers a new step from app listener.
-
-        Unlike others, this method doesn't behave as a decorator.
-        If you want to register a step from app by a decorator, use `AsyncWorkflowStepBuilder`'s methods.
-
-            # Create a new WorkflowStep instance
-            from slack_bolt.workflows.async_step import AsyncWorkflowStep
-            ws = AsyncWorkflowStep(
-                callback_id="add_task",
-                edit=edit,
-                save=save,
-                execute=execute,
-            )
-            # Pass Step to set up listeners
-            app.step(ws)
-
-        Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-        For further information about AsyncWorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            callback_id: The Callback ID for this step from app
-            edit: The function for displaying a modal in the Workflow Builder
-            save: The function for handling configuration in the Workflow Builder
-            execute: The function for handling the step execution
-        """
-        warnings.warn(
-            (
-                "Steps from apps for legacy workflows are now deprecated. "
-                "Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/"
-            ),
-            category=DeprecationWarning,
-        )
-        step = callback_id
-        if isinstance(callback_id, (str, Pattern)):
-            step = AsyncWorkflowStep(
-                callback_id=callback_id,
-                edit=edit,  # type: ignore[arg-type]
-                save=save,  # type: ignore[arg-type]
-                execute=execute,  # type: ignore[arg-type]
-                base_logger=self._base_logger,
-            )
-        elif isinstance(step, AsyncWorkflowStepBuilder):
-            step = step.build(base_logger=self._base_logger)
-        elif not isinstance(step, AsyncWorkflowStep):
-            raise BoltError(f"Invalid step object ({type(step)})")
-
-        self.use(AsyncWorkflowStepMiddleware(step))
-
-    # -------------------------
-    # global error handler
-
-    def error(
-        self, func: Callable[..., Awaitable[Optional[BoltResponse]]]
-    ) -> Callable[..., Awaitable[Optional[BoltResponse]]]:
-        """Updates the global error handler. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.error
-            async def custom_error_handler(error, body, logger):
-                logger.exception(f"Error: {error}")
-                logger.info(f"Request body: {body}")
-
-            # Pass a function to this method
-            app.error(custom_error_handler)
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            func: The function that is supposed to be executed
-                when getting an unhandled error in Bolt app.
-        """
-        if not is_callable_coroutine(func):
-            name = get_name_for_callable(func)
-            raise BoltError(error_listener_function_must_be_coro_func(name))
-        self._async_listener_runner.listener_error_handler = AsyncCustomListenerErrorHandler(
-            logger=self._framework_logger,
-            func=func,
-        )
-        self._async_middleware_error_handler = AsyncCustomMiddlewareErrorHandler(
-            logger=self._framework_logger,
-            func=func,
-        )
-        return func
-
-    # -------------------------
-    # events
-
-    def event(
-        self,
-        event: Union[
-            str,
-            Pattern,
-            Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]],
-        ],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new event listener. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.event("team_join")
-            async def ask_for_introduction(event, say):
-                welcome_channel_id = "C12345"
-                user_id = event["user"]
-                text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-                await say(text=text, channel=welcome_channel_id)
-
-            # Pass a function to this method
-            app.event("team_join")(ask_for_introduction)
-
-        Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            event: The conditions that match a request payload.
-                If you pass a dict for this, you can have type, subtype in the constraint.
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.event(event, True, base_logger=self._base_logger)
-            if self._attaching_conversation_kwargs_enabled:
-                middleware.insert(0, AsyncAttachingConversationKwargs(self._assistant_thread_context_store))
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-        return __call__
-
-    def message(
-        self,
-        keyword: Union[str, Pattern] = "",
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new message event listener. This method can be used as either a decorator or a method.
-        Check the `App#event` method's docstring for details.
-
-            # Use this method as a decorator
-            @app.message(":wave:")
-            async def say_hello(message, say):
-                user = message['user']
-                await say(f"Hi there, <@{user}>!")
-
-            # Pass a function to this method
-            app.message(":wave:")(say_hello)
-
-        Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            keyword: The keyword to match
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-        matchers = list(matchers) if matchers else []
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            constraints = {
-                "type": "message",
-                "subtype": (
-                    # In most cases, new message events come with no subtype.
-                    None,
-                    # As of Jan 2021, most bot messages no longer have the subtype bot_message.
-                    # By contrast, messages posted using classic app's bot token still have the subtype.
-                    "bot_message",
-                    # If an end-user posts a message with "Also send to #channel" checked,
-                    # the message event comes with this subtype.
-                    "thread_broadcast",
-                    # If an end-user posts a message with attached files,
-                    # the message event comes with this subtype.
-                    "file_share",
-                ),
-            }
-            primary_matcher = builtin_matchers.message_event(
-                constraints=constraints,
-                keyword=keyword,
-                asyncio=True,
-                base_logger=self._base_logger,
-            )
-            if self._attaching_conversation_kwargs_enabled:
-                middleware.insert(0, AsyncAttachingConversationKwargs(self._assistant_thread_context_store))
-            middleware.insert(0, AsyncMessageListenerMatches(keyword))
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-        return __call__
-
-    def function(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-        auto_acknowledge: bool = True,
-        ack_timeout: int = 3,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[BoltResponse]]]]:
-        """Registers a new Function listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.function("reverse")
-            async def reverse_string(ack: AsyncAck, inputs: dict, complete: AsyncComplete, fail: AsyncFail):
-                try:
-                    await ack()
-                    string_to_reverse = inputs["stringToReverse"]
-                    await complete({"reverseString": string_to_reverse[::-1]})
-                except Exception as e:
-                    await fail(f"Cannot reverse string (error: {e})")
-                    raise e
-
-            # Pass a function to this method
-            app.function("reverse")(reverse_string)
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            callback_id: The callback id to identify the function
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-        if auto_acknowledge is True:
-            if ack_timeout != 3:
-                self._framework_logger.warning(warning_ack_timeout_has_no_effect(callback_id, ack_timeout))
-
-        matchers = list(matchers) if matchers else []
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.function_executed(
-                callback_id=callback_id, base_logger=self._base_logger, asyncio=True
-            )
-            return self._register_listener(functions, primary_matcher, matchers, middleware, auto_acknowledge, ack_timeout)
-
-        return __call__
-
-    # -------------------------
-    # slash commands
-
-    def command(
-        self,
-        command: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new slash command listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.command("/echo")
-            async def repeat_text(ack, say, command):
-                # Acknowledge command request
-                await ack()
-                await say(f"{command['text']}")
-
-            # Pass a function to this method
-            app.command("/echo")(repeat_text)
-
-        Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            command: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.command(command, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # shortcut
-
-    def shortcut(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new shortcut listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.shortcut("open_modal")
-            async def open_modal(ack, body, client):
-                # Acknowledge the command request
-                await ack()
-                # Call views_open with the built-in client
-                await client.views_open(
-                    # Pass a valid trigger_id within 3 seconds of receiving it
-                    trigger_id=body["trigger_id"],
-                    # View payload
-                    view={ ... }
-                )
-
-            # Pass a function to this method
-            app.shortcut("open_modal")(open_modal)
-
-        Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload.
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.shortcut(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def global_shortcut(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new global shortcut listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.global_shortcut(callback_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def message_shortcut(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new message shortcut listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.message_shortcut(callback_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # action
-
-    def action(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new action listener. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.action("approve_button")
-            async def update_message(ack):
-                await ack()
-
-            # Pass a function to this method
-            app.action("approve_button")(update_message)
-
-        * Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`.
-        * Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`.
-        * Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.action(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def block_action(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `block_actions` action listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.block_action(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def attachment_action(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `interactive_message` action listener.
-        Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.attachment_action(callback_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_submission(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `dialog_submission` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_submission(callback_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_cancellation(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `dialog_submission` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_cancellation(callback_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # view
-
-    def view(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `view_submission`/`view_closed` event listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.view("view_1")
-            async def handle_submission(ack, body, client, view):
-                # Assume there's an input block with `block_c` as the block_id and `dreamy_input`
-                hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-                user = body["user"]["id"]
-                # Validate the inputs
-                errors = {}
-                if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-                    errors["block_c"] = "The value must be longer than 5 characters"
-                if len(errors) > 0:
-                    await ack(response_action="errors", errors=errors)
-                    return
-                # Acknowledge the view_submission event and close the modal
-                await ack()
-                # Do whatever you want with the input data - here we're saving it to a DB
-
-            # Pass a function to this method
-            app.view("view_1")(handle_submission)
-
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def view_submission(
-        self,
-        constraints: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `view_submission` listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for
-        details.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view_submission(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def view_closed(
-        self,
-        constraints: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `view_closed` listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view_closed(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # options
-
-    def options(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new options listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.options("menu_selection")
-            async def show_menu_options(ack):
-                options = [
-                    {
-                        "text": {"type": "plain_text", "text": "Option 1"},
-                        "value": "1-1",
-                    },
-                    {
-                        "text": {"type": "plain_text", "text": "Option 2"},
-                        "value": "1-2",
-                    },
-                ]
-                await ack(options=options)
-
-            # Pass a function to this method
-            app.options("menu_selection")(show_menu_options)
-
-        Refer to the following documents for details:
-
-        * https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select
-        * https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.options(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def block_suggestion(
-        self,
-        action_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `block_suggestion` listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.block_suggestion(action_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_suggestion(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `dialog_suggestion` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_suggestion(callback_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # built-in listener functions
-
-    def default_tokens_revoked_event_listener(
-        self,
-    ) -> Callable[..., Awaitable[Optional[BoltResponse]]]:
-        if self._async_tokens_revocation_listeners is None:
-            raise BoltError(error_installation_store_required_for_builtin_listeners())
-        return self._async_tokens_revocation_listeners.handle_tokens_revoked_events
-
-    def default_app_uninstalled_event_listener(
-        self,
-    ) -> Callable[..., Awaitable[Optional[BoltResponse]]]:
-        if self._async_tokens_revocation_listeners is None:
-            raise BoltError(error_installation_store_required_for_builtin_listeners())
-        return self._async_tokens_revocation_listeners.handle_app_uninstalled_events
-
-    def enable_token_revocation_listeners(self) -> None:
-        self.event("tokens_revoked")(self.default_tokens_revoked_event_listener())
-        self.event("app_uninstalled")(self.default_app_uninstalled_event_listener())
-
-    # -------------------------
-
-    def _init_context(self, req: AsyncBoltRequest):
-        req.context["logger"] = get_bolt_app_logger(app_name=self.name, base_logger=self._base_logger)
-        req.context["token"] = self._token
-        # Prior to version 1.15, when the token is static, self._client was passed to `req.context`.
-        # The intention was to avoid creating a new instance per request
-        # in the interest of runtime performance/memory footprint optimization.
-        # However, developers may want to replace the token held by req.context.client in some situations.
-        # In this case, this behavior can result in thread-unsafe data modification on `self._client`.
-        # (`self._client` a.k.a. `app.client` is a singleton object per an App instance)
-        # Thus, we've changed the behavior to create a new instance per request regardless of token argument
-        # in the App initialization starting v1.15.
-        # The overhead brought by this change is slight so that we believe that it is ignorable in any cases.
-        client_per_request: AsyncWebClient = AsyncWebClient(
-            token=self._token,  # this can be None, and it can be set later on
-            base_url=self._async_client.base_url,
-            timeout=self._async_client.timeout,
-            ssl=self._async_client.ssl,
-            proxy=self._async_client.proxy,
-            session=self._async_client.session,
-            trust_env_in_session=self._async_client.trust_env_in_session,
-            headers=self._async_client.headers,
-            team_id=req.context.team_id,
-            logger=self._async_client.logger,
-            retry_handlers=(
-                self._async_client.retry_handlers.copy() if self._async_client.retry_handlers is not None else None
-            ),
-        )
-        req.context["client"] = client_per_request
-
-        # Most apps do not need this "listener_runner" instance.
-        # It is intended for apps that start lazy listeners from their custom global middleware.
-        req.context["listener_runner"] = self.listener_runner
-
-    @staticmethod
-    def _to_listener_functions(
-        kwargs: dict,
-    ) -> Optional[Sequence[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        if kwargs:
-            functions = [kwargs["ack"]]
-            for sub in kwargs["lazy"]:
-                functions.append(sub)
-            return functions
-        return None
-
-    def _register_listener(
-        self,
-        functions: Sequence[Callable[..., Awaitable[Optional[BoltResponse]]]],
-        primary_matcher: AsyncListenerMatcher,
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]],
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]],
-        auto_acknowledgement: bool = False,
-        ack_timeout: int = 3,
-    ) -> Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]:
-        value_to_return = None
-        if not isinstance(functions, list):
-            functions = list(functions)
-        if len(functions) == 1:
-            # In the case where the function is registered using decorator,
-            # the registration should return the original function.
-            value_to_return = functions[0]
-
-        for func in functions:
-            if not is_callable_coroutine(func):
-                name = get_name_for_callable(func)
-                raise BoltError(error_listener_function_must_be_coro_func(name))
-
-        listener_matchers: List[AsyncListenerMatcher] = [
-            AsyncCustomListenerMatcher(app_name=self.name, func=f, base_logger=self._base_logger) for f in (matchers or [])
-        ]
-        listener_matchers.insert(0, primary_matcher)
-        listener_middleware = []
-        for m in middleware or []:
-            if isinstance(m, AsyncMiddleware):
-                listener_middleware.append(m)
-            elif callable(m) and is_callable_coroutine(m):
-                listener_middleware.append(AsyncCustomMiddleware(app_name=self.name, func=m, base_logger=self._base_logger))
-            else:
-                raise ValueError(error_unexpected_listener_middleware(type(m)))
-
-        self._async_listeners.append(
-            AsyncCustomListener(
-                app_name=self.name,
-                ack_function=functions.pop(0),
-                lazy_functions=functions,  # type: ignore[arg-type]
-                matchers=listener_matchers,
-                middleware=listener_middleware,
-                auto_acknowledgement=auto_acknowledgement,
-                ack_timeout=ack_timeout,
-                base_logger=self._base_logger,
-            )
-        )
-
-        return value_to_return
-
-

Bolt App that provides functionalities to register middleware/listeners.

-
import os
-from slack_bolt.async_app import AsyncApp
-
-# Initializes your app with your bot token and signing secret
-app = AsyncApp(
-    token=os.environ.get("SLACK_BOT_TOKEN"),
-    signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
-)
-
-# Listens to incoming messages that contain "hello"
-@app.message("hello")
-async def message_hello(message, say):  # async function
-    # say() sends a message to the channel where the event was triggered
-    await say(f"Hey there <@{message['user']}>!")
-
-# Start your app
-if __name__ == "__main__":
-    app.start(port=int(os.environ.get("PORT", 3000)))
-
-

Refer to https://docs.slack.dev/tools/bolt-python/concepts/async for details.

-

If you would like to build an OAuth app for enabling the app to run with multiple workspaces, -refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app.

-

Args

-
-
logger
-
The custom logger that can be used in this app.
-
name
-
The application name that will be used in logging. If absent, the source file name will be used.
-
process_before_response
-
True if this app runs on Function as a Service. (Default: False)
-
raise_error_for_unhandled_request
-
True if you want to raise exceptions for unhandled requests -and use @app.error listeners instead of -the built-in handler, which pints warning logs and returns 404 to Slack (Default: False)
-
signing_secret
-
The Signing Secret value used for verifying requests from Slack.
-
token
-
The bot/user access token required only for single-workspace app.
-
client
-
The singleton slack_sdk.web.async_client.AsyncWebClient instance for this app.
-
before_authorize
-
A global middleware that can be executed right before authorize function
-
authorize
-
The function to authorize an incoming request from Slack -by checking if there is a team/user in the installation data.
-
user_facing_authorize_error_message
-
The user-facing error message to display -when the app is installed but the installation is not managed by this app's installation store
-
installation_store
-
The module offering save/find operations of installation data
-
installation_store_bot_only
-
Use AsyncInstallationStore#async_find_bot() if True (Default: False)
-
request_verification_enabled
-
False if you would like to disable the built-in middleware (Default: True). -AsyncRequestVerification is a built-in middleware that verifies the signature in HTTP Mode requests. -Make sure if it's safe enough when you turn a built-in middleware off. -We strongly recommend using RequestVerification for better security. -If you have a proxy that verifies request signature in front of the Bolt app, -it's totally fine to disable RequestVerification to avoid duplication of work. -Don't turn it off just for easiness of development.
-
ignoring_self_events_enabled
-
False if you would like to disable the built-in middleware (Default: True). -AsyncIgnoringSelfEvents is a built-in middleware that enables Bolt apps to easily skip the events -generated by this app's bot user (this is useful for avoiding code error causing an infinite loop).
-
ignoring_self_assistant_message_events_enabled
-
False if you would like to disable the built-in middleware. -IgnoringSelfEvents for this app's bot user message events within an assistant thread -This is useful for avoiding code error causing an infinite loop; Default: True
-
url_verification_enabled
-
False if you would like to disable the built-in middleware (Default: True). -AsyncUrlVerification is a built-in middleware that handles url_verification requests -that verify the endpoint for Events API in HTTP Mode requests.
-
ssl_check_enabled
-
bool = False if you would like to disable the built-in middleware (Default: True). -AsyncSslCheck is a built-in middleware that handles ssl_check requests from Slack.
-
attaching_function_token_enabled
-
False if you would like to disable the built-in middleware (Default: True). -AsyncAttachingFunctionToken is a built-in middleware that injects the just-in-time workflow-execution token -when your app receives function_executed or interactivity events scoped to a custom step.
-
oauth_settings
-
The settings related to Slack app installation flow (OAuth flow)
-
oauth_flow
-
Instantiated slack_bolt.oauth.AsyncOAuthFlow. This is always prioritized over oauth_settings.
-
verification_token
-
Deprecated verification mechanism. This can be used only for ssl_check requests.
-
assistant_thread_context_store
-
Custom AssistantThreadContext store (Default: the built-in implementation, -which uses a parent message's metadata to store the latest context)
-
-

Class variables

-
-
var AsyncSlackAppServer
-
-

The type of the None singleton.

-
-
-

Instance variables

-
-
prop client : slack_sdk.web.async_client.AsyncWebClient
-
-
- -Expand source code - -
@property
-def client(self) -> AsyncWebClient:
-    """The singleton `slack_sdk.web.async_client.AsyncWebClient` instance in this app."""
-    return self._async_client
-
-

The singleton slack_sdk.web.async_client.AsyncWebClient instance in this app.

-
-
prop installation_store : slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore | None
-
-
- -Expand source code - -
@property
-def installation_store(self) -> Optional[AsyncInstallationStore]:
-    """The `slack_sdk.oauth.AsyncInstallationStore` that can be used in the `authorize` middleware."""
-    return self._async_installation_store
-
-

The slack_sdk.oauth.AsyncInstallationStore that can be used in the authorize middleware.

-
-
prop listener_runnerAsyncioListenerRunner
-
-
- -Expand source code - -
@property
-def listener_runner(self) -> AsyncioListenerRunner:
-    """The asyncio-based executor for asynchronously running listeners."""
-    return self._async_listener_runner
-
-

The asyncio-based executor for asynchronously running listeners.

-
-
prop logger : logging.Logger
-
-
- -Expand source code - -
@property
-def logger(self) -> logging.Logger:
-    """The logger this app uses."""
-    return self._framework_logger
-
-

The logger this app uses.

-
-
prop name : str
-
-
- -Expand source code - -
@property
-def name(self) -> str:
-    """The name of this app (default: the filename)"""
-    return self._name
-
-

The name of this app (default: the filename)

-
-
prop oauth_flowAsyncOAuthFlow | None
-
-
- -Expand source code - -
@property
-def oauth_flow(self) -> Optional[AsyncOAuthFlow]:
-    """Configured `OAuthFlow` object if exists."""
-    return self._async_oauth_flow
-
-

Configured OAuthFlow object if exists.

-
-
prop process_before_response : bool
-
-
- -Expand source code - -
@property
-def process_before_response(self) -> bool:
-    return self._process_before_response or False
-
-
-
-
-

Methods

-
-
-def action(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def action(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new action listener. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.action("approve_button")
-        async def update_message(ack):
-            await ack()
-
-        # Pass a function to this method
-        app.action("approve_button")(update_message)
-
-    * Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`.
-    * Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`.
-    * Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.action(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new action listener. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.action("approve_button")
-async def update_message(ack):
-    await ack()
-
-# Pass a function to this method
-app.action("approve_button")(update_message)
-
- -

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def assistant(self,
assistant: AsyncAssistant) ‑> Callable | None
-
-
-
- -Expand source code - -
def assistant(self, assistant: AsyncAssistant) -> Optional[Callable]:
-    return self.middleware(assistant)
-
-
-
-
-async def async_dispatch(self,
req: AsyncBoltRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
async def async_dispatch(self, req: AsyncBoltRequest) -> BoltResponse:
-    """Applies all middleware and dispatches an incoming request from Slack to the right code path.
-
-    Args:
-        req: An incoming request from Slack.
-
-    Returns:
-        The response generated by this Bolt app.
-    """
-    starting_time = time.time()
-    self._init_context(req)
-
-    resp: Optional[BoltResponse] = BoltResponse(status=200, body="")
-    middleware_state = {"next_called": False}
-
-    async def async_middleware_next():
-        middleware_state["next_called"] = True
-
-    try:
-        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  # type: ignore[arg-type]
-            )
-            if not middleware_state["next_called"]:
-                if resp is None:
-                    # next() method was not called without providing the response to return to Slack
-                    # This should not be an intentional handling in usual use cases.
-                    resp = BoltResponse(status=404, body={"error": "no next() calls in middleware"})
-                    if self._raise_error_for_unhandled_request is True:
-                        try:
-                            raise BoltUnhandledRequestError(
-                                request=req,
-                                current_response=resp,
-                                last_global_middleware_name=middleware.name,
-                            )
-                        except BoltUnhandledRequestError as e:
-                            await self._async_listener_runner.listener_error_handler.handle(
-                                error=e,
-                                request=req,
-                                response=resp,
-                            )
-                        return resp
-                    self._framework_logger.warning(warning_unhandled_by_global_middleware(middleware.name, req))
-                    return resp
-                return resp
-
-        for listener in self._async_listeners:
-            listener_name = get_name_for_callable(listener.ack_function)
-            self._framework_logger.debug(debug_checking_listener(listener_name))
-            if await listener.async_matches(req=req, resp=resp):  # type: ignore[arg-type]
-                # run all the middleware attached to this listener first
-                middleware_resp, next_was_not_called = await listener.run_async_middleware(
-                    req=req, resp=resp  # type: ignore[arg-type]
-                )
-                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] = await self._async_listener_runner.run(
-                    request=req,
-                    response=resp,  # type: ignore[arg-type]
-                    listener_name=listener_name,
-                    listener=listener,
-                )
-                if listener_response is not None:
-                    return listener_response
-
-        if resp is None:
-            resp = BoltResponse(status=404, body={"error": "unhandled request"})
-        if self._raise_error_for_unhandled_request is True:
-            try:
-                raise BoltUnhandledRequestError(
-                    request=req,
-                    current_response=resp,
-                )
-            except BoltUnhandledRequestError as e:
-                await self._async_listener_runner.listener_error_handler.handle(
-                    error=e,
-                    request=req,
-                    response=resp,
-                )
-            return resp
-        return self._handle_unmatched_requests(req, resp)
-
-    except Exception as error:
-        resp = BoltResponse(status=500, body="")
-        await self._async_middleware_error_handler.handle(
-            error=error,
-            request=req,
-            response=resp,
-        )
-        return resp
-
-

Applies all middleware and dispatches an incoming request from Slack to the right code path.

-

Args

-
-
req
-
An incoming request from Slack.
-
-

Returns

-

The response generated by this Bolt app.

-
-
-def attachment_action(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def attachment_action(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `interactive_message` action listener.
-    Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.attachment_action(callback_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new interactive_message action listener. -Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details.

-
-
-def block_action(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def block_action(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `block_actions` action listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.block_action(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new block_actions action listener. -Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.

-
-
-def block_suggestion(self,
action_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def block_suggestion(
-    self,
-    action_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `block_suggestion` listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.block_suggestion(action_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new block_suggestion listener.

-
-
-def command(self,
command: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def command(
-    self,
-    command: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new slash command listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.command("/echo")
-        async def repeat_text(ack, say, command):
-            # Acknowledge command request
-            await ack()
-            await say(f"{command['text']}")
-
-        # Pass a function to this method
-        app.command("/echo")(repeat_text)
-
-    Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        command: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.command(command, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new slash command listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.command("/echo")
-async def repeat_text(ack, say, command):
-    # Acknowledge command request
-    await ack()
-    await say(f"{command['text']}")
-
-# Pass a function to this method
-app.command("/echo")(repeat_text)
-
-

Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
command
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def default_app_uninstalled_event_listener(self) ‑> Callable[..., Awaitable[BoltResponse | None]] -
-
-
- -Expand source code - -
def default_app_uninstalled_event_listener(
-    self,
-) -> Callable[..., Awaitable[Optional[BoltResponse]]]:
-    if self._async_tokens_revocation_listeners is None:
-        raise BoltError(error_installation_store_required_for_builtin_listeners())
-    return self._async_tokens_revocation_listeners.handle_app_uninstalled_events
-
-
-
-
-def default_tokens_revoked_event_listener(self) ‑> Callable[..., Awaitable[BoltResponse | None]] -
-
-
- -Expand source code - -
def default_tokens_revoked_event_listener(
-    self,
-) -> Callable[..., Awaitable[Optional[BoltResponse]]]:
-    if self._async_tokens_revocation_listeners is None:
-        raise BoltError(error_installation_store_required_for_builtin_listeners())
-    return self._async_tokens_revocation_listeners.handle_tokens_revoked_events
-
-
-
-
-def dialog_cancellation(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def dialog_cancellation(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `dialog_submission` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_cancellation(callback_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_submission listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dialog_submission(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def dialog_submission(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `dialog_submission` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_submission(callback_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_submission listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dialog_suggestion(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def dialog_suggestion(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `dialog_suggestion` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_suggestion(callback_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_suggestion listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def enable_token_revocation_listeners(self) ‑> None -
-
-
- -Expand source code - -
def enable_token_revocation_listeners(self) -> None:
-    self.event("tokens_revoked")(self.default_tokens_revoked_event_listener())
-    self.event("app_uninstalled")(self.default_app_uninstalled_event_listener())
-
-
-
-
-def error(self,
func: Callable[..., Awaitable[BoltResponse | None]]) ‑> Callable[..., Awaitable[BoltResponse | None]]
-
-
-
- -Expand source code - -
def error(
-    self, func: Callable[..., Awaitable[Optional[BoltResponse]]]
-) -> Callable[..., Awaitable[Optional[BoltResponse]]]:
-    """Updates the global error handler. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.error
-        async def custom_error_handler(error, body, logger):
-            logger.exception(f"Error: {error}")
-            logger.info(f"Request body: {body}")
-
-        # Pass a function to this method
-        app.error(custom_error_handler)
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        func: The function that is supposed to be executed
-            when getting an unhandled error in Bolt app.
-    """
-    if not is_callable_coroutine(func):
-        name = get_name_for_callable(func)
-        raise BoltError(error_listener_function_must_be_coro_func(name))
-    self._async_listener_runner.listener_error_handler = AsyncCustomListenerErrorHandler(
-        logger=self._framework_logger,
-        func=func,
-    )
-    self._async_middleware_error_handler = AsyncCustomMiddlewareErrorHandler(
-        logger=self._framework_logger,
-        func=func,
-    )
-    return func
-
-

Updates the global error handler. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.error
-async def custom_error_handler(error, body, logger):
-    logger.exception(f"Error: {error}")
-    logger.info(f"Request body: {body}")
-
-# Pass a function to this method
-app.error(custom_error_handler)
-
-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
func
-
The function that is supposed to be executed -when getting an unhandled error in Bolt app.
-
-
-
-def event(self,
event: str | Pattern | Dict[str, str | Sequence[str | Pattern | None] | None],
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def event(
-    self,
-    event: Union[
-        str,
-        Pattern,
-        Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]],
-    ],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new event listener. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.event("team_join")
-        async def ask_for_introduction(event, say):
-            welcome_channel_id = "C12345"
-            user_id = event["user"]
-            text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-            await say(text=text, channel=welcome_channel_id)
-
-        # Pass a function to this method
-        app.event("team_join")(ask_for_introduction)
-
-    Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        event: The conditions that match a request payload.
-            If you pass a dict for this, you can have type, subtype in the constraint.
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.event(event, True, base_logger=self._base_logger)
-        if self._attaching_conversation_kwargs_enabled:
-            middleware.insert(0, AsyncAttachingConversationKwargs(self._assistant_thread_context_store))
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-    return __call__
-
-

Registers a new event listener. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.event("team_join")
-async def ask_for_introduction(event, say):
-    welcome_channel_id = "C12345"
-    user_id = event["user"]
-    text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-    await say(text=text, channel=welcome_channel_id)
-
-# Pass a function to this method
-app.event("team_join")(ask_for_introduction)
-
-

Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
event
-
The conditions that match a request payload. -If you pass a dict for this, you can have type, subtype in the constraint.
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def function(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None,
auto_acknowledge: bool = True,
ack_timeout: int = 3) ‑> Callable[..., Callable[..., Awaitable[BoltResponse]] | None]
-
-
-
- -Expand source code - -
def function(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    auto_acknowledge: bool = True,
-    ack_timeout: int = 3,
-) -> Callable[..., Optional[Callable[..., Awaitable[BoltResponse]]]]:
-    """Registers a new Function listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.function("reverse")
-        async def reverse_string(ack: AsyncAck, inputs: dict, complete: AsyncComplete, fail: AsyncFail):
-            try:
-                await ack()
-                string_to_reverse = inputs["stringToReverse"]
-                await complete({"reverseString": string_to_reverse[::-1]})
-            except Exception as e:
-                await fail(f"Cannot reverse string (error: {e})")
-                raise e
-
-        # Pass a function to this method
-        app.function("reverse")(reverse_string)
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        callback_id: The callback id to identify the function
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-    if auto_acknowledge is True:
-        if ack_timeout != 3:
-            self._framework_logger.warning(warning_ack_timeout_has_no_effect(callback_id, ack_timeout))
-
-    matchers = list(matchers) if matchers else []
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.function_executed(
-            callback_id=callback_id, base_logger=self._base_logger, asyncio=True
-        )
-        return self._register_listener(functions, primary_matcher, matchers, middleware, auto_acknowledge, ack_timeout)
-
-    return __call__
-
-

Registers a new Function listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.function("reverse")
-async def reverse_string(ack: AsyncAck, inputs: dict, complete: AsyncComplete, fail: AsyncFail):
-    try:
-        await ack()
-        string_to_reverse = inputs["stringToReverse"]
-        await complete({"reverseString": string_to_reverse[::-1]})
-    except Exception as e:
-        await fail(f"Cannot reverse string (error: {e})")
-        raise e
-
-# Pass a function to this method
-app.function("reverse")(reverse_string)
-
-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
callback_id
-
The callback id to identify the function
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def global_shortcut(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def global_shortcut(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new global shortcut listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.global_shortcut(callback_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new global shortcut listener.

-
-
-def message(self,
keyword: str | Pattern = '',
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def message(
-    self,
-    keyword: Union[str, Pattern] = "",
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new message event listener. This method can be used as either a decorator or a method.
-    Check the `App#event` method's docstring for details.
-
-        # Use this method as a decorator
-        @app.message(":wave:")
-        async def say_hello(message, say):
-            user = message['user']
-            await say(f"Hi there, <@{user}>!")
-
-        # Pass a function to this method
-        app.message(":wave:")(say_hello)
-
-    Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        keyword: The keyword to match
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-    matchers = list(matchers) if matchers else []
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        constraints = {
-            "type": "message",
-            "subtype": (
-                # In most cases, new message events come with no subtype.
-                None,
-                # As of Jan 2021, most bot messages no longer have the subtype bot_message.
-                # By contrast, messages posted using classic app's bot token still have the subtype.
-                "bot_message",
-                # If an end-user posts a message with "Also send to #channel" checked,
-                # the message event comes with this subtype.
-                "thread_broadcast",
-                # If an end-user posts a message with attached files,
-                # the message event comes with this subtype.
-                "file_share",
-            ),
-        }
-        primary_matcher = builtin_matchers.message_event(
-            constraints=constraints,
-            keyword=keyword,
-            asyncio=True,
-            base_logger=self._base_logger,
-        )
-        if self._attaching_conversation_kwargs_enabled:
-            middleware.insert(0, AsyncAttachingConversationKwargs(self._assistant_thread_context_store))
-        middleware.insert(0, AsyncMessageListenerMatches(keyword))
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-    return __call__
-
-

Registers a new message event listener. This method can be used as either a decorator or a method. -Check the App#event method's docstring for details.

-
# Use this method as a decorator
-@app.message(":wave:")
-async def say_hello(message, say):
-    user = message['user']
-    await say(f"Hi there, <@{user}>!")
-
-# Pass a function to this method
-app.message(":wave:")(say_hello)
-
-

Refer to https://docs.slack.dev/reference/events/message/ for details of message events.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
keyword
-
The keyword to match
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def message_shortcut(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def message_shortcut(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new message shortcut listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.message_shortcut(callback_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new message shortcut listener.

-
-
-def middleware(self, *args) ‑> Callable | None -
-
-
- -Expand source code - -
def middleware(self, *args) -> Optional[Callable]:
-    """Registers a new middleware to this app.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.middleware
-        async def middleware_func(logger, body, next):
-            logger.info(f"request body: {body}")
-            await next()
-
-        # Pass a function to this method
-        app.middleware(middleware_func)
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        *args: A function that works as a global middleware.
-    """
-    if len(args) > 0:
-        middleware_or_callable = args[0]
-        if isinstance(middleware_or_callable, AsyncMiddleware):
-            middleware: AsyncMiddleware = middleware_or_callable
-            self._async_middleware_list.append(middleware)
-            if isinstance(middleware, AsyncAssistant) and middleware.thread_context_store is not None:
-                self._assistant_thread_context_store = middleware.thread_context_store
-        elif callable(middleware_or_callable):
-            self._async_middleware_list.append(
-                AsyncCustomMiddleware(
-                    app_name=self.name,
-                    func=middleware_or_callable,
-                    base_logger=self._base_logger,
-                )
-            )
-            return middleware_or_callable
-        else:
-            raise BoltError(f"Unexpected type for a middleware ({type(middleware_or_callable)})")
-    return None
-
-

Registers a new middleware to this app. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.middleware
-async def middleware_func(logger, body, next):
-    logger.info(f"request body: {body}")
-    await next()
-
-# Pass a function to this method
-app.middleware(middleware_func)
-
-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
*args
-
A function that works as a global middleware.
-
-
-
-def options(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def options(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new options listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.options("menu_selection")
-        async def show_menu_options(ack):
-            options = [
-                {
-                    "text": {"type": "plain_text", "text": "Option 1"},
-                    "value": "1-1",
-                },
-                {
-                    "text": {"type": "plain_text", "text": "Option 2"},
-                    "value": "1-2",
-                },
-            ]
-            await ack(options=options)
-
-        # Pass a function to this method
-        app.options("menu_selection")(show_menu_options)
-
-    Refer to the following documents for details:
-
-    * https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select
-    * https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.options(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new options listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.options("menu_selection")
-async def show_menu_options(ack):
-    options = [
-        {
-            "text": {"type": "plain_text", "text": "Option 1"},
-            "value": "1-1",
-        },
-        {
-            "text": {"type": "plain_text", "text": "Option 2"},
-            "value": "1-2",
-        },
-    ]
-    await ack(options=options)
-
-# Pass a function to this method
-app.options("menu_selection")(show_menu_options)
-
-

Refer to the following documents for details:

- -

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def server(self, port: int = 3000, path: str = '/slack/events', host: str | None = None) ‑> AsyncSlackAppServer -
-
-
- -Expand source code - -
def server(
-    self,
-    port: int = 3000,
-    path: str = "/slack/events",
-    host: Optional[str] = None,
-) -> AsyncSlackAppServer:
-    """Configure a web server using AIOHTTP.
-    Refer to https://docs.aiohttp.org/ for more details about AIOHTTP.
-
-    Args:
-        port: The port to listen on (Default: 3000)
-        path: The path to handle request from Slack (Default: `/slack/events`)
-        host: The hostname to serve the web endpoints. (Default: 0.0.0.0)
-    """
-    if self._server is None or self._server.port != port or self._server.path != path:
-        self._server = AsyncSlackAppServer(
-            port=port,
-            path=path,
-            app=self,
-            host=host,
-        )
-    return self._server
-
-

Configure a web server using AIOHTTP. -Refer to https://docs.aiohttp.org/ for more details about AIOHTTP.

-

Args

-
-
port
-
The port to listen on (Default: 3000)
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
host
-
The hostname to serve the web endpoints. (Default: 0.0.0.0)
-
-
-
-def shortcut(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def shortcut(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new shortcut listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.shortcut("open_modal")
-        async def open_modal(ack, body, client):
-            # Acknowledge the command request
-            await ack()
-            # Call views_open with the built-in client
-            await client.views_open(
-                # Pass a valid trigger_id within 3 seconds of receiving it
-                trigger_id=body["trigger_id"],
-                # View payload
-                view={ ... }
-            )
-
-        # Pass a function to this method
-        app.shortcut("open_modal")(open_modal)
-
-    Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload.
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.shortcut(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new shortcut listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.shortcut("open_modal")
-async def open_modal(ack, body, client):
-    # Acknowledge the command request
-    await ack()
-    # Call views_open with the built-in client
-    await client.views_open(
-        # Pass a valid trigger_id within 3 seconds of receiving it
-        trigger_id=body["trigger_id"],
-        # View payload
-        view={ ... }
-    )
-
-# Pass a function to this method
-app.shortcut("open_modal")(open_modal)
-
-

Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload.
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def start(self, port: int = 3000, path: str = '/slack/events', host: str | None = None) ‑> None -
-
-
- -Expand source code - -
def start(self, port: int = 3000, path: str = "/slack/events", host: Optional[str] = None) -> None:
-    """Start a web server using AIOHTTP.
-    Refer to https://docs.aiohttp.org/ for more details about AIOHTTP.
-
-    Args:
-        port: The port to listen on (Default: 3000)
-        path: The path to handle request from Slack (Default: `/slack/events`)
-        host: The hostname to serve the web endpoints. (Default: 0.0.0.0)
-    """
-    self.server(port=port, path=path, host=host).start()
-
-

Start a web server using AIOHTTP. -Refer to https://docs.aiohttp.org/ for more details about AIOHTTP.

-

Args

-
-
port
-
The port to listen on (Default: 3000)
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
host
-
The hostname to serve the web endpoints. (Default: 0.0.0.0)
-
-
-
-def step(self,
callback_id: str | Pattern | AsyncWorkflowStep | AsyncWorkflowStepBuilder,
edit: Callable[..., BoltResponse | None] | AsyncListener | Sequence[Callable] | None = None,
save: Callable[..., BoltResponse | None] | AsyncListener | Sequence[Callable] | None = None,
execute: Callable[..., BoltResponse | None] | AsyncListener | Sequence[Callable] | None = None)
-
-
-
- -Expand source code - -
def step(
-    self,
-    callback_id: Union[str, Pattern, AsyncWorkflowStep, AsyncWorkflowStepBuilder],
-    edit: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None,
-    save: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None,
-    execute: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None,
-):
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Registers a new step from app listener.
-
-    Unlike others, this method doesn't behave as a decorator.
-    If you want to register a step from app by a decorator, use `AsyncWorkflowStepBuilder`'s methods.
-
-        # Create a new WorkflowStep instance
-        from slack_bolt.workflows.async_step import AsyncWorkflowStep
-        ws = AsyncWorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        # Pass Step to set up listeners
-        app.step(ws)
-
-    Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-    For further information about AsyncWorkflowStep specific function arguments
-    such as `configure`, `update`, `complete`, and `fail`,
-    refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents.
-
-    Args:
-        callback_id: The Callback ID for this step from app
-        edit: The function for displaying a modal in the Workflow Builder
-        save: The function for handling configuration in the Workflow Builder
-        execute: The function for handling the step execution
-    """
-    warnings.warn(
-        (
-            "Steps from apps for legacy workflows are now deprecated. "
-            "Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/"
-        ),
-        category=DeprecationWarning,
-    )
-    step = callback_id
-    if isinstance(callback_id, (str, Pattern)):
-        step = AsyncWorkflowStep(
-            callback_id=callback_id,
-            edit=edit,  # type: ignore[arg-type]
-            save=save,  # type: ignore[arg-type]
-            execute=execute,  # type: ignore[arg-type]
-            base_logger=self._base_logger,
-        )
-    elif isinstance(step, AsyncWorkflowStepBuilder):
-        step = step.build(base_logger=self._base_logger)
-    elif not isinstance(step, AsyncWorkflowStep):
-        raise BoltError(f"Invalid step object ({type(step)})")
-
-    self.use(AsyncWorkflowStepMiddleware(step))
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Registers a new step from app listener.

-

Unlike others, this method doesn't behave as a decorator. -If you want to register a step from app by a decorator, use AsyncWorkflowStepBuilder's methods.

-
# Create a new WorkflowStep instance
-from slack_bolt.workflows.async_step import AsyncWorkflowStep
-ws = AsyncWorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-# Pass Step to set up listeners
-app.step(ws)
-
-

Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document. -For further information about AsyncWorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to the async prefixed ones in slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
callback_id
-
The Callback ID for this step from app
-
edit
-
The function for displaying a modal in the Workflow Builder
-
save
-
The function for handling configuration in the Workflow Builder
-
execute
-
The function for handling the step execution
-
-
-
-def use(self, *args) ‑> Callable | None -
-
-
- -Expand source code - -
def use(self, *args) -> Optional[Callable]:
-    """Refer to `AsyncApp#middleware()` method's docstring for details."""
-    return self.middleware(*args)
-
-

Refer to AsyncApp#middleware() method's docstring for details.

-
-
-def view(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def view(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `view_submission`/`view_closed` event listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.view("view_1")
-        async def handle_submission(ack, body, client, view):
-            # Assume there's an input block with `block_c` as the block_id and `dreamy_input`
-            hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-            user = body["user"]["id"]
-            # Validate the inputs
-            errors = {}
-            if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-                errors["block_c"] = "The value must be longer than 5 characters"
-            if len(errors) > 0:
-                await ack(response_action="errors", errors=errors)
-                return
-            # Acknowledge the view_submission event and close the modal
-            await ack()
-            # Do whatever you want with the input data - here we're saving it to a DB
-
-        # Pass a function to this method
-        app.view("view_1")(handle_submission)
-
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new view_submission/view_closed event listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.view("view_1")
-async def handle_submission(ack, body, client, view):
-    # Assume there's an input block with <code>block\_c</code> as the block_id and <code>dreamy\_input</code>
-    hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-    user = body["user"]["id"]
-    # Validate the inputs
-    errors = {}
-    if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-        errors["block_c"] = "The value must be longer than 5 characters"
-    if len(errors) > 0:
-        await ack(response_action="errors", errors=errors)
-        return
-    # Acknowledge the view_submission event and close the modal
-    await ack()
-    # Do whatever you want with the input data - here we're saving it to a DB
-
-# Pass a function to this method
-app.view("view_1")(handle_submission)
-
-

Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def view_closed(self,
constraints: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def view_closed(
-    self,
-    constraints: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `view_closed` listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view_closed(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
- -
-
-def view_submission(self,
constraints: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def view_submission(
-    self,
-    constraints: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `view_submission` listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for
-    details.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view_submission(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new view_submission listener. -Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for -details.

-
-
-def web_app(self, path: str = '/slack/events', port: int = 3000) ‑> aiohttp.web_app.Application -
-
-
- -Expand source code - -
def web_app(self, path: str = "/slack/events", port: int = 3000) -> web.Application:
-    """Returns a `web.Application` instance for aiohttp-devtools users.
-
-        from slack_bolt.async_app import AsyncApp
-        app = AsyncApp()
-
-        @app.event("app_mention")
-        async def event_test(body, say, logger):
-            logger.info(body)
-            await say("What's up?")
-
-        def app_factory():
-            return app.web_app()
-
-        # adev runserver --port 3000 --app-factory app_factory async_app.py
-
-    Args:
-        path: The path to receive incoming requests from Slack
-        port: The port to listen on (Default: 3000)
-    """
-    return self.server(path=path, port=port).web_app
-
-

Returns a web.Application instance for aiohttp-devtools users.

-
from slack_bolt.async_app import AsyncApp
-app = AsyncApp()
-
-@app.event("app_mention")
-async def event_test(body, say, logger):
-    logger.info(body)
-    await say("What's up?")
-
-def app_factory():
-    return app.web_app()
-
-# adev runserver --port 3000 --app-factory app_factory async_app.py
-
-

Args

-
-
path
-
The path to receive incoming requests from Slack
-
port
-
The port to listen on (Default: 3000)
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/app/async_server.html b/docs/reference/app/async_server.html deleted file mode 100644 index 5eefe90dd..000000000 --- a/docs/reference/app/async_server.html +++ /dev/null @@ -1,276 +0,0 @@ - - - - - - -slack_bolt.app.async_server API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.app.async_server

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSlackAppServer -(port: int, path: str, app: AsyncApp, host: str | None = None) -
-
-
- -Expand source code - -
class AsyncSlackAppServer:
-    port: int
-    path: str
-    host: str
-    bolt_app: "AsyncApp"
-    web_app: web.Application
-
-    def __init__(
-        self,
-        port: int,
-        path: str,
-        app: "AsyncApp",
-        host: Optional[str] = None,
-    ):
-        """Standalone AIOHTTP Web Server.
-        Refer to https://docs.aiohttp.org/en/stable/web.html for details of AIOHTTP.
-
-        Args:
-            port: The port to listen on
-            path: The path to receive incoming requests from Slack
-            app: The `AsyncApp` instance that is used for processing requests
-            host: The hostname to serve the web endpoints. (Default: 0.0.0.0)
-        """
-        self.port = port
-        self.path = path
-        self.host = host if host is not None else "0.0.0.0"
-        self.bolt_app: "AsyncApp" = app
-        self.web_app = web.Application()
-        self._bolt_oauth_flow = self.bolt_app.oauth_flow
-        if self._bolt_oauth_flow:
-            self.web_app.add_routes(
-                [
-                    web.get(self._bolt_oauth_flow.install_path, self.handle_get_requests),
-                    web.get(
-                        self._bolt_oauth_flow.redirect_uri_path,
-                        self.handle_get_requests,
-                    ),
-                    web.post(self.path, self.handle_post_requests),
-                ]
-            )
-        else:
-            self.web_app.add_routes([web.post(self.path, self.handle_post_requests)])
-
-    async def handle_get_requests(self, request: web.Request) -> web.Response:
-        oauth_flow = self._bolt_oauth_flow
-        if oauth_flow:
-            if request.path == oauth_flow.install_path:
-                bolt_req = await to_bolt_request(request)
-                bolt_resp = await oauth_flow.handle_installation(bolt_req)
-                return await to_aiohttp_response(bolt_resp)
-            elif request.path == oauth_flow.redirect_uri_path:
-                bolt_req = await to_bolt_request(request)
-                bolt_resp = await oauth_flow.handle_callback(bolt_req)
-                return await to_aiohttp_response(bolt_resp)
-            else:
-                return web.Response(status=404)
-        else:
-            return web.Response(status=404)
-
-    async def handle_post_requests(self, request: web.Request) -> web.Response:
-        if self.path != request.path:
-            return web.Response(status=404)
-
-        bolt_req = await to_bolt_request(request)
-        bolt_resp: BoltResponse = await self.bolt_app.async_dispatch(bolt_req)
-        return await to_aiohttp_response(bolt_resp)
-
-    def start(self, host: Optional[str] = None) -> None:
-        """Starts a new web server process."""
-        if self.bolt_app.logger.level > logging.INFO:
-            print(get_boot_message())
-        else:
-            self.bolt_app.logger.info(get_boot_message())
-
-        _host = host if host is not None else self.host
-        web.run_app(self.web_app, host=_host, port=self.port)
-
-

Standalone AIOHTTP Web Server. -Refer to https://docs.aiohttp.org/en/stable/web.html for details of AIOHTTP.

-

Args

-
-
port
-
The port to listen on
-
path
-
The path to receive incoming requests from Slack
-
app
-
The AsyncApp instance that is used for processing requests
-
host
-
The hostname to serve the web endpoints. (Default: 0.0.0.0)
-
-

Class variables

-
-
var bolt_app : AsyncApp
-
-

The type of the None singleton.

-
-
var host : str
-
-

The type of the None singleton.

-
-
var path : str
-
-

The type of the None singleton.

-
-
var port : int
-
-

The type of the None singleton.

-
-
var web_app : aiohttp.web_app.Application
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-async def handle_get_requests(self, request: aiohttp.web_request.Request) ‑> aiohttp.web_response.Response -
-
-
- -Expand source code - -
async def handle_get_requests(self, request: web.Request) -> web.Response:
-    oauth_flow = self._bolt_oauth_flow
-    if oauth_flow:
-        if request.path == oauth_flow.install_path:
-            bolt_req = await to_bolt_request(request)
-            bolt_resp = await oauth_flow.handle_installation(bolt_req)
-            return await to_aiohttp_response(bolt_resp)
-        elif request.path == oauth_flow.redirect_uri_path:
-            bolt_req = await to_bolt_request(request)
-            bolt_resp = await oauth_flow.handle_callback(bolt_req)
-            return await to_aiohttp_response(bolt_resp)
-        else:
-            return web.Response(status=404)
-    else:
-        return web.Response(status=404)
-
-
-
-
-async def handle_post_requests(self, request: aiohttp.web_request.Request) ‑> aiohttp.web_response.Response -
-
-
- -Expand source code - -
async def handle_post_requests(self, request: web.Request) -> web.Response:
-    if self.path != request.path:
-        return web.Response(status=404)
-
-    bolt_req = await to_bolt_request(request)
-    bolt_resp: BoltResponse = await self.bolt_app.async_dispatch(bolt_req)
-    return await to_aiohttp_response(bolt_resp)
-
-
-
-
-def start(self, host: str | None = None) ‑> None -
-
-
- -Expand source code - -
def start(self, host: Optional[str] = None) -> None:
-    """Starts a new web server process."""
-    if self.bolt_app.logger.level > logging.INFO:
-        print(get_boot_message())
-    else:
-        self.bolt_app.logger.info(get_boot_message())
-
-    _host = host if host is not None else self.host
-    web.run_app(self.web_app, host=_host, port=self.port)
-
-

Starts a new web server process.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/app/index.html b/docs/reference/app/index.html deleted file mode 100644 index 5581b98e7..000000000 --- a/docs/reference/app/index.html +++ /dev/null @@ -1,3128 +0,0 @@ - - - - - - -slack_bolt.app API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.app

-
-
-

Application interface in Bolt.

-

For most use cases, we recommend using slack_bolt.app.app. -If you already have knowledge about asyncio and prefer the programming model, -you can use slack_bolt.app.async_app for building async apps.

-
-
-

Sub-modules

-
-
slack_bolt.app.app
-
-
-
-
slack_bolt.app.async_app
-
-
-
-
slack_bolt.app.async_server
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class App -(*,
logger: logging.Logger | None = None,
name: str | None = None,
process_before_response: bool = False,
raise_error_for_unhandled_request: bool = False,
signing_secret: str | None = None,
token: str | None = None,
token_verification_enabled: bool = True,
client: slack_sdk.web.client.WebClient | None = None,
before_authorize: Middleware | Callable[..., Any] | None = None,
authorize: Callable[..., AuthorizeResult] | None = None,
user_facing_authorize_error_message: str | None = None,
installation_store: slack_sdk.oauth.installation_store.installation_store.InstallationStore | None = None,
installation_store_bot_only: bool | None = None,
request_verification_enabled: bool = True,
ignoring_self_events_enabled: bool = True,
ignoring_self_assistant_message_events_enabled: bool = True,
ssl_check_enabled: bool = True,
url_verification_enabled: bool = True,
attaching_function_token_enabled: bool = True,
oauth_settings: OAuthSettings | None = None,
oauth_flow: OAuthFlow | None = None,
verification_token: str | None = None,
listener_executor: concurrent.futures._base.Executor | None = None,
assistant_thread_context_store: AssistantThreadContextStore | None = None,
attaching_conversation_kwargs_enabled: bool = True)
-
-
-
- -Expand source code - -
class App:
-    def __init__(
-        self,
-        *,
-        logger: Optional[logging.Logger] = None,
-        # Used in logger
-        name: Optional[str] = None,
-        # Set True when you run this app on a FaaS platform
-        process_before_response: bool = False,
-        # Set True if you want to handle an unhandled request as an exception
-        raise_error_for_unhandled_request: bool = False,
-        # Basic Information > Credentials > Signing Secret
-        signing_secret: Optional[str] = None,
-        # for single-workspace apps
-        token: Optional[str] = None,
-        token_verification_enabled: bool = True,
-        client: Optional[WebClient] = None,
-        # for multi-workspace apps
-        before_authorize: Optional[Union[Middleware, Callable[..., Any]]] = None,
-        authorize: Optional[Callable[..., AuthorizeResult]] = None,
-        user_facing_authorize_error_message: Optional[str] = None,
-        installation_store: Optional[InstallationStore] = None,
-        # for either only bot scope usage or v1.0.x compatibility
-        installation_store_bot_only: Optional[bool] = None,
-        # for customizing the built-in middleware
-        request_verification_enabled: bool = True,
-        ignoring_self_events_enabled: bool = True,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-        ssl_check_enabled: bool = True,
-        url_verification_enabled: bool = True,
-        attaching_function_token_enabled: bool = True,
-        # for the OAuth flow
-        oauth_settings: Optional[OAuthSettings] = None,
-        oauth_flow: Optional[OAuthFlow] = None,
-        # No need to set (the value is used only in response to ssl_check requests)
-        verification_token: Optional[str] = None,
-        # Set this one only when you want to customize the executor
-        listener_executor: Optional[Executor] = None,
-        # for AI Agents & Assistants
-        assistant_thread_context_store: Optional[AssistantThreadContextStore] = None,
-        attaching_conversation_kwargs_enabled: bool = True,
-    ):
-        """Bolt App that provides functionalities to register middleware/listeners.
-
-            import os
-            from slack_bolt import App
-
-            # Initializes your app with your bot token and signing secret
-            app = App(
-                token=os.environ.get("SLACK_BOT_TOKEN"),
-                signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
-            )
-
-            # Listens to incoming messages that contain "hello"
-            @app.message("hello")
-            def message_hello(message, say):
-                # say() sends a message to the channel where the event was triggered
-                say(f"Hey there <@{message['user']}>!")
-
-            # Start your app
-            if __name__ == "__main__":
-                app.start(port=int(os.environ.get("PORT", 3000)))
-
-        Refer to https://docs.slack.dev/tools/bolt-python/creating-an-app for details.
-
-        If you would like to build an OAuth app for enabling the app to run with multiple workspaces,
-        refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app.
-
-        Args:
-            logger: The custom logger that can be used in this app.
-            name: The application name that will be used in logging. If absent, the source file name will be used.
-            process_before_response: True if this app runs on Function as a Service. (Default: False)
-            raise_error_for_unhandled_request: True if you want to raise exceptions for unhandled requests
-                and use @app.error listeners instead of
-                the built-in handler, which pints warning logs and returns 404 to Slack (Default: False)
-            signing_secret: The Signing Secret value used for verifying requests from Slack.
-            token: The bot/user access token required only for single-workspace app.
-            token_verification_enabled: Verifies the validity of the given token if True.
-            client: The singleton `slack_sdk.WebClient` instance for this app.
-            before_authorize: A global middleware that can be executed right before authorize function
-            authorize: The function to authorize an incoming request from Slack
-                by checking if there is a team/user in the installation data.
-            user_facing_authorize_error_message: The user-facing error message to display
-                when the app is installed but the installation is not managed by this app's installation store
-            installation_store: The module offering save/find operations of installation data
-            installation_store_bot_only: Use `InstallationStore#find_bot()` if True (Default: False)
-            request_verification_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `RequestVerification` is a built-in middleware that verifies the signature in HTTP Mode requests.
-                Make sure if it's safe enough when you turn a built-in middleware off.
-                We strongly recommend using RequestVerification for better security.
-                If you have a proxy that verifies request signature in front of the Bolt app,
-                it's totally fine to disable RequestVerification to avoid duplication of work.
-                Don't turn it off just for easiness of development.
-            ignoring_self_events_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `IgnoringSelfEvents` is a built-in middleware that enables Bolt apps to easily skip the events
-                generated by this app's bot user (this is useful for avoiding code error causing an infinite loop).
-            ignoring_self_assistant_message_events_enabled: False if you would like to disable the built-in middleware.
-                `IgnoringSelfEvents` for this app's bot user message events within an assistant thread
-                This is useful for avoiding code error causing an infinite loop; Default: True
-            url_verification_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `UrlVerification` is a built-in middleware that handles url_verification requests
-                that verify the endpoint for Events API in HTTP Mode requests.
-            attaching_function_token_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `AttachingFunctionToken` is a built-in middleware that injects the just-in-time workflow-execution tokens
-                when your app receives `function_executed` or interactivity events scoped to a custom step.
-            ssl_check_enabled: bool = False if you would like to disable the built-in middleware (Default: True).
-                `SslCheck` is a built-in middleware that handles ssl_check requests from Slack.
-            oauth_settings: The settings related to Slack app installation flow (OAuth flow)
-            oauth_flow: Instantiated `slack_bolt.oauth.OAuthFlow`. This is always prioritized over oauth_settings.
-            verification_token: Deprecated verification mechanism. This can be used only for ssl_check requests.
-            listener_executor: Custom executor to run background tasks. If absent, the default `ThreadPoolExecutor` will
-                be used.
-            assistant_thread_context_store: Custom AssistantThreadContext store (Default: the built-in implementation,
-                which uses a parent message's metadata to store the latest context)
-        """
-        if signing_secret is None:
-            signing_secret = os.environ.get("SLACK_SIGNING_SECRET", "")
-        token = token or os.environ.get("SLACK_BOT_TOKEN")
-
-        self._name: str = name or inspect.stack()[1].filename.split(os.path.sep)[-1]
-        self._signing_secret: str = signing_secret
-
-        self._verification_token: Optional[str] = verification_token or os.environ.get("SLACK_VERIFICATION_TOKEN", None)
-        # If a logger is explicitly passed when initializing, the logger works as the base logger.
-        # The base logger's logging settings will be propagated to all the loggers created by bolt-python.
-        self._base_logger = logger
-        # The framework logger is supposed to be used for the internal logging.
-        # Also, it's accessible via `app.logger` as the app's singleton logger.
-        self._framework_logger = logger or get_bolt_logger(App)
-        self._raise_error_for_unhandled_request = raise_error_for_unhandled_request
-
-        self._token: Optional[str] = token
-
-        if client is not None:
-            if not isinstance(client, WebClient):
-                raise BoltError(error_client_invalid_type())
-            self._client = client
-            self._token = client.token
-            if token is not None:
-                self._framework_logger.warning(warning_client_prioritized_and_token_skipped())
-        else:
-            self._client = create_web_client(
-                # NOTE: the token here can be None
-                token=token,
-                logger=self._framework_logger,
-            )
-
-        # --------------------------------------
-        # Authorize & OAuthFlow initialization
-        # --------------------------------------
-
-        self._before_authorize: Optional[Middleware] = None
-        if before_authorize is not None:
-            if callable(before_authorize):
-                self._before_authorize = CustomMiddleware(
-                    app_name=self._name,
-                    func=before_authorize,
-                    base_logger=self._framework_logger,
-                )
-            elif isinstance(before_authorize, Middleware):
-                self._before_authorize = before_authorize
-
-        self._authorize: Optional[Authorize] = None
-        if authorize is not None:
-            if isinstance(authorize, Authorize):
-                # As long as an advanced developer understands what they're doing,
-                # bolt-python should not prevent customizing authorize middleware
-                self._authorize = authorize
-            else:
-                if oauth_settings is not None or oauth_flow is not None:
-                    # If the given authorize is a simple function,
-                    # it does not work along with installation_store.
-                    raise BoltError(error_authorize_conflicts())
-                self._authorize = CallableAuthorize(logger=self._framework_logger, func=authorize)
-
-        self._installation_store: Optional[InstallationStore] = installation_store
-        if self._installation_store is not None and self._authorize is None:
-            settings = oauth_flow.settings if oauth_flow is not None else oauth_settings
-            self._authorize = InstallationStoreAuthorize(
-                installation_store=self._installation_store,
-                client_id=settings.client_id if settings is not None else None,
-                client_secret=settings.client_secret if settings is not None else None,
-                logger=self._framework_logger,
-                bot_only=installation_store_bot_only or False,
-                client=self._client,  # for proxy use cases etc.
-                user_token_resolution=(settings.user_token_resolution if settings is not None else "authed_user"),
-            )
-
-        self._oauth_flow: Optional[OAuthFlow] = None
-
-        if (
-            oauth_settings is None
-            and os.environ.get("SLACK_CLIENT_ID") is not None
-            and os.environ.get("SLACK_CLIENT_SECRET") is not None
-        ):
-            # initialize with the default settings
-            oauth_settings = OAuthSettings()
-
-            if oauth_flow is None and installation_store is None:
-                # show info-level log for avoiding confusions
-                self._framework_logger.info(info_default_oauth_settings_loaded())
-
-        if oauth_flow is not None:
-            self._oauth_flow = oauth_flow
-            installation_store = select_consistent_installation_store(
-                client_id=self._oauth_flow.client_id,
-                app_store=self._installation_store,
-                oauth_flow_store=self._oauth_flow.settings.installation_store,
-                logger=self._framework_logger,
-            )
-            self._installation_store = installation_store
-            if installation_store is not None:
-                self._oauth_flow.settings.installation_store = installation_store
-
-            if self._oauth_flow._client is None:
-                self._oauth_flow._client = self._client
-            if self._authorize is None:
-                self._authorize = self._oauth_flow.settings.authorize
-        elif oauth_settings is not None:
-            installation_store = select_consistent_installation_store(
-                client_id=oauth_settings.client_id,
-                app_store=self._installation_store,
-                oauth_flow_store=oauth_settings.installation_store,
-                logger=self._framework_logger,
-            )
-            self._installation_store = installation_store
-            if installation_store is not None:
-                oauth_settings.installation_store = installation_store
-            self._oauth_flow = OAuthFlow(client=self.client, logger=self.logger, settings=oauth_settings)
-            if self._authorize is None:
-                self._authorize = self._oauth_flow.settings.authorize
-            self._authorize.token_rotation_expiration_minutes = oauth_settings.token_rotation_expiration_minutes  # type: ignore[attr-defined] # noqa: E501
-
-        if (self._installation_store is not None or self._authorize is not None) and self._token is not None:
-            self._token = None
-            self._framework_logger.warning(warning_token_skipped())
-
-        # after setting bot_only here, __init__ cannot replace authorize function
-        if installation_store_bot_only is not None and self._oauth_flow is not None:
-            app_bot_only = installation_store_bot_only or False
-            oauth_flow_bot_only = self._oauth_flow.settings.installation_store_bot_only
-            if app_bot_only != oauth_flow_bot_only:
-                self.logger.warning(warning_bot_only_conflicts())
-                self._oauth_flow.settings.installation_store_bot_only = app_bot_only
-                self._authorize.bot_only = app_bot_only  # type: ignore[union-attr]
-
-        self._tokens_revocation_listeners: Optional[TokenRevocationListeners] = None
-        if self._installation_store is not None:
-            self._tokens_revocation_listeners = TokenRevocationListeners(self._installation_store)
-
-        # --------------------------------------
-        # Middleware Initialization
-        # --------------------------------------
-
-        self._middleware_list: List[Middleware] = []
-        self._listeners: List[Listener] = []
-
-        if listener_executor is None:
-            listener_executor = ThreadPoolExecutor(max_workers=5)
-
-        self._assistant_thread_context_store = assistant_thread_context_store
-        self._attaching_conversation_kwargs_enabled = attaching_conversation_kwargs_enabled
-
-        self._process_before_response = process_before_response
-        self._listener_runner = ThreadListenerRunner(
-            logger=self._framework_logger,
-            process_before_response=process_before_response,
-            listener_error_handler=DefaultListenerErrorHandler(logger=self._framework_logger),
-            listener_start_handler=DefaultListenerStartHandler(logger=self._framework_logger),
-            listener_completion_handler=DefaultListenerCompletionHandler(logger=self._framework_logger),
-            listener_executor=listener_executor,
-            lazy_listener_runner=ThreadLazyListenerRunner(
-                logger=self._framework_logger,
-                executor=listener_executor,
-            ),
-        )
-        self._middleware_error_handler: MiddlewareErrorHandler = DefaultMiddlewareErrorHandler(
-            logger=self._framework_logger,
-        )
-
-        self._init_middleware_list_done = False
-        self._init_middleware_list(
-            token_verification_enabled=token_verification_enabled,
-            request_verification_enabled=request_verification_enabled,
-            ignoring_self_events_enabled=ignoring_self_events_enabled,
-            ignoring_self_assistant_message_events_enabled=ignoring_self_assistant_message_events_enabled,
-            ssl_check_enabled=ssl_check_enabled,
-            url_verification_enabled=url_verification_enabled,
-            attaching_function_token_enabled=attaching_function_token_enabled,
-            user_facing_authorize_error_message=user_facing_authorize_error_message,
-        )
-
-    def _init_middleware_list(
-        self,
-        token_verification_enabled: bool = True,
-        request_verification_enabled: bool = True,
-        ignoring_self_events_enabled: bool = True,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-        ssl_check_enabled: bool = True,
-        url_verification_enabled: bool = True,
-        attaching_function_token_enabled: bool = True,
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        if self._init_middleware_list_done:
-            return
-        if ssl_check_enabled is True:
-            self._middleware_list.append(
-                SslCheck(
-                    verification_token=self._verification_token,
-                    base_logger=self._base_logger,
-                )
-            )
-        if request_verification_enabled is True:
-            self._middleware_list.append(RequestVerification(self._signing_secret, base_logger=self._base_logger))
-
-        if self._before_authorize is not None:
-            self._middleware_list.append(self._before_authorize)
-
-        # As authorize is required for making a Bolt app function, we don't offer the flag to disable this
-        if self._oauth_flow is None:
-            if self._token is not None:
-                try:
-                    auth_test_result = None
-                    if token_verification_enabled:
-                        # This API call is for eagerly validating the token
-                        auth_test_result = self._client.auth_test(token=self._token)
-                    self._middleware_list.append(
-                        SingleTeamAuthorization(
-                            auth_test_result=auth_test_result,
-                            base_logger=self._base_logger,
-                            user_facing_authorize_error_message=user_facing_authorize_error_message,
-                        )
-                    )
-                except SlackApiError as err:
-                    raise BoltError(error_auth_test_failure(err.response))
-            elif self._authorize is not None:
-                self._middleware_list.append(
-                    MultiTeamsAuthorization(
-                        authorize=self._authorize,
-                        base_logger=self._base_logger,
-                        user_facing_authorize_error_message=user_facing_authorize_error_message,
-                    )
-                )
-            else:
-                raise BoltError(error_token_required())
-        elif self._authorize is not None:
-            self._middleware_list.append(
-                MultiTeamsAuthorization(
-                    authorize=self._authorize,
-                    base_logger=self._base_logger,
-                    user_token_resolution=self._oauth_flow.settings.user_token_resolution,
-                    user_facing_authorize_error_message=user_facing_authorize_error_message,
-                )
-            )
-        else:
-            raise BoltError(error_oauth_flow_or_authorize_required())
-
-        if ignoring_self_events_enabled is True:
-            self._middleware_list.append(
-                IgnoringSelfEvents(
-                    base_logger=self._base_logger,
-                    ignoring_self_assistant_message_events_enabled=ignoring_self_assistant_message_events_enabled,
-                )
-            )
-        if url_verification_enabled is True:
-            self._middleware_list.append(UrlVerification(base_logger=self._base_logger))
-        if attaching_function_token_enabled is True:
-            self._middleware_list.append(AttachingFunctionToken())
-        self._init_middleware_list_done = True
-
-    # -------------------------
-    # accessors
-
-    @property
-    def name(self) -> str:
-        """The name of this app (default: the filename)"""
-        return self._name
-
-    @property
-    def oauth_flow(self) -> Optional[OAuthFlow]:
-        """Configured `OAuthFlow` object if exists."""
-        return self._oauth_flow
-
-    @property
-    def logger(self) -> logging.Logger:
-        """The logger this app uses."""
-        return self._framework_logger
-
-    @property
-    def client(self) -> WebClient:
-        """The singleton `slack_sdk.WebClient` instance in this app."""
-        return self._client
-
-    @property
-    def installation_store(self) -> Optional[InstallationStore]:
-        """The `slack_sdk.oauth.InstallationStore` that can be used in the `authorize` middleware."""
-        return self._installation_store
-
-    @property
-    def listener_runner(self) -> ThreadListenerRunner:
-        """The thread executor for asynchronously running listeners."""
-        return self._listener_runner
-
-    @property
-    def process_before_response(self) -> bool:
-        return self._process_before_response or False
-
-    # -------------------------
-    # standalone server
-
-    def start(
-        self,
-        port: int = 3000,
-        path: str = "/slack/events",
-        http_server_logger_enabled: bool = True,
-    ) -> None:
-        """Starts a web server for local development.
-
-            # With the default settings, `http://localhost:3000/slack/events`
-            # is available for handling incoming requests from Slack
-            app.start()
-
-        This method internally starts a Web server process built with the `http.server` module.
-        For production, consider using a production-ready WSGI server such as Gunicorn.
-
-        Args:
-            port: The port to listen on (Default: 3000)
-            path: The path to handle request from Slack (Default: `/slack/events`)
-            http_server_logger_enabled: The flag to enable http.server logging if True (Default: True)
-        """
-        self._development_server = SlackAppDevelopmentServer(
-            port=port,
-            path=path,
-            app=self,
-            oauth_flow=self.oauth_flow,
-            http_server_logger_enabled=http_server_logger_enabled,
-        )
-        self._development_server.start()
-
-    # -------------------------
-    # main dispatcher
-
-    def dispatch(self, req: BoltRequest) -> BoltResponse:
-        """Applies all middleware and dispatches an incoming request from Slack to the right code path.
-
-        Args:
-            req: An incoming request from Slack
-
-        Returns:
-            The response generated by this Bolt app
-        """
-        starting_time = time.time()
-        self._init_context(req)
-
-        resp: Optional[BoltResponse] = BoltResponse(status=200, body="")
-        middleware_state = {"next_called": False}
-
-        def middleware_next():
-            middleware_state["next_called"] = True
-
-        try:
-            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)  # type: ignore[arg-type]
-                if not middleware_state["next_called"]:
-                    if resp is None:
-                        # next() method was not called without providing the response to return to Slack
-                        # This should not be an intentional handling in usual use cases.
-                        resp = BoltResponse(status=404, body={"error": "no next() calls in middleware"})
-                        if self._raise_error_for_unhandled_request is True:
-                            try:
-                                raise BoltUnhandledRequestError(
-                                    request=req,
-                                    current_response=resp,
-                                    last_global_middleware_name=middleware.name,
-                                )
-                            except BoltUnhandledRequestError as e:
-                                self._listener_runner.listener_error_handler.handle(
-                                    error=e,
-                                    request=req,
-                                    response=resp,
-                                )
-                            return resp
-                        self._framework_logger.warning(warning_unhandled_by_global_middleware(middleware.name, req))
-                        return resp
-                    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):  # type: ignore[arg-type]
-                    # run all the middleware attached to this listener first
-                    middleware_resp, next_was_not_called = listener.run_middleware(
-                        req=req, resp=resp  # type: ignore[arg-type]
-                    )
-                    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,  # type: ignore[arg-type]
-                        listener_name=listener_name,
-                        listener=listener,
-                    )
-                    if listener_response is not None:
-                        return listener_response
-
-            if resp is None:
-                resp = BoltResponse(status=404, body={"error": "unhandled request"})
-            if self._raise_error_for_unhandled_request is True:
-                try:
-                    raise BoltUnhandledRequestError(
-                        request=req,
-                        current_response=resp,
-                    )
-                except BoltUnhandledRequestError as e:
-                    self._listener_runner.listener_error_handler.handle(
-                        error=e,
-                        request=req,
-                        response=resp,
-                    )
-                return resp
-            return self._handle_unmatched_requests(req, resp)
-        except Exception as error:
-            resp = BoltResponse(status=500, body="")
-            self._middleware_error_handler.handle(
-                error=error,
-                request=req,
-                response=resp,
-            )
-            return resp
-
-    def _handle_unmatched_requests(self, req: BoltRequest, resp: BoltResponse) -> BoltResponse:
-        self._framework_logger.warning(warning_unhandled_request(req))
-        return resp
-
-    # -------------------------
-    # middleware
-
-    def use(self, *args) -> Optional[Callable]:
-        """Registers a new global middleware to this app. This method can be used as either a decorator or a method.
-
-        Refer to `App#middleware()` method's docstring for details."""
-        return self.middleware(*args)
-
-    def middleware(self, *args) -> Optional[Callable]:
-        """Registers a new middleware to this app.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.middleware
-            def middleware_func(logger, body, next):
-                logger.info(f"request body: {body}")
-                next()
-
-            # Pass a function to this method
-            app.middleware(middleware_func)
-
-        Refer to https://docs.slack.dev/tools/bolt-python/concepts/global-middleware for details.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            *args: A function that works as a global middleware.
-        """
-        if len(args) > 0:
-            middleware_or_callable = args[0]
-            if isinstance(middleware_or_callable, Middleware):
-                middleware: Middleware = middleware_or_callable
-                self._middleware_list.append(middleware)
-                if isinstance(middleware, Assistant) and middleware.thread_context_store is not None:
-                    self._assistant_thread_context_store = middleware.thread_context_store
-            elif callable(middleware_or_callable):
-                self._middleware_list.append(
-                    CustomMiddleware(
-                        app_name=self.name,
-                        func=middleware_or_callable,
-                        base_logger=self._base_logger,
-                    )
-                )
-                return middleware_or_callable
-            else:
-                raise BoltError(f"Unexpected type for a middleware ({type(middleware_or_callable)})")
-        return None
-
-    # -------------------------
-    # AI Agents & Assistants
-
-    def assistant(self, assistant: Assistant) -> Optional[Callable]:
-        return self.middleware(assistant)
-
-    # -------------------------
-    # Workflows: Steps from apps
-
-    def step(
-        self,
-        callback_id: Union[str, Pattern, WorkflowStep, WorkflowStepBuilder],
-        edit: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-        save: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-        execute: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Registers a new step from app listener.
-
-        Unlike others, this method doesn't behave as a decorator.
-        If you want to register a step from app by a decorator, use `WorkflowStepBuilder`'s methods.
-
-            # Create a new WorkflowStep instance
-            from slack_bolt.workflows.step import WorkflowStep
-            ws = WorkflowStep(
-                callback_id="add_task",
-                edit=edit,
-                save=save,
-                execute=execute,
-            )
-            # Pass Step to set up listeners
-            app.step(ws)
-
-        Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        For further information about WorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            callback_id: The Callback ID for this step from app
-            edit: The function for displaying a modal in the Workflow Builder
-            save: The function for handling configuration in the Workflow Builder
-            execute: The function for handling the step execution
-        """
-        warnings.warn(
-            (
-                "Steps from apps for legacy workflows are now deprecated. "
-                "Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/"
-            ),
-            category=DeprecationWarning,
-        )
-        step = callback_id
-        if isinstance(callback_id, (str, Pattern)):
-            step = WorkflowStep(
-                callback_id=callback_id,
-                edit=edit,  # type: ignore[arg-type]
-                save=save,  # type: ignore[arg-type]
-                execute=execute,  # type: ignore[arg-type]
-                base_logger=self._base_logger,
-            )
-        elif isinstance(step, WorkflowStepBuilder):
-            step = step.build(base_logger=self._base_logger)
-        elif not isinstance(step, WorkflowStep):
-            raise BoltError(f"Invalid step object ({type(step)})")
-
-        self.use(WorkflowStepMiddleware(step))
-
-    # -------------------------
-    # global error handler
-
-    def error(self, func: Callable[..., Optional[BoltResponse]]) -> Callable[..., Optional[BoltResponse]]:
-        """Updates the global error handler. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.error
-            def custom_error_handler(error, body, logger):
-                logger.exception(f"Error: {error}")
-                logger.info(f"Request body: {body}")
-
-            # Pass a function to this method
-            app.error(custom_error_handler)
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            func: The function that is supposed to be executed
-                when getting an unhandled error in Bolt app.
-        """
-        self._listener_runner.listener_error_handler = CustomListenerErrorHandler(
-            logger=self._framework_logger,
-            func=func,
-        )
-        self._middleware_error_handler = CustomMiddlewareErrorHandler(
-            logger=self._framework_logger,
-            func=func,
-        )
-        return func
-
-    # -------------------------
-    # events
-
-    def event(
-        self,
-        event: Union[
-            str,
-            Pattern,
-            Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]],
-        ],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new event listener. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.event("team_join")
-            def ask_for_introduction(event, say):
-                welcome_channel_id = "C12345"
-                user_id = event["user"]
-                text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-                say(text=text, channel=welcome_channel_id)
-
-            # Pass a function to this method
-            app.event("team_join")(ask_for_introduction)
-
-        Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            event: The conditions that match a request payload.
-                If you pass a dict for this, you can have type, subtype in the constraint.
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.event(event, base_logger=self._base_logger)
-            if self._attaching_conversation_kwargs_enabled:
-                middleware.insert(0, AttachingConversationKwargs(self._assistant_thread_context_store))
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-        return __call__
-
-    def message(
-        self,
-        keyword: Union[str, Pattern] = "",
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new message event listener. This method can be used as either a decorator or a method.
-        Check the `App#event` method's docstring for details.
-
-            # Use this method as a decorator
-            @app.message(":wave:")
-            def say_hello(message, say):
-                user = message['user']
-                say(f"Hi there, <@{user}>!")
-
-            # Pass a function to this method
-            app.message(":wave:")(say_hello)
-
-        Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            keyword: The keyword to match
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-        matchers = list(matchers) if matchers else []
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            constraints = {
-                "type": "message",
-                "subtype": (
-                    # In most cases, new message events come with no subtype.
-                    None,
-                    # As of Jan 2021, most bot messages no longer have the subtype bot_message.
-                    # By contrast, messages posted using classic app's bot token still have the subtype.
-                    "bot_message",
-                    # If an end-user posts a message with "Also send to #channel" checked,
-                    # the message event comes with this subtype.
-                    "thread_broadcast",
-                    # If an end-user posts a message with attached files,
-                    # the message event comes with this subtype.
-                    "file_share",
-                ),
-            }
-            primary_matcher = builtin_matchers.message_event(
-                keyword=keyword, constraints=constraints, base_logger=self._base_logger
-            )
-            if self._attaching_conversation_kwargs_enabled:
-                middleware.insert(0, AttachingConversationKwargs(self._assistant_thread_context_store))
-            middleware.insert(0, MessageListenerMatches(keyword))
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-        return __call__
-
-    def function(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-        auto_acknowledge: bool = True,
-        ack_timeout: int = 3,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new Function listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.function("reverse")
-            def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail):
-                try:
-                    ack()
-                    string_to_reverse = inputs["stringToReverse"]
-                    complete(outputs={"reverseString": string_to_reverse[::-1]})
-                except Exception as e:
-                    fail(f"Cannot reverse string (error: {e})")
-                    raise e
-
-            # Pass a function to this method
-            app.function("reverse")(reverse_string)
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            callback_id: The callback id to identify the function
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        if auto_acknowledge is True:
-            if ack_timeout != 3:
-                self._framework_logger.warning(warning_ack_timeout_has_no_effect(callback_id, ack_timeout))
-
-        matchers = list(matchers) if matchers else []
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.function_executed(callback_id=callback_id, base_logger=self._base_logger)
-            return self._register_listener(functions, primary_matcher, matchers, middleware, auto_acknowledge, ack_timeout)
-
-        return __call__
-
-    # -------------------------
-    # slash commands
-
-    def command(
-        self,
-        command: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new slash command listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.command("/echo")
-            def repeat_text(ack, say, command):
-                # Acknowledge command request
-                ack()
-                say(f"{command['text']}")
-
-            # Pass a function to this method
-            app.command("/echo")(repeat_text)
-
-        Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            command: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.command(command, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # shortcut
-
-    def shortcut(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new shortcut listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.shortcut("open_modal")
-            def open_modal(ack, body, client):
-                # Acknowledge the command request
-                ack()
-                # Call views_open with the built-in client
-                client.views_open(
-                    # Pass a valid trigger_id within 3 seconds of receiving it
-                    trigger_id=body["trigger_id"],
-                    # View payload
-                    view={ ... }
-                )
-
-            # Pass a function to this method
-            app.shortcut("open_modal")(open_modal)
-
-        Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload.
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.shortcut(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def global_shortcut(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new global shortcut listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.global_shortcut(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def message_shortcut(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new message shortcut listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.message_shortcut(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # action
-
-    def action(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new action listener. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.action("approve_button")
-            def update_message(ack):
-                ack()
-
-            # Pass a function to this method
-            app.action("approve_button")(update_message)
-
-        * Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`.
-        * Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`.
-        * Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.action(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def block_action(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `block_actions` action listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.block_action(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def attachment_action(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `interactive_message` action listener.
-        Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.attachment_action(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_submission(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `dialog_submission` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_submission(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_cancellation(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `dialog_cancellation` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_cancellation(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # view
-
-    def view(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `view_submission`/`view_closed` event listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.view("view_1")
-            def handle_submission(ack, body, client, view):
-                # Assume there's an input block with `block_c` as the block_id and `dreamy_input`
-                hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-                user = body["user"]["id"]
-                # Validate the inputs
-                errors = {}
-                if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-                    errors["block_c"] = "The value must be longer than 5 characters"
-                if len(errors) > 0:
-                    ack(response_action="errors", errors=errors)
-                    return
-                # Acknowledge the view_submission event and close the modal
-                ack()
-                # Do whatever you want with the input data - here we're saving it to a DB
-
-            # Pass a function to this method
-            app.view("view_1")(handle_submission)
-
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def view_submission(
-        self,
-        constraints: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `view_submission` listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for
-        details.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view_submission(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def view_closed(
-        self,
-        constraints: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `view_closed` listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view_closed(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # options
-
-    def options(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new options listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.options("menu_selection")
-            def show_menu_options(ack):
-                options = [
-                    {
-                        "text": {"type": "plain_text", "text": "Option 1"},
-                        "value": "1-1",
-                    },
-                    {
-                        "text": {"type": "plain_text", "text": "Option 2"},
-                        "value": "1-2",
-                    },
-                ]
-                ack(options=options)
-
-            # Pass a function to this method
-            app.options("menu_selection")(show_menu_options)
-
-        Refer to the following documents for details:
-
-        * https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select
-        * https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.options(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def block_suggestion(
-        self,
-        action_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `block_suggestion` listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.block_suggestion(action_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_suggestion(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `dialog_suggestion` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_suggestion(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # built-in listener functions
-
-    def default_tokens_revoked_event_listener(
-        self,
-    ) -> Callable[..., Optional[BoltResponse]]:
-        if self._tokens_revocation_listeners is None:
-            raise BoltError(error_installation_store_required_for_builtin_listeners())
-        return self._tokens_revocation_listeners.handle_tokens_revoked_events
-
-    def default_app_uninstalled_event_listener(
-        self,
-    ) -> Callable[..., Optional[BoltResponse]]:
-        if self._tokens_revocation_listeners is None:
-            raise BoltError(error_installation_store_required_for_builtin_listeners())
-        return self._tokens_revocation_listeners.handle_app_uninstalled_events
-
-    def enable_token_revocation_listeners(self) -> None:
-        self.event("tokens_revoked")(self.default_tokens_revoked_event_listener())
-        self.event("app_uninstalled")(self.default_app_uninstalled_event_listener())
-
-    # -------------------------
-
-    def _init_context(self, req: BoltRequest):
-        req.context["logger"] = get_bolt_app_logger(app_name=self.name, base_logger=self._base_logger)
-        req.context["token"] = self._token
-        # Prior to version 1.15, when the token is static, self._client was passed to `req.context`.
-        # The intention was to avoid creating a new instance per request
-        # in the interest of runtime performance/memory footprint optimization.
-        # However, developers may want to replace the token held by req.context.client in some situations.
-        # In this case, this behavior can result in thread-unsafe data modification on `self._client`.
-        # (`self._client` a.k.a. `app.client` is a singleton object per an App instance)
-        # Thus, we've changed the behavior to create a new instance per request regardless of token argument
-        # in the App initialization starting v1.15.
-        # The overhead brought by this change is slight so that we believe that it is ignorable in any cases.
-        client_per_request: WebClient = WebClient(
-            token=self._token,  # this can be None, and it can be set later on
-            base_url=self._client.base_url,
-            timeout=self._client.timeout,
-            ssl=self._client.ssl,
-            proxy=self._client.proxy,
-            headers=self._client.headers,
-            team_id=req.context.team_id,
-            logger=self._client.logger,
-            retry_handlers=self._client.retry_handlers.copy() if self._client.retry_handlers is not None else None,
-        )
-        req.context["client"] = client_per_request
-
-        # Most apps do not need this "listener_runner" instance.
-        # It is intended for apps that start lazy listeners from their custom global middleware.
-        req.context["listener_runner"] = self.listener_runner
-
-    @staticmethod
-    def _to_listener_functions(
-        kwargs: dict,
-    ) -> Optional[Sequence[Callable[..., Optional[BoltResponse]]]]:
-        if kwargs:
-            functions = [kwargs["ack"]]
-            for sub in kwargs["lazy"]:
-                functions.append(sub)
-            return functions
-        return None
-
-    def _register_listener(
-        self,
-        functions: Sequence[Callable[..., Optional[BoltResponse]]],
-        primary_matcher: ListenerMatcher,
-        matchers: Optional[Sequence[Callable[..., bool]]],
-        middleware: Optional[Sequence[Union[Callable, Middleware]]],
-        auto_acknowledgement: bool = False,
-        ack_timeout: int = 3,
-    ) -> Optional[Callable[..., Optional[BoltResponse]]]:
-        value_to_return = None
-        if not isinstance(functions, list):
-            functions = list(functions)
-        if len(functions) == 1:
-            # In the case where the function is registered using decorator,
-            # the registration should return the original function.
-            value_to_return = functions[0]
-
-        listener_matchers: List[ListenerMatcher] = [
-            CustomListenerMatcher(app_name=self.name, func=f, base_logger=self._base_logger) for f in (matchers or [])
-        ]
-        listener_matchers.insert(0, primary_matcher)
-        listener_middleware = []
-        for m in middleware or []:
-            if isinstance(m, Middleware):
-                listener_middleware.append(m)
-            elif callable(m):
-                listener_middleware.append(CustomMiddleware(app_name=self.name, func=m, base_logger=self._base_logger))
-            else:
-                raise ValueError(error_unexpected_listener_middleware(type(m)))
-
-        self._listeners.append(
-            CustomListener(
-                app_name=self.name,
-                ack_function=functions.pop(0),
-                lazy_functions=functions,  # type: ignore[arg-type]
-                matchers=listener_matchers,
-                middleware=listener_middleware,
-                auto_acknowledgement=auto_acknowledgement,
-                ack_timeout=ack_timeout,
-                base_logger=self._base_logger,
-            )
-        )
-        return value_to_return
-
-

Bolt App that provides functionalities to register middleware/listeners.

-
import os
-from slack_bolt import App
-
-# Initializes your app with your bot token and signing secret
-app = App(
-    token=os.environ.get("SLACK_BOT_TOKEN"),
-    signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
-)
-
-# Listens to incoming messages that contain "hello"
-@app.message("hello")
-def message_hello(message, say):
-    # say() sends a message to the channel where the event was triggered
-    say(f"Hey there <@{message['user']}>!")
-
-# Start your app
-if __name__ == "__main__":
-    app.start(port=int(os.environ.get("PORT", 3000)))
-
-

Refer to https://docs.slack.dev/tools/bolt-python/creating-an-app for details.

-

If you would like to build an OAuth app for enabling the app to run with multiple workspaces, -refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app.

-

Args

-
-
logger
-
The custom logger that can be used in this app.
-
name
-
The application name that will be used in logging. If absent, the source file name will be used.
-
process_before_response
-
True if this app runs on Function as a Service. (Default: False)
-
raise_error_for_unhandled_request
-
True if you want to raise exceptions for unhandled requests -and use @app.error listeners instead of -the built-in handler, which pints warning logs and returns 404 to Slack (Default: False)
-
signing_secret
-
The Signing Secret value used for verifying requests from Slack.
-
token
-
The bot/user access token required only for single-workspace app.
-
token_verification_enabled
-
Verifies the validity of the given token if True.
-
client
-
The singleton slack_sdk.WebClient instance for this app.
-
before_authorize
-
A global middleware that can be executed right before authorize function
-
authorize
-
The function to authorize an incoming request from Slack -by checking if there is a team/user in the installation data.
-
user_facing_authorize_error_message
-
The user-facing error message to display -when the app is installed but the installation is not managed by this app's installation store
-
installation_store
-
The module offering save/find operations of installation data
-
installation_store_bot_only
-
Use InstallationStore#find_bot() if True (Default: False)
-
request_verification_enabled
-
False if you would like to disable the built-in middleware (Default: True). -RequestVerification is a built-in middleware that verifies the signature in HTTP Mode requests. -Make sure if it's safe enough when you turn a built-in middleware off. -We strongly recommend using RequestVerification for better security. -If you have a proxy that verifies request signature in front of the Bolt app, -it's totally fine to disable RequestVerification to avoid duplication of work. -Don't turn it off just for easiness of development.
-
ignoring_self_events_enabled
-
False if you would like to disable the built-in middleware (Default: True). -IgnoringSelfEvents is a built-in middleware that enables Bolt apps to easily skip the events -generated by this app's bot user (this is useful for avoiding code error causing an infinite loop).
-
ignoring_self_assistant_message_events_enabled
-
False if you would like to disable the built-in middleware. -IgnoringSelfEvents for this app's bot user message events within an assistant thread -This is useful for avoiding code error causing an infinite loop; Default: True
-
url_verification_enabled
-
False if you would like to disable the built-in middleware (Default: True). -UrlVerification is a built-in middleware that handles url_verification requests -that verify the endpoint for Events API in HTTP Mode requests.
-
attaching_function_token_enabled
-
False if you would like to disable the built-in middleware (Default: True). -AttachingFunctionToken is a built-in middleware that injects the just-in-time workflow-execution tokens -when your app receives function_executed or interactivity events scoped to a custom step.
-
ssl_check_enabled
-
bool = False if you would like to disable the built-in middleware (Default: True). -SslCheck is a built-in middleware that handles ssl_check requests from Slack.
-
oauth_settings
-
The settings related to Slack app installation flow (OAuth flow)
-
oauth_flow
-
Instantiated OAuthFlow. This is always prioritized over oauth_settings.
-
verification_token
-
Deprecated verification mechanism. This can be used only for ssl_check requests.
-
listener_executor
-
Custom executor to run background tasks. If absent, the default ThreadPoolExecutor will -be used.
-
assistant_thread_context_store
-
Custom AssistantThreadContext store (Default: the built-in implementation, -which uses a parent message's metadata to store the latest context)
-
-

Instance variables

-
-
prop client : slack_sdk.web.client.WebClient
-
-
- -Expand source code - -
@property
-def client(self) -> WebClient:
-    """The singleton `slack_sdk.WebClient` instance in this app."""
-    return self._client
-
-

The singleton slack_sdk.WebClient instance in this app.

-
-
prop installation_store : slack_sdk.oauth.installation_store.installation_store.InstallationStore | None
-
-
- -Expand source code - -
@property
-def installation_store(self) -> Optional[InstallationStore]:
-    """The `slack_sdk.oauth.InstallationStore` that can be used in the `authorize` middleware."""
-    return self._installation_store
-
-

The slack_sdk.oauth.InstallationStore that can be used in the authorize middleware.

-
-
prop listener_runnerThreadListenerRunner
-
-
- -Expand source code - -
@property
-def listener_runner(self) -> ThreadListenerRunner:
-    """The thread executor for asynchronously running listeners."""
-    return self._listener_runner
-
-

The thread executor for asynchronously running listeners.

-
-
prop logger : logging.Logger
-
-
- -Expand source code - -
@property
-def logger(self) -> logging.Logger:
-    """The logger this app uses."""
-    return self._framework_logger
-
-

The logger this app uses.

-
-
prop name : str
-
-
- -Expand source code - -
@property
-def name(self) -> str:
-    """The name of this app (default: the filename)"""
-    return self._name
-
-

The name of this app (default: the filename)

-
-
prop oauth_flowOAuthFlow | None
-
-
- -Expand source code - -
@property
-def oauth_flow(self) -> Optional[OAuthFlow]:
-    """Configured `OAuthFlow` object if exists."""
-    return self._oauth_flow
-
-

Configured OAuthFlow object if exists.

-
-
prop process_before_response : bool
-
-
- -Expand source code - -
@property
-def process_before_response(self) -> bool:
-    return self._process_before_response or False
-
-
-
-
-

Methods

-
-
-def action(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def action(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new action listener. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.action("approve_button")
-        def update_message(ack):
-            ack()
-
-        # Pass a function to this method
-        app.action("approve_button")(update_message)
-
-    * Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`.
-    * Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`.
-    * Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.action(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new action listener. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.action("approve_button")
-def update_message(ack):
-    ack()
-
-# Pass a function to this method
-app.action("approve_button")(update_message)
-
- -

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def assistant(self,
assistant: Assistant) ‑> Callable | None
-
-
-
- -Expand source code - -
def assistant(self, assistant: Assistant) -> Optional[Callable]:
-    return self.middleware(assistant)
-
-
-
-
-def attachment_action(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def attachment_action(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `interactive_message` action listener.
-    Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.attachment_action(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new interactive_message action listener. -Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details.

-
-
-def block_action(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def block_action(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `block_actions` action listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.block_action(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new block_actions action listener. -Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.

-
-
-def block_suggestion(self,
action_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def block_suggestion(
-    self,
-    action_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `block_suggestion` listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.block_suggestion(action_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new block_suggestion listener.

-
-
-def command(self,
command: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def command(
-    self,
-    command: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new slash command listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.command("/echo")
-        def repeat_text(ack, say, command):
-            # Acknowledge command request
-            ack()
-            say(f"{command['text']}")
-
-        # Pass a function to this method
-        app.command("/echo")(repeat_text)
-
-    Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        command: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.command(command, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new slash command listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.command("/echo")
-def repeat_text(ack, say, command):
-    # Acknowledge command request
-    ack()
-    say(f"{command['text']}")
-
-# Pass a function to this method
-app.command("/echo")(repeat_text)
-
-

Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
command
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def default_app_uninstalled_event_listener(self) ‑> Callable[..., BoltResponse | None] -
-
-
- -Expand source code - -
def default_app_uninstalled_event_listener(
-    self,
-) -> Callable[..., Optional[BoltResponse]]:
-    if self._tokens_revocation_listeners is None:
-        raise BoltError(error_installation_store_required_for_builtin_listeners())
-    return self._tokens_revocation_listeners.handle_app_uninstalled_events
-
-
-
-
-def default_tokens_revoked_event_listener(self) ‑> Callable[..., BoltResponse | None] -
-
-
- -Expand source code - -
def default_tokens_revoked_event_listener(
-    self,
-) -> Callable[..., Optional[BoltResponse]]:
-    if self._tokens_revocation_listeners is None:
-        raise BoltError(error_installation_store_required_for_builtin_listeners())
-    return self._tokens_revocation_listeners.handle_tokens_revoked_events
-
-
-
-
-def dialog_cancellation(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def dialog_cancellation(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `dialog_cancellation` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_cancellation(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_cancellation listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dialog_submission(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def dialog_submission(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `dialog_submission` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_submission(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_submission listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dialog_suggestion(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def dialog_suggestion(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `dialog_suggestion` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_suggestion(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_suggestion listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dispatch(self,
req: BoltRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def dispatch(self, req: BoltRequest) -> BoltResponse:
-    """Applies all middleware and dispatches an incoming request from Slack to the right code path.
-
-    Args:
-        req: An incoming request from Slack
-
-    Returns:
-        The response generated by this Bolt app
-    """
-    starting_time = time.time()
-    self._init_context(req)
-
-    resp: Optional[BoltResponse] = BoltResponse(status=200, body="")
-    middleware_state = {"next_called": False}
-
-    def middleware_next():
-        middleware_state["next_called"] = True
-
-    try:
-        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)  # type: ignore[arg-type]
-            if not middleware_state["next_called"]:
-                if resp is None:
-                    # next() method was not called without providing the response to return to Slack
-                    # This should not be an intentional handling in usual use cases.
-                    resp = BoltResponse(status=404, body={"error": "no next() calls in middleware"})
-                    if self._raise_error_for_unhandled_request is True:
-                        try:
-                            raise BoltUnhandledRequestError(
-                                request=req,
-                                current_response=resp,
-                                last_global_middleware_name=middleware.name,
-                            )
-                        except BoltUnhandledRequestError as e:
-                            self._listener_runner.listener_error_handler.handle(
-                                error=e,
-                                request=req,
-                                response=resp,
-                            )
-                        return resp
-                    self._framework_logger.warning(warning_unhandled_by_global_middleware(middleware.name, req))
-                    return resp
-                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):  # type: ignore[arg-type]
-                # run all the middleware attached to this listener first
-                middleware_resp, next_was_not_called = listener.run_middleware(
-                    req=req, resp=resp  # type: ignore[arg-type]
-                )
-                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,  # type: ignore[arg-type]
-                    listener_name=listener_name,
-                    listener=listener,
-                )
-                if listener_response is not None:
-                    return listener_response
-
-        if resp is None:
-            resp = BoltResponse(status=404, body={"error": "unhandled request"})
-        if self._raise_error_for_unhandled_request is True:
-            try:
-                raise BoltUnhandledRequestError(
-                    request=req,
-                    current_response=resp,
-                )
-            except BoltUnhandledRequestError as e:
-                self._listener_runner.listener_error_handler.handle(
-                    error=e,
-                    request=req,
-                    response=resp,
-                )
-            return resp
-        return self._handle_unmatched_requests(req, resp)
-    except Exception as error:
-        resp = BoltResponse(status=500, body="")
-        self._middleware_error_handler.handle(
-            error=error,
-            request=req,
-            response=resp,
-        )
-        return resp
-
-

Applies all middleware and dispatches an incoming request from Slack to the right code path.

-

Args

-
-
req
-
An incoming request from Slack
-
-

Returns

-

The response generated by this Bolt app

-
-
-def enable_token_revocation_listeners(self) ‑> None -
-
-
- -Expand source code - -
def enable_token_revocation_listeners(self) -> None:
-    self.event("tokens_revoked")(self.default_tokens_revoked_event_listener())
-    self.event("app_uninstalled")(self.default_app_uninstalled_event_listener())
-
-
-
-
-def error(self,
func: Callable[..., BoltResponse | None]) ‑> Callable[..., BoltResponse | None]
-
-
-
- -Expand source code - -
def error(self, func: Callable[..., Optional[BoltResponse]]) -> Callable[..., Optional[BoltResponse]]:
-    """Updates the global error handler. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.error
-        def custom_error_handler(error, body, logger):
-            logger.exception(f"Error: {error}")
-            logger.info(f"Request body: {body}")
-
-        # Pass a function to this method
-        app.error(custom_error_handler)
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        func: The function that is supposed to be executed
-            when getting an unhandled error in Bolt app.
-    """
-    self._listener_runner.listener_error_handler = CustomListenerErrorHandler(
-        logger=self._framework_logger,
-        func=func,
-    )
-    self._middleware_error_handler = CustomMiddlewareErrorHandler(
-        logger=self._framework_logger,
-        func=func,
-    )
-    return func
-
-

Updates the global error handler. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.error
-def custom_error_handler(error, body, logger):
-    logger.exception(f"Error: {error}")
-    logger.info(f"Request body: {body}")
-
-# Pass a function to this method
-app.error(custom_error_handler)
-
-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
func
-
The function that is supposed to be executed -when getting an unhandled error in Bolt app.
-
-
-
-def event(self,
event: str | Pattern | Dict[str, str | Sequence[str | Pattern | None] | None],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def event(
-    self,
-    event: Union[
-        str,
-        Pattern,
-        Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]],
-    ],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new event listener. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.event("team_join")
-        def ask_for_introduction(event, say):
-            welcome_channel_id = "C12345"
-            user_id = event["user"]
-            text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-            say(text=text, channel=welcome_channel_id)
-
-        # Pass a function to this method
-        app.event("team_join")(ask_for_introduction)
-
-    Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        event: The conditions that match a request payload.
-            If you pass a dict for this, you can have type, subtype in the constraint.
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.event(event, base_logger=self._base_logger)
-        if self._attaching_conversation_kwargs_enabled:
-            middleware.insert(0, AttachingConversationKwargs(self._assistant_thread_context_store))
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-    return __call__
-
-

Registers a new event listener. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.event("team_join")
-def ask_for_introduction(event, say):
-    welcome_channel_id = "C12345"
-    user_id = event["user"]
-    text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-    say(text=text, channel=welcome_channel_id)
-
-# Pass a function to this method
-app.event("team_join")(ask_for_introduction)
-
-

Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
event
-
The conditions that match a request payload. -If you pass a dict for this, you can have type, subtype in the constraint.
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def function(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None,
auto_acknowledge: bool = True,
ack_timeout: int = 3) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def function(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    auto_acknowledge: bool = True,
-    ack_timeout: int = 3,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new Function listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.function("reverse")
-        def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail):
-            try:
-                ack()
-                string_to_reverse = inputs["stringToReverse"]
-                complete(outputs={"reverseString": string_to_reverse[::-1]})
-            except Exception as e:
-                fail(f"Cannot reverse string (error: {e})")
-                raise e
-
-        # Pass a function to this method
-        app.function("reverse")(reverse_string)
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        callback_id: The callback id to identify the function
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    if auto_acknowledge is True:
-        if ack_timeout != 3:
-            self._framework_logger.warning(warning_ack_timeout_has_no_effect(callback_id, ack_timeout))
-
-    matchers = list(matchers) if matchers else []
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.function_executed(callback_id=callback_id, base_logger=self._base_logger)
-        return self._register_listener(functions, primary_matcher, matchers, middleware, auto_acknowledge, ack_timeout)
-
-    return __call__
-
-

Registers a new Function listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.function("reverse")
-def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail):
-    try:
-        ack()
-        string_to_reverse = inputs["stringToReverse"]
-        complete(outputs={"reverseString": string_to_reverse[::-1]})
-    except Exception as e:
-        fail(f"Cannot reverse string (error: {e})")
-        raise e
-
-# Pass a function to this method
-app.function("reverse")(reverse_string)
-
-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
callback_id
-
The callback id to identify the function
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def global_shortcut(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def global_shortcut(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new global shortcut listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.global_shortcut(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new global shortcut listener.

-
-
-def message(self,
keyword: str | Pattern = '',
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def message(
-    self,
-    keyword: Union[str, Pattern] = "",
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new message event listener. This method can be used as either a decorator or a method.
-    Check the `App#event` method's docstring for details.
-
-        # Use this method as a decorator
-        @app.message(":wave:")
-        def say_hello(message, say):
-            user = message['user']
-            say(f"Hi there, <@{user}>!")
-
-        # Pass a function to this method
-        app.message(":wave:")(say_hello)
-
-    Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        keyword: The keyword to match
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-    matchers = list(matchers) if matchers else []
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        constraints = {
-            "type": "message",
-            "subtype": (
-                # In most cases, new message events come with no subtype.
-                None,
-                # As of Jan 2021, most bot messages no longer have the subtype bot_message.
-                # By contrast, messages posted using classic app's bot token still have the subtype.
-                "bot_message",
-                # If an end-user posts a message with "Also send to #channel" checked,
-                # the message event comes with this subtype.
-                "thread_broadcast",
-                # If an end-user posts a message with attached files,
-                # the message event comes with this subtype.
-                "file_share",
-            ),
-        }
-        primary_matcher = builtin_matchers.message_event(
-            keyword=keyword, constraints=constraints, base_logger=self._base_logger
-        )
-        if self._attaching_conversation_kwargs_enabled:
-            middleware.insert(0, AttachingConversationKwargs(self._assistant_thread_context_store))
-        middleware.insert(0, MessageListenerMatches(keyword))
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-    return __call__
-
-

Registers a new message event listener. This method can be used as either a decorator or a method. -Check the App#event method's docstring for details.

-
# Use this method as a decorator
-@app.message(":wave:")
-def say_hello(message, say):
-    user = message['user']
-    say(f"Hi there, <@{user}>!")
-
-# Pass a function to this method
-app.message(":wave:")(say_hello)
-
-

Refer to https://docs.slack.dev/reference/events/message/ for details of message events.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
keyword
-
The keyword to match
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def message_shortcut(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def message_shortcut(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new message shortcut listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.message_shortcut(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new message shortcut listener.

-
-
-def middleware(self, *args) ‑> Callable | None -
-
-
- -Expand source code - -
def middleware(self, *args) -> Optional[Callable]:
-    """Registers a new middleware to this app.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.middleware
-        def middleware_func(logger, body, next):
-            logger.info(f"request body: {body}")
-            next()
-
-        # Pass a function to this method
-        app.middleware(middleware_func)
-
-    Refer to https://docs.slack.dev/tools/bolt-python/concepts/global-middleware for details.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        *args: A function that works as a global middleware.
-    """
-    if len(args) > 0:
-        middleware_or_callable = args[0]
-        if isinstance(middleware_or_callable, Middleware):
-            middleware: Middleware = middleware_or_callable
-            self._middleware_list.append(middleware)
-            if isinstance(middleware, Assistant) and middleware.thread_context_store is not None:
-                self._assistant_thread_context_store = middleware.thread_context_store
-        elif callable(middleware_or_callable):
-            self._middleware_list.append(
-                CustomMiddleware(
-                    app_name=self.name,
-                    func=middleware_or_callable,
-                    base_logger=self._base_logger,
-                )
-            )
-            return middleware_or_callable
-        else:
-            raise BoltError(f"Unexpected type for a middleware ({type(middleware_or_callable)})")
-    return None
-
-

Registers a new middleware to this app. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.middleware
-def middleware_func(logger, body, next):
-    logger.info(f"request body: {body}")
-    next()
-
-# Pass a function to this method
-app.middleware(middleware_func)
-
-

Refer to https://docs.slack.dev/tools/bolt-python/concepts/global-middleware for details.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
*args
-
A function that works as a global middleware.
-
-
-
-def options(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def options(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new options listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.options("menu_selection")
-        def show_menu_options(ack):
-            options = [
-                {
-                    "text": {"type": "plain_text", "text": "Option 1"},
-                    "value": "1-1",
-                },
-                {
-                    "text": {"type": "plain_text", "text": "Option 2"},
-                    "value": "1-2",
-                },
-            ]
-            ack(options=options)
-
-        # Pass a function to this method
-        app.options("menu_selection")(show_menu_options)
-
-    Refer to the following documents for details:
-
-    * https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select
-    * https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.options(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new options listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.options("menu_selection")
-def show_menu_options(ack):
-    options = [
-        {
-            "text": {"type": "plain_text", "text": "Option 1"},
-            "value": "1-1",
-        },
-        {
-            "text": {"type": "plain_text", "text": "Option 2"},
-            "value": "1-2",
-        },
-    ]
-    ack(options=options)
-
-# Pass a function to this method
-app.options("menu_selection")(show_menu_options)
-
-

Refer to the following documents for details:

- -

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def shortcut(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def shortcut(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new shortcut listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.shortcut("open_modal")
-        def open_modal(ack, body, client):
-            # Acknowledge the command request
-            ack()
-            # Call views_open with the built-in client
-            client.views_open(
-                # Pass a valid trigger_id within 3 seconds of receiving it
-                trigger_id=body["trigger_id"],
-                # View payload
-                view={ ... }
-            )
-
-        # Pass a function to this method
-        app.shortcut("open_modal")(open_modal)
-
-    Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload.
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.shortcut(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new shortcut listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.shortcut("open_modal")
-def open_modal(ack, body, client):
-    # Acknowledge the command request
-    ack()
-    # Call views_open with the built-in client
-    client.views_open(
-        # Pass a valid trigger_id within 3 seconds of receiving it
-        trigger_id=body["trigger_id"],
-        # View payload
-        view={ ... }
-    )
-
-# Pass a function to this method
-app.shortcut("open_modal")(open_modal)
-
-

Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload.
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def start(self,
port: int = 3000,
path: str = '/slack/events',
http_server_logger_enabled: bool = True) ‑> None
-
-
-
- -Expand source code - -
def start(
-    self,
-    port: int = 3000,
-    path: str = "/slack/events",
-    http_server_logger_enabled: bool = True,
-) -> None:
-    """Starts a web server for local development.
-
-        # With the default settings, `http://localhost:3000/slack/events`
-        # is available for handling incoming requests from Slack
-        app.start()
-
-    This method internally starts a Web server process built with the `http.server` module.
-    For production, consider using a production-ready WSGI server such as Gunicorn.
-
-    Args:
-        port: The port to listen on (Default: 3000)
-        path: The path to handle request from Slack (Default: `/slack/events`)
-        http_server_logger_enabled: The flag to enable http.server logging if True (Default: True)
-    """
-    self._development_server = SlackAppDevelopmentServer(
-        port=port,
-        path=path,
-        app=self,
-        oauth_flow=self.oauth_flow,
-        http_server_logger_enabled=http_server_logger_enabled,
-    )
-    self._development_server.start()
-
-

Starts a web server for local development.

-
# With the default settings, `http://localhost:3000/slack/events`
-# is available for handling incoming requests from Slack
-app.start()
-
-

This method internally starts a Web server process built with the http.server module. -For production, consider using a production-ready WSGI server such as Gunicorn.

-

Args

-
-
port
-
The port to listen on (Default: 3000)
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
http_server_logger_enabled
-
The flag to enable http.server logging if True (Default: True)
-
-
-
-def step(self,
callback_id: str | Pattern | WorkflowStep | WorkflowStepBuilder,
edit: Callable[..., BoltResponse | None] | Listener | Sequence[Callable] | None = None,
save: Callable[..., BoltResponse | None] | Listener | Sequence[Callable] | None = None,
execute: Callable[..., BoltResponse | None] | Listener | Sequence[Callable] | None = None)
-
-
-
- -Expand source code - -
def step(
-    self,
-    callback_id: Union[str, Pattern, WorkflowStep, WorkflowStepBuilder],
-    edit: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-    save: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-    execute: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-):
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Registers a new step from app listener.
-
-    Unlike others, this method doesn't behave as a decorator.
-    If you want to register a step from app by a decorator, use `WorkflowStepBuilder`'s methods.
-
-        # Create a new WorkflowStep instance
-        from slack_bolt.workflows.step import WorkflowStep
-        ws = WorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        # Pass Step to set up listeners
-        app.step(ws)
-
-    Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    For further information about WorkflowStep specific function arguments
-    such as `configure`, `update`, `complete`, and `fail`,
-    refer to `slack_bolt.workflows.step.utilities` API documents.
-
-    Args:
-        callback_id: The Callback ID for this step from app
-        edit: The function for displaying a modal in the Workflow Builder
-        save: The function for handling configuration in the Workflow Builder
-        execute: The function for handling the step execution
-    """
-    warnings.warn(
-        (
-            "Steps from apps for legacy workflows are now deprecated. "
-            "Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/"
-        ),
-        category=DeprecationWarning,
-    )
-    step = callback_id
-    if isinstance(callback_id, (str, Pattern)):
-        step = WorkflowStep(
-            callback_id=callback_id,
-            edit=edit,  # type: ignore[arg-type]
-            save=save,  # type: ignore[arg-type]
-            execute=execute,  # type: ignore[arg-type]
-            base_logger=self._base_logger,
-        )
-    elif isinstance(step, WorkflowStepBuilder):
-        step = step.build(base_logger=self._base_logger)
-    elif not isinstance(step, WorkflowStep):
-        raise BoltError(f"Invalid step object ({type(step)})")
-
-    self.use(WorkflowStepMiddleware(step))
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Registers a new step from app listener.

-

Unlike others, this method doesn't behave as a decorator. -If you want to register a step from app by a decorator, use WorkflowStepBuilder's methods.

-
# Create a new WorkflowStep instance
-from slack_bolt.workflows.step import WorkflowStep
-ws = WorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-# Pass Step to set up listeners
-app.step(ws)
-
-

Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

For further information about WorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
callback_id
-
The Callback ID for this step from app
-
edit
-
The function for displaying a modal in the Workflow Builder
-
save
-
The function for handling configuration in the Workflow Builder
-
execute
-
The function for handling the step execution
-
-
-
-def use(self, *args) ‑> Callable | None -
-
-
- -Expand source code - -
def use(self, *args) -> Optional[Callable]:
-    """Registers a new global middleware to this app. This method can be used as either a decorator or a method.
-
-    Refer to `App#middleware()` method's docstring for details."""
-    return self.middleware(*args)
-
-

Registers a new global middleware to this app. This method can be used as either a decorator or a method.

-

Refer to App#middleware() method's docstring for details.

-
-
-def view(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def view(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `view_submission`/`view_closed` event listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.view("view_1")
-        def handle_submission(ack, body, client, view):
-            # Assume there's an input block with `block_c` as the block_id and `dreamy_input`
-            hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-            user = body["user"]["id"]
-            # Validate the inputs
-            errors = {}
-            if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-                errors["block_c"] = "The value must be longer than 5 characters"
-            if len(errors) > 0:
-                ack(response_action="errors", errors=errors)
-                return
-            # Acknowledge the view_submission event and close the modal
-            ack()
-            # Do whatever you want with the input data - here we're saving it to a DB
-
-        # Pass a function to this method
-        app.view("view_1")(handle_submission)
-
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new view_submission/view_closed event listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.view("view_1")
-def handle_submission(ack, body, client, view):
-    # Assume there's an input block with <code>block\_c</code> as the block_id and <code>dreamy\_input</code>
-    hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-    user = body["user"]["id"]
-    # Validate the inputs
-    errors = {}
-    if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-        errors["block_c"] = "The value must be longer than 5 characters"
-    if len(errors) > 0:
-        ack(response_action="errors", errors=errors)
-        return
-    # Acknowledge the view_submission event and close the modal
-    ack()
-    # Do whatever you want with the input data - here we're saving it to a DB
-
-# Pass a function to this method
-app.view("view_1")(handle_submission)
-
-

Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def view_closed(self,
constraints: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def view_closed(
-    self,
-    constraints: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `view_closed` listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view_closed(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
- -
-
-def view_submission(self,
constraints: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def view_submission(
-    self,
-    constraints: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `view_submission` listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for
-    details.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view_submission(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new view_submission listener. -Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for -details.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/async_app.html b/docs/reference/async_app.html deleted file mode 100644 index 670ba58d0..000000000 --- a/docs/reference/async_app.html +++ /dev/null @@ -1,5739 +0,0 @@ - - - - - - -slack_bolt.async_app API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.async_app

-
-
-

Module for creating asyncio based apps

-

Creating an async app

-

If you'd prefer to build your app with asyncio, you can import the AIOHTTP library and call the AsyncApp constructor. Within async apps, you can use the async/await pattern.

-
# Python 3.7+ required
-python -m venv .venv
-source .venv/bin/activate
-
-pip install -U pip
-# aiohttp is required
-pip install slack_bolt aiohttp
-
-

In async apps, all middleware/listeners must be async functions. When calling utility methods (like ack and say) within these functions, it's required to use the await keyword.

-
# Import the async app instead of the regular one
-from slack_bolt.async_app import AsyncApp
-
-app = AsyncApp()
-
-@app.event("app_mention")
-async def event_test(body, say, logger):
-    logger.info(body)
-    await say("What's up?")
-
-@app.command("/hello-bolt-python")
-async def command(ack, body, respond):
-    await ack()
-    await respond(f"Hi <@{body['user_id']}>!")
-
-if __name__ == "__main__":
-    app.start(3000)
-
-

If you want to use another async Web framework (e.g., Sanic, FastAPI, Starlette), take a look at the built-in adapters and their examples.

- -

Refer to slack_bolt.app.async_app for more details.

-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncAck -
-
-
- -Expand source code - -
class AsyncAck:
-    response: Optional[BoltResponse]
-
-    def __init__(self):
-        self.response: Optional[BoltResponse] = None
-
-    async def __call__(
-        self,
-        text: Union[str, dict] = "",  # text: str or whole_response: dict
-        blocks: Optional[Sequence[Union[dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[dict, Attachment]]] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        response_type: Optional[str] = None,  # in_channel / ephemeral
-        # block_suggestion / dialog_suggestion
-        options: Optional[Sequence[Union[dict, Option]]] = None,
-        option_groups: Optional[Sequence[Union[dict, OptionGroup]]] = None,
-        # view_submission
-        response_action: Optional[str] = None,  # errors / update / push / clear
-        errors: Optional[Dict[str, str]] = None,
-        view: Optional[Union[dict, View]] = None,
-    ) -> BoltResponse:
-        return _set_response(
-            self,
-            text_or_whole_response=text,
-            blocks=blocks,
-            attachments=attachments,
-            unfurl_links=unfurl_links,
-            unfurl_media=unfurl_media,
-            response_type=response_type,
-            options=options,
-            option_groups=option_groups,
-            response_action=response_action,
-            errors=errors,
-            view=view,
-        )
-
-
-

Class variables

-
-
var responseBoltResponse | None
-
-

The type of the None singleton.

-
-
-
-
-class AsyncApp -(*,
logger: logging.Logger | None = None,
name: str | None = None,
process_before_response: bool = False,
raise_error_for_unhandled_request: bool = False,
signing_secret: str | None = None,
token: str | None = None,
client: slack_sdk.web.async_client.AsyncWebClient | None = None,
before_authorize: AsyncMiddleware | Callable[..., Awaitable[Any]] | None = None,
authorize: Callable[..., Awaitable[AuthorizeResult]] | None = None,
user_facing_authorize_error_message: str | None = None,
installation_store: slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore | None = None,
installation_store_bot_only: bool | None = None,
request_verification_enabled: bool = True,
ignoring_self_events_enabled: bool = True,
ignoring_self_assistant_message_events_enabled: bool = True,
ssl_check_enabled: bool = True,
url_verification_enabled: bool = True,
attaching_function_token_enabled: bool = True,
oauth_settings: AsyncOAuthSettings | None = None,
oauth_flow: AsyncOAuthFlow | None = None,
verification_token: str | None = None,
assistant_thread_context_store: AsyncAssistantThreadContextStore | None = None,
attaching_conversation_kwargs_enabled: bool = True)
-
-
-
- -Expand source code - -
class AsyncApp:
-    def __init__(
-        self,
-        *,
-        logger: Optional[logging.Logger] = None,
-        # Used in logger
-        name: Optional[str] = None,
-        # Set True when you run this app on a FaaS platform
-        process_before_response: bool = False,
-        # Set True if you want to handle an unhandled request as an exception
-        raise_error_for_unhandled_request: bool = False,
-        # Basic Information > Credentials > Signing Secret
-        signing_secret: Optional[str] = None,
-        # for single-workspace apps
-        token: Optional[str] = None,
-        client: Optional[AsyncWebClient] = None,
-        # for multi-workspace apps
-        before_authorize: Optional[Union[AsyncMiddleware, Callable[..., Awaitable[Any]]]] = None,
-        authorize: Optional[Callable[..., Awaitable[AuthorizeResult]]] = None,
-        user_facing_authorize_error_message: Optional[str] = None,
-        installation_store: Optional[AsyncInstallationStore] = None,
-        # for either only bot scope usage or v1.0.x compatibility
-        installation_store_bot_only: Optional[bool] = None,
-        # for customizing the built-in middleware
-        request_verification_enabled: bool = True,
-        ignoring_self_events_enabled: bool = True,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-        ssl_check_enabled: bool = True,
-        url_verification_enabled: bool = True,
-        attaching_function_token_enabled: bool = True,
-        # for the OAuth flow
-        oauth_settings: Optional[AsyncOAuthSettings] = None,
-        oauth_flow: Optional[AsyncOAuthFlow] = None,
-        # No need to set (the value is used only in response to ssl_check requests)
-        verification_token: Optional[str] = None,
-        # for AI Agents & Assistants
-        assistant_thread_context_store: Optional[AsyncAssistantThreadContextStore] = None,
-        attaching_conversation_kwargs_enabled: bool = True,
-    ):
-        """Bolt App that provides functionalities to register middleware/listeners.
-
-            import os
-            from slack_bolt.async_app import AsyncApp
-
-            # Initializes your app with your bot token and signing secret
-            app = AsyncApp(
-                token=os.environ.get("SLACK_BOT_TOKEN"),
-                signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
-            )
-
-            # Listens to incoming messages that contain "hello"
-            @app.message("hello")
-            async def message_hello(message, say):  # async function
-                # say() sends a message to the channel where the event was triggered
-                await say(f"Hey there <@{message['user']}>!")
-
-            # Start your app
-            if __name__ == "__main__":
-                app.start(port=int(os.environ.get("PORT", 3000)))
-
-        Refer to https://docs.slack.dev/tools/bolt-python/concepts/async for details.
-
-        If you would like to build an OAuth app for enabling the app to run with multiple workspaces,
-        refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app.
-
-        Args:
-            logger: The custom logger that can be used in this app.
-            name: The application name that will be used in logging. If absent, the source file name will be used.
-            process_before_response: True if this app runs on Function as a Service. (Default: False)
-            raise_error_for_unhandled_request: True if you want to raise exceptions for unhandled requests
-                and use @app.error listeners instead of
-                the built-in handler, which pints warning logs and returns 404 to Slack (Default: False)
-            signing_secret: The Signing Secret value used for verifying requests from Slack.
-            token: The bot/user access token required only for single-workspace app.
-            client: The singleton `slack_sdk.web.async_client.AsyncWebClient` instance for this app.
-            before_authorize: A global middleware that can be executed right before authorize function
-            authorize: The function to authorize an incoming request from Slack
-                by checking if there is a team/user in the installation data.
-            user_facing_authorize_error_message: The user-facing error message to display
-                when the app is installed but the installation is not managed by this app's installation store
-            installation_store: The module offering save/find operations of installation data
-            installation_store_bot_only: Use `AsyncInstallationStore#async_find_bot()` if True (Default: False)
-            request_verification_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `AsyncRequestVerification` is a built-in middleware that verifies the signature in HTTP Mode requests.
-                Make sure if it's safe enough when you turn a built-in middleware off.
-                We strongly recommend using RequestVerification for better security.
-                If you have a proxy that verifies request signature in front of the Bolt app,
-                it's totally fine to disable RequestVerification to avoid duplication of work.
-                Don't turn it off just for easiness of development.
-            ignoring_self_events_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `AsyncIgnoringSelfEvents` is a built-in middleware that enables Bolt apps to easily skip the events
-                generated by this app's bot user (this is useful for avoiding code error causing an infinite loop).
-            ignoring_self_assistant_message_events_enabled: False if you would like to disable the built-in middleware.
-                `IgnoringSelfEvents` for this app's bot user message events within an assistant thread
-                This is useful for avoiding code error causing an infinite loop; Default: True
-            url_verification_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `AsyncUrlVerification` is a built-in middleware that handles url_verification requests
-                that verify the endpoint for Events API in HTTP Mode requests.
-            ssl_check_enabled: bool = False if you would like to disable the built-in middleware (Default: True).
-                `AsyncSslCheck` is a built-in middleware that handles ssl_check requests from Slack.
-            attaching_function_token_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `AsyncAttachingFunctionToken` is a built-in middleware that injects the just-in-time workflow-execution token
-                when your app receives `function_executed` or interactivity events scoped to a custom step.
-            oauth_settings: The settings related to Slack app installation flow (OAuth flow)
-            oauth_flow: Instantiated `slack_bolt.oauth.AsyncOAuthFlow`. This is always prioritized over oauth_settings.
-            verification_token: Deprecated verification mechanism. This can be used only for ssl_check requests.
-            assistant_thread_context_store: Custom AssistantThreadContext store (Default: the built-in implementation,
-                which uses a parent message's metadata to store the latest context)
-        """
-        if signing_secret is None:
-            signing_secret = os.environ.get("SLACK_SIGNING_SECRET", "")
-        token = token or os.environ.get("SLACK_BOT_TOKEN")
-
-        self._name: str = name or inspect.stack()[1].filename.split(os.path.sep)[-1]
-        self._signing_secret: str = signing_secret
-        self._verification_token: Optional[str] = verification_token or os.environ.get("SLACK_VERIFICATION_TOKEN", None)
-        # If a logger is explicitly passed when initializing, the logger works as the base logger.
-        # The base logger's logging settings will be propagated to all the loggers created by bolt-python.
-        self._base_logger = logger
-        # The framework logger is supposed to be used for the internal logging.
-        # Also, it's accessible via `app.logger` as the app's singleton logger.
-        self._framework_logger = logger or get_bolt_logger(AsyncApp)
-        self._raise_error_for_unhandled_request = raise_error_for_unhandled_request
-
-        self._token: Optional[str] = token
-
-        if client is not None:
-            if not isinstance(client, AsyncWebClient):
-                raise BoltError(error_client_invalid_type_async())
-            self._async_client = client
-            self._token = client.token
-            if token is not None:
-                self._framework_logger.warning(warning_client_prioritized_and_token_skipped())
-        else:
-            self._async_client = create_async_web_client(
-                # NOTE: the token here can be None
-                token=token,
-                logger=self._framework_logger,
-            )
-
-        # --------------------------------------
-        # Authorize & OAuthFlow initialization
-        # --------------------------------------
-
-        self._async_before_authorize: Optional[AsyncMiddleware] = None
-        if before_authorize is not None:
-            if callable(before_authorize):
-                self._async_before_authorize = AsyncCustomMiddleware(
-                    app_name=self._name,
-                    func=before_authorize,
-                    base_logger=self._framework_logger,
-                )
-            elif isinstance(before_authorize, AsyncMiddleware):
-                self._async_before_authorize = before_authorize
-
-        self._async_authorize: Optional[AsyncAuthorize] = None
-        if authorize is not None:
-            if isinstance(authorize, AsyncAuthorize):
-                # As long as an advanced developer understands what they're doing,
-                # bolt-python should not prevent customizing authorize middleware
-                self._async_authorize = authorize
-            else:
-                if oauth_settings is not None or oauth_flow is not None:
-                    # If the given authorize is a simple function,
-                    # it does not work along with installation_store.
-                    raise BoltError(error_authorize_conflicts())
-                self._async_authorize = AsyncCallableAuthorize(logger=self._framework_logger, func=authorize)
-
-        self._async_installation_store: Optional[AsyncInstallationStore] = installation_store
-        if self._async_installation_store is not None and self._async_authorize is None:
-            settings = oauth_flow.settings if oauth_flow is not None else oauth_settings
-            self._async_authorize = AsyncInstallationStoreAuthorize(
-                installation_store=self._async_installation_store,
-                client_id=settings.client_id if settings is not None else None,
-                client_secret=settings.client_secret if settings is not None else None,
-                logger=self._framework_logger,
-                bot_only=installation_store_bot_only or False,
-                client=self._async_client,  # for proxy use cases etc.
-                user_token_resolution=(settings.user_token_resolution if settings is not None else "authed_user"),
-            )
-
-        self._async_oauth_flow: Optional[AsyncOAuthFlow] = None
-
-        if (
-            oauth_settings is None
-            and os.environ.get("SLACK_CLIENT_ID") is not None
-            and os.environ.get("SLACK_CLIENT_SECRET") is not None
-        ):
-            # initialize with the default settings
-            oauth_settings = AsyncOAuthSettings()
-
-            if oauth_flow is None and installation_store is None:
-                # show info-level log for avoiding confusions
-                self._framework_logger.info(info_default_oauth_settings_loaded())
-
-        if oauth_flow:
-            if not isinstance(oauth_flow, AsyncOAuthFlow):
-                raise BoltError(error_oauth_flow_invalid_type_async())
-
-            self._async_oauth_flow = oauth_flow
-            installation_store = select_consistent_installation_store(
-                client_id=self._async_oauth_flow.client_id,
-                app_store=self._async_installation_store,
-                oauth_flow_store=self._async_oauth_flow.settings.installation_store,
-                logger=self._framework_logger,
-            )
-            self._async_installation_store = installation_store
-            if installation_store is not None:
-                self._async_oauth_flow.settings.installation_store = installation_store
-
-            if self._async_oauth_flow._async_client is None:
-                self._async_oauth_flow._async_client = self._async_client
-            if self._async_authorize is None:
-                self._async_authorize = self._async_oauth_flow.settings.authorize
-        elif oauth_settings is not None:
-            if not isinstance(oauth_settings, AsyncOAuthSettings):
-                raise BoltError(error_oauth_settings_invalid_type_async())
-
-            installation_store = select_consistent_installation_store(
-                client_id=oauth_settings.client_id,
-                app_store=self._async_installation_store,
-                oauth_flow_store=oauth_settings.installation_store,
-                logger=self._framework_logger,
-            )
-            self._async_installation_store = installation_store
-            if installation_store is not None:
-                oauth_settings.installation_store = installation_store
-
-            self._async_oauth_flow = AsyncOAuthFlow(client=self._async_client, logger=self.logger, settings=oauth_settings)
-            if self._async_authorize is None:
-                self._async_authorize = self._async_oauth_flow.settings.authorize
-            self._async_authorize.token_rotation_expiration_minutes = oauth_settings.token_rotation_expiration_minutes  # type: ignore[attr-defined] # noqa: E501
-
-        if (self._async_installation_store is not None or self._async_authorize is not None) and self._token is not None:
-            self._token = None
-            self._framework_logger.warning(warning_token_skipped())
-
-        # after setting bot_only here, __init__ cannot replace authorize function
-        if installation_store_bot_only is not None and self._async_oauth_flow is not None:
-            app_bot_only = installation_store_bot_only or False
-            oauth_flow_bot_only = self._async_oauth_flow.settings.installation_store_bot_only
-            if app_bot_only != oauth_flow_bot_only:
-                self.logger.warning(warning_bot_only_conflicts())
-                self._async_oauth_flow.settings.installation_store_bot_only = app_bot_only
-                self._async_authorize.bot_only = app_bot_only  # type: ignore[union-attr]
-
-        self._async_tokens_revocation_listeners: Optional[AsyncTokenRevocationListeners] = None
-        if self._async_installation_store is not None:
-            self._async_tokens_revocation_listeners = AsyncTokenRevocationListeners(self._async_installation_store)
-
-        # --------------------------------------
-        # Middleware Initialization
-        # --------------------------------------
-
-        self._async_middleware_list: List[AsyncMiddleware] = []
-        self._async_listeners: List[AsyncListener] = []
-
-        self._assistant_thread_context_store = assistant_thread_context_store
-        self._attaching_conversation_kwargs_enabled = attaching_conversation_kwargs_enabled
-
-        self._process_before_response = process_before_response
-        self._async_listener_runner = AsyncioListenerRunner(
-            logger=self._framework_logger,
-            process_before_response=process_before_response,
-            listener_error_handler=AsyncDefaultListenerErrorHandler(logger=self._framework_logger),
-            listener_start_handler=AsyncDefaultListenerStartHandler(logger=self._framework_logger),
-            listener_completion_handler=AsyncDefaultListenerCompletionHandler(logger=self._framework_logger),
-            lazy_listener_runner=AsyncioLazyListenerRunner(
-                logger=self._framework_logger,
-            ),
-        )
-        self._async_middleware_error_handler: AsyncMiddlewareErrorHandler = AsyncDefaultMiddlewareErrorHandler(
-            logger=self._framework_logger,
-        )
-
-        self._init_middleware_list_done = False
-        self._init_async_middleware_list(
-            request_verification_enabled=request_verification_enabled,
-            ignoring_self_events_enabled=ignoring_self_events_enabled,
-            ignoring_self_assistant_message_events_enabled=ignoring_self_assistant_message_events_enabled,
-            ssl_check_enabled=ssl_check_enabled,
-            url_verification_enabled=url_verification_enabled,
-            attaching_function_token_enabled=attaching_function_token_enabled,
-            user_facing_authorize_error_message=user_facing_authorize_error_message,
-        )
-
-        self._server: Optional[AsyncSlackAppServer] = None
-
-    def _init_async_middleware_list(
-        self,
-        request_verification_enabled: bool = True,
-        ignoring_self_events_enabled: bool = True,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-        ssl_check_enabled: bool = True,
-        url_verification_enabled: bool = True,
-        attaching_function_token_enabled: bool = True,
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        if self._init_middleware_list_done:
-            return
-        if ssl_check_enabled is True:
-            self._async_middleware_list.append(
-                AsyncSslCheck(
-                    verification_token=self._verification_token,
-                    base_logger=self._base_logger,
-                )
-            )
-        if request_verification_enabled is True:
-            self._async_middleware_list.append(AsyncRequestVerification(self._signing_secret, base_logger=self._base_logger))
-
-        if self._async_before_authorize is not None:
-            self._async_middleware_list.append(self._async_before_authorize)
-
-        # As authorize is required for making a Bolt app function, we don't offer the flag to disable this
-        if self._async_oauth_flow is None:
-            if self._token:
-                self._async_middleware_list.append(
-                    AsyncSingleTeamAuthorization(
-                        base_logger=self._base_logger,
-                        user_facing_authorize_error_message=user_facing_authorize_error_message,
-                    )
-                )
-            elif self._async_authorize is not None:
-                self._async_middleware_list.append(
-                    AsyncMultiTeamsAuthorization(
-                        authorize=self._async_authorize,
-                        base_logger=self._base_logger,
-                        user_facing_authorize_error_message=user_facing_authorize_error_message,
-                    )
-                )
-            else:
-                raise BoltError(error_token_required())
-        elif self._async_authorize is not None:
-            self._async_middleware_list.append(
-                AsyncMultiTeamsAuthorization(
-                    authorize=self._async_authorize,
-                    base_logger=self._base_logger,
-                    user_token_resolution=self._async_oauth_flow.settings.user_token_resolution,
-                    user_facing_authorize_error_message=user_facing_authorize_error_message,
-                )
-            )
-        else:
-            raise BoltError(error_oauth_flow_or_authorize_required())
-
-        if ignoring_self_events_enabled is True:
-            self._async_middleware_list.append(
-                AsyncIgnoringSelfEvents(
-                    base_logger=self._base_logger,
-                    ignoring_self_assistant_message_events_enabled=ignoring_self_assistant_message_events_enabled,
-                )
-            )
-        if url_verification_enabled is True:
-            self._async_middleware_list.append(AsyncUrlVerification(base_logger=self._base_logger))
-        if attaching_function_token_enabled is True:
-            self._async_middleware_list.append(AsyncAttachingFunctionToken())
-        self._init_middleware_list_done = True
-
-    # -------------------------
-    # accessors
-
-    @property
-    def name(self) -> str:
-        """The name of this app (default: the filename)"""
-        return self._name
-
-    @property
-    def oauth_flow(self) -> Optional[AsyncOAuthFlow]:
-        """Configured `OAuthFlow` object if exists."""
-        return self._async_oauth_flow
-
-    @property
-    def client(self) -> AsyncWebClient:
-        """The singleton `slack_sdk.web.async_client.AsyncWebClient` instance in this app."""
-        return self._async_client
-
-    @property
-    def logger(self) -> logging.Logger:
-        """The logger this app uses."""
-        return self._framework_logger
-
-    @property
-    def installation_store(self) -> Optional[AsyncInstallationStore]:
-        """The `slack_sdk.oauth.AsyncInstallationStore` that can be used in the `authorize` middleware."""
-        return self._async_installation_store
-
-    @property
-    def listener_runner(self) -> AsyncioListenerRunner:
-        """The asyncio-based executor for asynchronously running listeners."""
-        return self._async_listener_runner
-
-    @property
-    def process_before_response(self) -> bool:
-        return self._process_before_response or False
-
-    # -------------------------
-    # standalone server
-
-    from .async_server import AsyncSlackAppServer
-
-    def server(
-        self,
-        port: int = 3000,
-        path: str = "/slack/events",
-        host: Optional[str] = None,
-    ) -> AsyncSlackAppServer:
-        """Configure a web server using AIOHTTP.
-        Refer to https://docs.aiohttp.org/ for more details about AIOHTTP.
-
-        Args:
-            port: The port to listen on (Default: 3000)
-            path: The path to handle request from Slack (Default: `/slack/events`)
-            host: The hostname to serve the web endpoints. (Default: 0.0.0.0)
-        """
-        if self._server is None or self._server.port != port or self._server.path != path:
-            self._server = AsyncSlackAppServer(
-                port=port,
-                path=path,
-                app=self,
-                host=host,
-            )
-        return self._server
-
-    def web_app(self, path: str = "/slack/events", port: int = 3000) -> web.Application:
-        """Returns a `web.Application` instance for aiohttp-devtools users.
-
-            from slack_bolt.async_app import AsyncApp
-            app = AsyncApp()
-
-            @app.event("app_mention")
-            async def event_test(body, say, logger):
-                logger.info(body)
-                await say("What's up?")
-
-            def app_factory():
-                return app.web_app()
-
-            # adev runserver --port 3000 --app-factory app_factory async_app.py
-
-        Args:
-            path: The path to receive incoming requests from Slack
-            port: The port to listen on (Default: 3000)
-        """
-        return self.server(path=path, port=port).web_app
-
-    def start(self, port: int = 3000, path: str = "/slack/events", host: Optional[str] = None) -> None:
-        """Start a web server using AIOHTTP.
-        Refer to https://docs.aiohttp.org/ for more details about AIOHTTP.
-
-        Args:
-            port: The port to listen on (Default: 3000)
-            path: The path to handle request from Slack (Default: `/slack/events`)
-            host: The hostname to serve the web endpoints. (Default: 0.0.0.0)
-        """
-        self.server(port=port, path=path, host=host).start()
-
-    # -------------------------
-    # main dispatcher
-
-    async def async_dispatch(self, req: AsyncBoltRequest) -> BoltResponse:
-        """Applies all middleware and dispatches an incoming request from Slack to the right code path.
-
-        Args:
-            req: An incoming request from Slack.
-
-        Returns:
-            The response generated by this Bolt app.
-        """
-        starting_time = time.time()
-        self._init_context(req)
-
-        resp: Optional[BoltResponse] = BoltResponse(status=200, body="")
-        middleware_state = {"next_called": False}
-
-        async def async_middleware_next():
-            middleware_state["next_called"] = True
-
-        try:
-            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  # type: ignore[arg-type]
-                )
-                if not middleware_state["next_called"]:
-                    if resp is None:
-                        # next() method was not called without providing the response to return to Slack
-                        # This should not be an intentional handling in usual use cases.
-                        resp = BoltResponse(status=404, body={"error": "no next() calls in middleware"})
-                        if self._raise_error_for_unhandled_request is True:
-                            try:
-                                raise BoltUnhandledRequestError(
-                                    request=req,
-                                    current_response=resp,
-                                    last_global_middleware_name=middleware.name,
-                                )
-                            except BoltUnhandledRequestError as e:
-                                await self._async_listener_runner.listener_error_handler.handle(
-                                    error=e,
-                                    request=req,
-                                    response=resp,
-                                )
-                            return resp
-                        self._framework_logger.warning(warning_unhandled_by_global_middleware(middleware.name, req))
-                        return resp
-                    return resp
-
-            for listener in self._async_listeners:
-                listener_name = get_name_for_callable(listener.ack_function)
-                self._framework_logger.debug(debug_checking_listener(listener_name))
-                if await listener.async_matches(req=req, resp=resp):  # type: ignore[arg-type]
-                    # run all the middleware attached to this listener first
-                    middleware_resp, next_was_not_called = await listener.run_async_middleware(
-                        req=req, resp=resp  # type: ignore[arg-type]
-                    )
-                    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] = await self._async_listener_runner.run(
-                        request=req,
-                        response=resp,  # type: ignore[arg-type]
-                        listener_name=listener_name,
-                        listener=listener,
-                    )
-                    if listener_response is not None:
-                        return listener_response
-
-            if resp is None:
-                resp = BoltResponse(status=404, body={"error": "unhandled request"})
-            if self._raise_error_for_unhandled_request is True:
-                try:
-                    raise BoltUnhandledRequestError(
-                        request=req,
-                        current_response=resp,
-                    )
-                except BoltUnhandledRequestError as e:
-                    await self._async_listener_runner.listener_error_handler.handle(
-                        error=e,
-                        request=req,
-                        response=resp,
-                    )
-                return resp
-            return self._handle_unmatched_requests(req, resp)
-
-        except Exception as error:
-            resp = BoltResponse(status=500, body="")
-            await self._async_middleware_error_handler.handle(
-                error=error,
-                request=req,
-                response=resp,
-            )
-            return resp
-
-    def _handle_unmatched_requests(self, req: AsyncBoltRequest, resp: BoltResponse) -> BoltResponse:
-        self._framework_logger.warning(warning_unhandled_request(req))
-        return resp
-
-    # -------------------------
-    # middleware
-
-    def use(self, *args) -> Optional[Callable]:
-        """Refer to `AsyncApp#middleware()` method's docstring for details."""
-        return self.middleware(*args)
-
-    def middleware(self, *args) -> Optional[Callable]:
-        """Registers a new middleware to this app.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.middleware
-            async def middleware_func(logger, body, next):
-                logger.info(f"request body: {body}")
-                await next()
-
-            # Pass a function to this method
-            app.middleware(middleware_func)
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            *args: A function that works as a global middleware.
-        """
-        if len(args) > 0:
-            middleware_or_callable = args[0]
-            if isinstance(middleware_or_callable, AsyncMiddleware):
-                middleware: AsyncMiddleware = middleware_or_callable
-                self._async_middleware_list.append(middleware)
-                if isinstance(middleware, AsyncAssistant) and middleware.thread_context_store is not None:
-                    self._assistant_thread_context_store = middleware.thread_context_store
-            elif callable(middleware_or_callable):
-                self._async_middleware_list.append(
-                    AsyncCustomMiddleware(
-                        app_name=self.name,
-                        func=middleware_or_callable,
-                        base_logger=self._base_logger,
-                    )
-                )
-                return middleware_or_callable
-            else:
-                raise BoltError(f"Unexpected type for a middleware ({type(middleware_or_callable)})")
-        return None
-
-    def assistant(self, assistant: AsyncAssistant) -> Optional[Callable]:
-        return self.middleware(assistant)
-
-    # -------------------------
-    # Workflows: Steps from apps
-
-    def step(
-        self,
-        callback_id: Union[str, Pattern, AsyncWorkflowStep, AsyncWorkflowStepBuilder],
-        edit: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None,
-        save: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None,
-        execute: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Registers a new step from app listener.
-
-        Unlike others, this method doesn't behave as a decorator.
-        If you want to register a step from app by a decorator, use `AsyncWorkflowStepBuilder`'s methods.
-
-            # Create a new WorkflowStep instance
-            from slack_bolt.workflows.async_step import AsyncWorkflowStep
-            ws = AsyncWorkflowStep(
-                callback_id="add_task",
-                edit=edit,
-                save=save,
-                execute=execute,
-            )
-            # Pass Step to set up listeners
-            app.step(ws)
-
-        Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-        For further information about AsyncWorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            callback_id: The Callback ID for this step from app
-            edit: The function for displaying a modal in the Workflow Builder
-            save: The function for handling configuration in the Workflow Builder
-            execute: The function for handling the step execution
-        """
-        warnings.warn(
-            (
-                "Steps from apps for legacy workflows are now deprecated. "
-                "Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/"
-            ),
-            category=DeprecationWarning,
-        )
-        step = callback_id
-        if isinstance(callback_id, (str, Pattern)):
-            step = AsyncWorkflowStep(
-                callback_id=callback_id,
-                edit=edit,  # type: ignore[arg-type]
-                save=save,  # type: ignore[arg-type]
-                execute=execute,  # type: ignore[arg-type]
-                base_logger=self._base_logger,
-            )
-        elif isinstance(step, AsyncWorkflowStepBuilder):
-            step = step.build(base_logger=self._base_logger)
-        elif not isinstance(step, AsyncWorkflowStep):
-            raise BoltError(f"Invalid step object ({type(step)})")
-
-        self.use(AsyncWorkflowStepMiddleware(step))
-
-    # -------------------------
-    # global error handler
-
-    def error(
-        self, func: Callable[..., Awaitable[Optional[BoltResponse]]]
-    ) -> Callable[..., Awaitable[Optional[BoltResponse]]]:
-        """Updates the global error handler. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.error
-            async def custom_error_handler(error, body, logger):
-                logger.exception(f"Error: {error}")
-                logger.info(f"Request body: {body}")
-
-            # Pass a function to this method
-            app.error(custom_error_handler)
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            func: The function that is supposed to be executed
-                when getting an unhandled error in Bolt app.
-        """
-        if not is_callable_coroutine(func):
-            name = get_name_for_callable(func)
-            raise BoltError(error_listener_function_must_be_coro_func(name))
-        self._async_listener_runner.listener_error_handler = AsyncCustomListenerErrorHandler(
-            logger=self._framework_logger,
-            func=func,
-        )
-        self._async_middleware_error_handler = AsyncCustomMiddlewareErrorHandler(
-            logger=self._framework_logger,
-            func=func,
-        )
-        return func
-
-    # -------------------------
-    # events
-
-    def event(
-        self,
-        event: Union[
-            str,
-            Pattern,
-            Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]],
-        ],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new event listener. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.event("team_join")
-            async def ask_for_introduction(event, say):
-                welcome_channel_id = "C12345"
-                user_id = event["user"]
-                text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-                await say(text=text, channel=welcome_channel_id)
-
-            # Pass a function to this method
-            app.event("team_join")(ask_for_introduction)
-
-        Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            event: The conditions that match a request payload.
-                If you pass a dict for this, you can have type, subtype in the constraint.
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.event(event, True, base_logger=self._base_logger)
-            if self._attaching_conversation_kwargs_enabled:
-                middleware.insert(0, AsyncAttachingConversationKwargs(self._assistant_thread_context_store))
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-        return __call__
-
-    def message(
-        self,
-        keyword: Union[str, Pattern] = "",
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new message event listener. This method can be used as either a decorator or a method.
-        Check the `App#event` method's docstring for details.
-
-            # Use this method as a decorator
-            @app.message(":wave:")
-            async def say_hello(message, say):
-                user = message['user']
-                await say(f"Hi there, <@{user}>!")
-
-            # Pass a function to this method
-            app.message(":wave:")(say_hello)
-
-        Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            keyword: The keyword to match
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-        matchers = list(matchers) if matchers else []
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            constraints = {
-                "type": "message",
-                "subtype": (
-                    # In most cases, new message events come with no subtype.
-                    None,
-                    # As of Jan 2021, most bot messages no longer have the subtype bot_message.
-                    # By contrast, messages posted using classic app's bot token still have the subtype.
-                    "bot_message",
-                    # If an end-user posts a message with "Also send to #channel" checked,
-                    # the message event comes with this subtype.
-                    "thread_broadcast",
-                    # If an end-user posts a message with attached files,
-                    # the message event comes with this subtype.
-                    "file_share",
-                ),
-            }
-            primary_matcher = builtin_matchers.message_event(
-                constraints=constraints,
-                keyword=keyword,
-                asyncio=True,
-                base_logger=self._base_logger,
-            )
-            if self._attaching_conversation_kwargs_enabled:
-                middleware.insert(0, AsyncAttachingConversationKwargs(self._assistant_thread_context_store))
-            middleware.insert(0, AsyncMessageListenerMatches(keyword))
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-        return __call__
-
-    def function(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-        auto_acknowledge: bool = True,
-        ack_timeout: int = 3,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[BoltResponse]]]]:
-        """Registers a new Function listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.function("reverse")
-            async def reverse_string(ack: AsyncAck, inputs: dict, complete: AsyncComplete, fail: AsyncFail):
-                try:
-                    await ack()
-                    string_to_reverse = inputs["stringToReverse"]
-                    await complete({"reverseString": string_to_reverse[::-1]})
-                except Exception as e:
-                    await fail(f"Cannot reverse string (error: {e})")
-                    raise e
-
-            # Pass a function to this method
-            app.function("reverse")(reverse_string)
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            callback_id: The callback id to identify the function
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-        if auto_acknowledge is True:
-            if ack_timeout != 3:
-                self._framework_logger.warning(warning_ack_timeout_has_no_effect(callback_id, ack_timeout))
-
-        matchers = list(matchers) if matchers else []
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.function_executed(
-                callback_id=callback_id, base_logger=self._base_logger, asyncio=True
-            )
-            return self._register_listener(functions, primary_matcher, matchers, middleware, auto_acknowledge, ack_timeout)
-
-        return __call__
-
-    # -------------------------
-    # slash commands
-
-    def command(
-        self,
-        command: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new slash command listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.command("/echo")
-            async def repeat_text(ack, say, command):
-                # Acknowledge command request
-                await ack()
-                await say(f"{command['text']}")
-
-            # Pass a function to this method
-            app.command("/echo")(repeat_text)
-
-        Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            command: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.command(command, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # shortcut
-
-    def shortcut(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new shortcut listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.shortcut("open_modal")
-            async def open_modal(ack, body, client):
-                # Acknowledge the command request
-                await ack()
-                # Call views_open with the built-in client
-                await client.views_open(
-                    # Pass a valid trigger_id within 3 seconds of receiving it
-                    trigger_id=body["trigger_id"],
-                    # View payload
-                    view={ ... }
-                )
-
-            # Pass a function to this method
-            app.shortcut("open_modal")(open_modal)
-
-        Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload.
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.shortcut(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def global_shortcut(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new global shortcut listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.global_shortcut(callback_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def message_shortcut(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new message shortcut listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.message_shortcut(callback_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # action
-
-    def action(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new action listener. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.action("approve_button")
-            async def update_message(ack):
-                await ack()
-
-            # Pass a function to this method
-            app.action("approve_button")(update_message)
-
-        * Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`.
-        * Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`.
-        * Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.action(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def block_action(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `block_actions` action listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.block_action(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def attachment_action(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `interactive_message` action listener.
-        Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.attachment_action(callback_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_submission(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `dialog_submission` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_submission(callback_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_cancellation(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `dialog_submission` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_cancellation(callback_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # view
-
-    def view(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `view_submission`/`view_closed` event listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.view("view_1")
-            async def handle_submission(ack, body, client, view):
-                # Assume there's an input block with `block_c` as the block_id and `dreamy_input`
-                hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-                user = body["user"]["id"]
-                # Validate the inputs
-                errors = {}
-                if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-                    errors["block_c"] = "The value must be longer than 5 characters"
-                if len(errors) > 0:
-                    await ack(response_action="errors", errors=errors)
-                    return
-                # Acknowledge the view_submission event and close the modal
-                await ack()
-                # Do whatever you want with the input data - here we're saving it to a DB
-
-            # Pass a function to this method
-            app.view("view_1")(handle_submission)
-
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def view_submission(
-        self,
-        constraints: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `view_submission` listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for
-        details.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view_submission(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def view_closed(
-        self,
-        constraints: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `view_closed` listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view_closed(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # options
-
-    def options(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new options listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.options("menu_selection")
-            async def show_menu_options(ack):
-                options = [
-                    {
-                        "text": {"type": "plain_text", "text": "Option 1"},
-                        "value": "1-1",
-                    },
-                    {
-                        "text": {"type": "plain_text", "text": "Option 2"},
-                        "value": "1-2",
-                    },
-                ]
-                await ack(options=options)
-
-            # Pass a function to this method
-            app.options("menu_selection")(show_menu_options)
-
-        Refer to the following documents for details:
-
-        * https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select
-        * https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-        Args:
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.options(constraints, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def block_suggestion(
-        self,
-        action_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `block_suggestion` listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.block_suggestion(action_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_suggestion(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        """Registers a new `dialog_suggestion` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_suggestion(callback_id, asyncio=True, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # built-in listener functions
-
-    def default_tokens_revoked_event_listener(
-        self,
-    ) -> Callable[..., Awaitable[Optional[BoltResponse]]]:
-        if self._async_tokens_revocation_listeners is None:
-            raise BoltError(error_installation_store_required_for_builtin_listeners())
-        return self._async_tokens_revocation_listeners.handle_tokens_revoked_events
-
-    def default_app_uninstalled_event_listener(
-        self,
-    ) -> Callable[..., Awaitable[Optional[BoltResponse]]]:
-        if self._async_tokens_revocation_listeners is None:
-            raise BoltError(error_installation_store_required_for_builtin_listeners())
-        return self._async_tokens_revocation_listeners.handle_app_uninstalled_events
-
-    def enable_token_revocation_listeners(self) -> None:
-        self.event("tokens_revoked")(self.default_tokens_revoked_event_listener())
-        self.event("app_uninstalled")(self.default_app_uninstalled_event_listener())
-
-    # -------------------------
-
-    def _init_context(self, req: AsyncBoltRequest):
-        req.context["logger"] = get_bolt_app_logger(app_name=self.name, base_logger=self._base_logger)
-        req.context["token"] = self._token
-        # Prior to version 1.15, when the token is static, self._client was passed to `req.context`.
-        # The intention was to avoid creating a new instance per request
-        # in the interest of runtime performance/memory footprint optimization.
-        # However, developers may want to replace the token held by req.context.client in some situations.
-        # In this case, this behavior can result in thread-unsafe data modification on `self._client`.
-        # (`self._client` a.k.a. `app.client` is a singleton object per an App instance)
-        # Thus, we've changed the behavior to create a new instance per request regardless of token argument
-        # in the App initialization starting v1.15.
-        # The overhead brought by this change is slight so that we believe that it is ignorable in any cases.
-        client_per_request: AsyncWebClient = AsyncWebClient(
-            token=self._token,  # this can be None, and it can be set later on
-            base_url=self._async_client.base_url,
-            timeout=self._async_client.timeout,
-            ssl=self._async_client.ssl,
-            proxy=self._async_client.proxy,
-            session=self._async_client.session,
-            trust_env_in_session=self._async_client.trust_env_in_session,
-            headers=self._async_client.headers,
-            team_id=req.context.team_id,
-            logger=self._async_client.logger,
-            retry_handlers=(
-                self._async_client.retry_handlers.copy() if self._async_client.retry_handlers is not None else None
-            ),
-        )
-        req.context["client"] = client_per_request
-
-        # Most apps do not need this "listener_runner" instance.
-        # It is intended for apps that start lazy listeners from their custom global middleware.
-        req.context["listener_runner"] = self.listener_runner
-
-    @staticmethod
-    def _to_listener_functions(
-        kwargs: dict,
-    ) -> Optional[Sequence[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-        if kwargs:
-            functions = [kwargs["ack"]]
-            for sub in kwargs["lazy"]:
-                functions.append(sub)
-            return functions
-        return None
-
-    def _register_listener(
-        self,
-        functions: Sequence[Callable[..., Awaitable[Optional[BoltResponse]]]],
-        primary_matcher: AsyncListenerMatcher,
-        matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]],
-        middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]],
-        auto_acknowledgement: bool = False,
-        ack_timeout: int = 3,
-    ) -> Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]:
-        value_to_return = None
-        if not isinstance(functions, list):
-            functions = list(functions)
-        if len(functions) == 1:
-            # In the case where the function is registered using decorator,
-            # the registration should return the original function.
-            value_to_return = functions[0]
-
-        for func in functions:
-            if not is_callable_coroutine(func):
-                name = get_name_for_callable(func)
-                raise BoltError(error_listener_function_must_be_coro_func(name))
-
-        listener_matchers: List[AsyncListenerMatcher] = [
-            AsyncCustomListenerMatcher(app_name=self.name, func=f, base_logger=self._base_logger) for f in (matchers or [])
-        ]
-        listener_matchers.insert(0, primary_matcher)
-        listener_middleware = []
-        for m in middleware or []:
-            if isinstance(m, AsyncMiddleware):
-                listener_middleware.append(m)
-            elif callable(m) and is_callable_coroutine(m):
-                listener_middleware.append(AsyncCustomMiddleware(app_name=self.name, func=m, base_logger=self._base_logger))
-            else:
-                raise ValueError(error_unexpected_listener_middleware(type(m)))
-
-        self._async_listeners.append(
-            AsyncCustomListener(
-                app_name=self.name,
-                ack_function=functions.pop(0),
-                lazy_functions=functions,  # type: ignore[arg-type]
-                matchers=listener_matchers,
-                middleware=listener_middleware,
-                auto_acknowledgement=auto_acknowledgement,
-                ack_timeout=ack_timeout,
-                base_logger=self._base_logger,
-            )
-        )
-
-        return value_to_return
-
-

Bolt App that provides functionalities to register middleware/listeners.

-
import os
-from slack_bolt.async_app import AsyncApp
-
-# Initializes your app with your bot token and signing secret
-app = AsyncApp(
-    token=os.environ.get("SLACK_BOT_TOKEN"),
-    signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
-)
-
-# Listens to incoming messages that contain "hello"
-@app.message("hello")
-async def message_hello(message, say):  # async function
-    # say() sends a message to the channel where the event was triggered
-    await say(f"Hey there <@{message['user']}>!")
-
-# Start your app
-if __name__ == "__main__":
-    app.start(port=int(os.environ.get("PORT", 3000)))
-
-

Refer to https://docs.slack.dev/tools/bolt-python/concepts/async for details.

-

If you would like to build an OAuth app for enabling the app to run with multiple workspaces, -refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app.

-

Args

-
-
logger
-
The custom logger that can be used in this app.
-
name
-
The application name that will be used in logging. If absent, the source file name will be used.
-
process_before_response
-
True if this app runs on Function as a Service. (Default: False)
-
raise_error_for_unhandled_request
-
True if you want to raise exceptions for unhandled requests -and use @app.error listeners instead of -the built-in handler, which pints warning logs and returns 404 to Slack (Default: False)
-
signing_secret
-
The Signing Secret value used for verifying requests from Slack.
-
token
-
The bot/user access token required only for single-workspace app.
-
client
-
The singleton slack_sdk.web.async_client.AsyncWebClient instance for this app.
-
before_authorize
-
A global middleware that can be executed right before authorize function
-
authorize
-
The function to authorize an incoming request from Slack -by checking if there is a team/user in the installation data.
-
user_facing_authorize_error_message
-
The user-facing error message to display -when the app is installed but the installation is not managed by this app's installation store
-
installation_store
-
The module offering save/find operations of installation data
-
installation_store_bot_only
-
Use AsyncInstallationStore#async_find_bot() if True (Default: False)
-
request_verification_enabled
-
False if you would like to disable the built-in middleware (Default: True). -AsyncRequestVerification is a built-in middleware that verifies the signature in HTTP Mode requests. -Make sure if it's safe enough when you turn a built-in middleware off. -We strongly recommend using RequestVerification for better security. -If you have a proxy that verifies request signature in front of the Bolt app, -it's totally fine to disable RequestVerification to avoid duplication of work. -Don't turn it off just for easiness of development.
-
ignoring_self_events_enabled
-
False if you would like to disable the built-in middleware (Default: True). -AsyncIgnoringSelfEvents is a built-in middleware that enables Bolt apps to easily skip the events -generated by this app's bot user (this is useful for avoiding code error causing an infinite loop).
-
ignoring_self_assistant_message_events_enabled
-
False if you would like to disable the built-in middleware. -IgnoringSelfEvents for this app's bot user message events within an assistant thread -This is useful for avoiding code error causing an infinite loop; Default: True
-
url_verification_enabled
-
False if you would like to disable the built-in middleware (Default: True). -AsyncUrlVerification is a built-in middleware that handles url_verification requests -that verify the endpoint for Events API in HTTP Mode requests.
-
ssl_check_enabled
-
bool = False if you would like to disable the built-in middleware (Default: True). -AsyncSslCheck is a built-in middleware that handles ssl_check requests from Slack.
-
attaching_function_token_enabled
-
False if you would like to disable the built-in middleware (Default: True). -AsyncAttachingFunctionToken is a built-in middleware that injects the just-in-time workflow-execution token -when your app receives function_executed or interactivity events scoped to a custom step.
-
oauth_settings
-
The settings related to Slack app installation flow (OAuth flow)
-
oauth_flow
-
Instantiated slack_bolt.oauth.AsyncOAuthFlow. This is always prioritized over oauth_settings.
-
verification_token
-
Deprecated verification mechanism. This can be used only for ssl_check requests.
-
assistant_thread_context_store
-
Custom AssistantThreadContext store (Default: the built-in implementation, -which uses a parent message's metadata to store the latest context)
-
-

Class variables

-
-
var AsyncSlackAppServer
-
-

The type of the None singleton.

-
-
-

Instance variables

-
-
prop client : slack_sdk.web.async_client.AsyncWebClient
-
-
- -Expand source code - -
@property
-def client(self) -> AsyncWebClient:
-    """The singleton `slack_sdk.web.async_client.AsyncWebClient` instance in this app."""
-    return self._async_client
-
-

The singleton slack_sdk.web.async_client.AsyncWebClient instance in this app.

-
-
prop installation_store : slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore | None
-
-
- -Expand source code - -
@property
-def installation_store(self) -> Optional[AsyncInstallationStore]:
-    """The `slack_sdk.oauth.AsyncInstallationStore` that can be used in the `authorize` middleware."""
-    return self._async_installation_store
-
-

The slack_sdk.oauth.AsyncInstallationStore that can be used in the authorize middleware.

-
-
prop listener_runnerAsyncioListenerRunner
-
-
- -Expand source code - -
@property
-def listener_runner(self) -> AsyncioListenerRunner:
-    """The asyncio-based executor for asynchronously running listeners."""
-    return self._async_listener_runner
-
-

The asyncio-based executor for asynchronously running listeners.

-
-
prop logger : logging.Logger
-
-
- -Expand source code - -
@property
-def logger(self) -> logging.Logger:
-    """The logger this app uses."""
-    return self._framework_logger
-
-

The logger this app uses.

-
-
prop name : str
-
-
- -Expand source code - -
@property
-def name(self) -> str:
-    """The name of this app (default: the filename)"""
-    return self._name
-
-

The name of this app (default: the filename)

-
-
prop oauth_flowAsyncOAuthFlow | None
-
-
- -Expand source code - -
@property
-def oauth_flow(self) -> Optional[AsyncOAuthFlow]:
-    """Configured `OAuthFlow` object if exists."""
-    return self._async_oauth_flow
-
-

Configured OAuthFlow object if exists.

-
-
prop process_before_response : bool
-
-
- -Expand source code - -
@property
-def process_before_response(self) -> bool:
-    return self._process_before_response or False
-
-
-
-
-

Methods

-
-
-def action(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def action(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new action listener. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.action("approve_button")
-        async def update_message(ack):
-            await ack()
-
-        # Pass a function to this method
-        app.action("approve_button")(update_message)
-
-    * Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`.
-    * Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`.
-    * Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.action(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new action listener. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.action("approve_button")
-async def update_message(ack):
-    await ack()
-
-# Pass a function to this method
-app.action("approve_button")(update_message)
-
- -

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def assistant(self,
assistant: AsyncAssistant) ‑> Callable | None
-
-
-
- -Expand source code - -
def assistant(self, assistant: AsyncAssistant) -> Optional[Callable]:
-    return self.middleware(assistant)
-
-
-
-
-async def async_dispatch(self,
req: AsyncBoltRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
async def async_dispatch(self, req: AsyncBoltRequest) -> BoltResponse:
-    """Applies all middleware and dispatches an incoming request from Slack to the right code path.
-
-    Args:
-        req: An incoming request from Slack.
-
-    Returns:
-        The response generated by this Bolt app.
-    """
-    starting_time = time.time()
-    self._init_context(req)
-
-    resp: Optional[BoltResponse] = BoltResponse(status=200, body="")
-    middleware_state = {"next_called": False}
-
-    async def async_middleware_next():
-        middleware_state["next_called"] = True
-
-    try:
-        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  # type: ignore[arg-type]
-            )
-            if not middleware_state["next_called"]:
-                if resp is None:
-                    # next() method was not called without providing the response to return to Slack
-                    # This should not be an intentional handling in usual use cases.
-                    resp = BoltResponse(status=404, body={"error": "no next() calls in middleware"})
-                    if self._raise_error_for_unhandled_request is True:
-                        try:
-                            raise BoltUnhandledRequestError(
-                                request=req,
-                                current_response=resp,
-                                last_global_middleware_name=middleware.name,
-                            )
-                        except BoltUnhandledRequestError as e:
-                            await self._async_listener_runner.listener_error_handler.handle(
-                                error=e,
-                                request=req,
-                                response=resp,
-                            )
-                        return resp
-                    self._framework_logger.warning(warning_unhandled_by_global_middleware(middleware.name, req))
-                    return resp
-                return resp
-
-        for listener in self._async_listeners:
-            listener_name = get_name_for_callable(listener.ack_function)
-            self._framework_logger.debug(debug_checking_listener(listener_name))
-            if await listener.async_matches(req=req, resp=resp):  # type: ignore[arg-type]
-                # run all the middleware attached to this listener first
-                middleware_resp, next_was_not_called = await listener.run_async_middleware(
-                    req=req, resp=resp  # type: ignore[arg-type]
-                )
-                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] = await self._async_listener_runner.run(
-                    request=req,
-                    response=resp,  # type: ignore[arg-type]
-                    listener_name=listener_name,
-                    listener=listener,
-                )
-                if listener_response is not None:
-                    return listener_response
-
-        if resp is None:
-            resp = BoltResponse(status=404, body={"error": "unhandled request"})
-        if self._raise_error_for_unhandled_request is True:
-            try:
-                raise BoltUnhandledRequestError(
-                    request=req,
-                    current_response=resp,
-                )
-            except BoltUnhandledRequestError as e:
-                await self._async_listener_runner.listener_error_handler.handle(
-                    error=e,
-                    request=req,
-                    response=resp,
-                )
-            return resp
-        return self._handle_unmatched_requests(req, resp)
-
-    except Exception as error:
-        resp = BoltResponse(status=500, body="")
-        await self._async_middleware_error_handler.handle(
-            error=error,
-            request=req,
-            response=resp,
-        )
-        return resp
-
-

Applies all middleware and dispatches an incoming request from Slack to the right code path.

-

Args

-
-
req
-
An incoming request from Slack.
-
-

Returns

-

The response generated by this Bolt app.

-
-
-def attachment_action(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def attachment_action(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `interactive_message` action listener.
-    Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.attachment_action(callback_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new interactive_message action listener. -Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details.

-
-
-def block_action(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def block_action(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `block_actions` action listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.block_action(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new block_actions action listener. -Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.

-
-
-def block_suggestion(self,
action_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def block_suggestion(
-    self,
-    action_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `block_suggestion` listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.block_suggestion(action_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new block_suggestion listener.

-
-
-def command(self,
command: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def command(
-    self,
-    command: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new slash command listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.command("/echo")
-        async def repeat_text(ack, say, command):
-            # Acknowledge command request
-            await ack()
-            await say(f"{command['text']}")
-
-        # Pass a function to this method
-        app.command("/echo")(repeat_text)
-
-    Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        command: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.command(command, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new slash command listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.command("/echo")
-async def repeat_text(ack, say, command):
-    # Acknowledge command request
-    await ack()
-    await say(f"{command['text']}")
-
-# Pass a function to this method
-app.command("/echo")(repeat_text)
-
-

Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
command
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def default_app_uninstalled_event_listener(self) ‑> Callable[..., Awaitable[BoltResponse | None]] -
-
-
- -Expand source code - -
def default_app_uninstalled_event_listener(
-    self,
-) -> Callable[..., Awaitable[Optional[BoltResponse]]]:
-    if self._async_tokens_revocation_listeners is None:
-        raise BoltError(error_installation_store_required_for_builtin_listeners())
-    return self._async_tokens_revocation_listeners.handle_app_uninstalled_events
-
-
-
-
-def default_tokens_revoked_event_listener(self) ‑> Callable[..., Awaitable[BoltResponse | None]] -
-
-
- -Expand source code - -
def default_tokens_revoked_event_listener(
-    self,
-) -> Callable[..., Awaitable[Optional[BoltResponse]]]:
-    if self._async_tokens_revocation_listeners is None:
-        raise BoltError(error_installation_store_required_for_builtin_listeners())
-    return self._async_tokens_revocation_listeners.handle_tokens_revoked_events
-
-
-
-
-def dialog_cancellation(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def dialog_cancellation(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `dialog_submission` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_cancellation(callback_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_submission listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dialog_submission(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def dialog_submission(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `dialog_submission` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_submission(callback_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_submission listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dialog_suggestion(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def dialog_suggestion(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `dialog_suggestion` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_suggestion(callback_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_suggestion listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def enable_token_revocation_listeners(self) ‑> None -
-
-
- -Expand source code - -
def enable_token_revocation_listeners(self) -> None:
-    self.event("tokens_revoked")(self.default_tokens_revoked_event_listener())
-    self.event("app_uninstalled")(self.default_app_uninstalled_event_listener())
-
-
-
-
-def error(self,
func: Callable[..., Awaitable[BoltResponse | None]]) ‑> Callable[..., Awaitable[BoltResponse | None]]
-
-
-
- -Expand source code - -
def error(
-    self, func: Callable[..., Awaitable[Optional[BoltResponse]]]
-) -> Callable[..., Awaitable[Optional[BoltResponse]]]:
-    """Updates the global error handler. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.error
-        async def custom_error_handler(error, body, logger):
-            logger.exception(f"Error: {error}")
-            logger.info(f"Request body: {body}")
-
-        # Pass a function to this method
-        app.error(custom_error_handler)
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        func: The function that is supposed to be executed
-            when getting an unhandled error in Bolt app.
-    """
-    if not is_callable_coroutine(func):
-        name = get_name_for_callable(func)
-        raise BoltError(error_listener_function_must_be_coro_func(name))
-    self._async_listener_runner.listener_error_handler = AsyncCustomListenerErrorHandler(
-        logger=self._framework_logger,
-        func=func,
-    )
-    self._async_middleware_error_handler = AsyncCustomMiddlewareErrorHandler(
-        logger=self._framework_logger,
-        func=func,
-    )
-    return func
-
-

Updates the global error handler. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.error
-async def custom_error_handler(error, body, logger):
-    logger.exception(f"Error: {error}")
-    logger.info(f"Request body: {body}")
-
-# Pass a function to this method
-app.error(custom_error_handler)
-
-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
func
-
The function that is supposed to be executed -when getting an unhandled error in Bolt app.
-
-
-
-def event(self,
event: str | Pattern | Dict[str, str | Sequence[str | Pattern | None] | None],
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def event(
-    self,
-    event: Union[
-        str,
-        Pattern,
-        Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]],
-    ],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new event listener. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.event("team_join")
-        async def ask_for_introduction(event, say):
-            welcome_channel_id = "C12345"
-            user_id = event["user"]
-            text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-            await say(text=text, channel=welcome_channel_id)
-
-        # Pass a function to this method
-        app.event("team_join")(ask_for_introduction)
-
-    Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        event: The conditions that match a request payload.
-            If you pass a dict for this, you can have type, subtype in the constraint.
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.event(event, True, base_logger=self._base_logger)
-        if self._attaching_conversation_kwargs_enabled:
-            middleware.insert(0, AsyncAttachingConversationKwargs(self._assistant_thread_context_store))
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-    return __call__
-
-

Registers a new event listener. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.event("team_join")
-async def ask_for_introduction(event, say):
-    welcome_channel_id = "C12345"
-    user_id = event["user"]
-    text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-    await say(text=text, channel=welcome_channel_id)
-
-# Pass a function to this method
-app.event("team_join")(ask_for_introduction)
-
-

Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
event
-
The conditions that match a request payload. -If you pass a dict for this, you can have type, subtype in the constraint.
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def function(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None,
auto_acknowledge: bool = True,
ack_timeout: int = 3) ‑> Callable[..., Callable[..., Awaitable[BoltResponse]] | None]
-
-
-
- -Expand source code - -
def function(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-    auto_acknowledge: bool = True,
-    ack_timeout: int = 3,
-) -> Callable[..., Optional[Callable[..., Awaitable[BoltResponse]]]]:
-    """Registers a new Function listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.function("reverse")
-        async def reverse_string(ack: AsyncAck, inputs: dict, complete: AsyncComplete, fail: AsyncFail):
-            try:
-                await ack()
-                string_to_reverse = inputs["stringToReverse"]
-                await complete({"reverseString": string_to_reverse[::-1]})
-            except Exception as e:
-                await fail(f"Cannot reverse string (error: {e})")
-                raise e
-
-        # Pass a function to this method
-        app.function("reverse")(reverse_string)
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        callback_id: The callback id to identify the function
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-    if auto_acknowledge is True:
-        if ack_timeout != 3:
-            self._framework_logger.warning(warning_ack_timeout_has_no_effect(callback_id, ack_timeout))
-
-    matchers = list(matchers) if matchers else []
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.function_executed(
-            callback_id=callback_id, base_logger=self._base_logger, asyncio=True
-        )
-        return self._register_listener(functions, primary_matcher, matchers, middleware, auto_acknowledge, ack_timeout)
-
-    return __call__
-
-

Registers a new Function listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.function("reverse")
-async def reverse_string(ack: AsyncAck, inputs: dict, complete: AsyncComplete, fail: AsyncFail):
-    try:
-        await ack()
-        string_to_reverse = inputs["stringToReverse"]
-        await complete({"reverseString": string_to_reverse[::-1]})
-    except Exception as e:
-        await fail(f"Cannot reverse string (error: {e})")
-        raise e
-
-# Pass a function to this method
-app.function("reverse")(reverse_string)
-
-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
callback_id
-
The callback id to identify the function
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def global_shortcut(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def global_shortcut(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new global shortcut listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.global_shortcut(callback_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new global shortcut listener.

-
-
-def message(self,
keyword: str | Pattern = '',
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def message(
-    self,
-    keyword: Union[str, Pattern] = "",
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new message event listener. This method can be used as either a decorator or a method.
-    Check the `App#event` method's docstring for details.
-
-        # Use this method as a decorator
-        @app.message(":wave:")
-        async def say_hello(message, say):
-            user = message['user']
-            await say(f"Hi there, <@{user}>!")
-
-        # Pass a function to this method
-        app.message(":wave:")(say_hello)
-
-    Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        keyword: The keyword to match
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-    matchers = list(matchers) if matchers else []
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        constraints = {
-            "type": "message",
-            "subtype": (
-                # In most cases, new message events come with no subtype.
-                None,
-                # As of Jan 2021, most bot messages no longer have the subtype bot_message.
-                # By contrast, messages posted using classic app's bot token still have the subtype.
-                "bot_message",
-                # If an end-user posts a message with "Also send to #channel" checked,
-                # the message event comes with this subtype.
-                "thread_broadcast",
-                # If an end-user posts a message with attached files,
-                # the message event comes with this subtype.
-                "file_share",
-            ),
-        }
-        primary_matcher = builtin_matchers.message_event(
-            constraints=constraints,
-            keyword=keyword,
-            asyncio=True,
-            base_logger=self._base_logger,
-        )
-        if self._attaching_conversation_kwargs_enabled:
-            middleware.insert(0, AsyncAttachingConversationKwargs(self._assistant_thread_context_store))
-        middleware.insert(0, AsyncMessageListenerMatches(keyword))
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-    return __call__
-
-

Registers a new message event listener. This method can be used as either a decorator or a method. -Check the App#event method's docstring for details.

-
# Use this method as a decorator
-@app.message(":wave:")
-async def say_hello(message, say):
-    user = message['user']
-    await say(f"Hi there, <@{user}>!")
-
-# Pass a function to this method
-app.message(":wave:")(say_hello)
-
-

Refer to https://docs.slack.dev/reference/events/message/ for details of message events.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
keyword
-
The keyword to match
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def message_shortcut(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def message_shortcut(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new message shortcut listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.message_shortcut(callback_id, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new message shortcut listener.

-
-
-def middleware(self, *args) ‑> Callable | None -
-
-
- -Expand source code - -
def middleware(self, *args) -> Optional[Callable]:
-    """Registers a new middleware to this app.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.middleware
-        async def middleware_func(logger, body, next):
-            logger.info(f"request body: {body}")
-            await next()
-
-        # Pass a function to this method
-        app.middleware(middleware_func)
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        *args: A function that works as a global middleware.
-    """
-    if len(args) > 0:
-        middleware_or_callable = args[0]
-        if isinstance(middleware_or_callable, AsyncMiddleware):
-            middleware: AsyncMiddleware = middleware_or_callable
-            self._async_middleware_list.append(middleware)
-            if isinstance(middleware, AsyncAssistant) and middleware.thread_context_store is not None:
-                self._assistant_thread_context_store = middleware.thread_context_store
-        elif callable(middleware_or_callable):
-            self._async_middleware_list.append(
-                AsyncCustomMiddleware(
-                    app_name=self.name,
-                    func=middleware_or_callable,
-                    base_logger=self._base_logger,
-                )
-            )
-            return middleware_or_callable
-        else:
-            raise BoltError(f"Unexpected type for a middleware ({type(middleware_or_callable)})")
-    return None
-
-

Registers a new middleware to this app. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.middleware
-async def middleware_func(logger, body, next):
-    logger.info(f"request body: {body}")
-    await next()
-
-# Pass a function to this method
-app.middleware(middleware_func)
-
-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
*args
-
A function that works as a global middleware.
-
-
-
-def options(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def options(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new options listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.options("menu_selection")
-        async def show_menu_options(ack):
-            options = [
-                {
-                    "text": {"type": "plain_text", "text": "Option 1"},
-                    "value": "1-1",
-                },
-                {
-                    "text": {"type": "plain_text", "text": "Option 2"},
-                    "value": "1-2",
-                },
-            ]
-            await ack(options=options)
-
-        # Pass a function to this method
-        app.options("menu_selection")(show_menu_options)
-
-    Refer to the following documents for details:
-
-    * https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select
-    * https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.options(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new options listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.options("menu_selection")
-async def show_menu_options(ack):
-    options = [
-        {
-            "text": {"type": "plain_text", "text": "Option 1"},
-            "value": "1-1",
-        },
-        {
-            "text": {"type": "plain_text", "text": "Option 2"},
-            "value": "1-2",
-        },
-    ]
-    await ack(options=options)
-
-# Pass a function to this method
-app.options("menu_selection")(show_menu_options)
-
-

Refer to the following documents for details:

- -

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def server(self, port: int = 3000, path: str = '/slack/events', host: str | None = None) ‑> AsyncSlackAppServer -
-
-
- -Expand source code - -
def server(
-    self,
-    port: int = 3000,
-    path: str = "/slack/events",
-    host: Optional[str] = None,
-) -> AsyncSlackAppServer:
-    """Configure a web server using AIOHTTP.
-    Refer to https://docs.aiohttp.org/ for more details about AIOHTTP.
-
-    Args:
-        port: The port to listen on (Default: 3000)
-        path: The path to handle request from Slack (Default: `/slack/events`)
-        host: The hostname to serve the web endpoints. (Default: 0.0.0.0)
-    """
-    if self._server is None or self._server.port != port or self._server.path != path:
-        self._server = AsyncSlackAppServer(
-            port=port,
-            path=path,
-            app=self,
-            host=host,
-        )
-    return self._server
-
-

Configure a web server using AIOHTTP. -Refer to https://docs.aiohttp.org/ for more details about AIOHTTP.

-

Args

-
-
port
-
The port to listen on (Default: 3000)
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
host
-
The hostname to serve the web endpoints. (Default: 0.0.0.0)
-
-
-
-def shortcut(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def shortcut(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new shortcut listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.shortcut("open_modal")
-        async def open_modal(ack, body, client):
-            # Acknowledge the command request
-            await ack()
-            # Call views_open with the built-in client
-            await client.views_open(
-                # Pass a valid trigger_id within 3 seconds of receiving it
-                trigger_id=body["trigger_id"],
-                # View payload
-                view={ ... }
-            )
-
-        # Pass a function to this method
-        app.shortcut("open_modal")(open_modal)
-
-    Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload.
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.shortcut(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new shortcut listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.shortcut("open_modal")
-async def open_modal(ack, body, client):
-    # Acknowledge the command request
-    await ack()
-    # Call views_open with the built-in client
-    await client.views_open(
-        # Pass a valid trigger_id within 3 seconds of receiving it
-        trigger_id=body["trigger_id"],
-        # View payload
-        view={ ... }
-    )
-
-# Pass a function to this method
-app.shortcut("open_modal")(open_modal)
-
-

Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload.
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def start(self, port: int = 3000, path: str = '/slack/events', host: str | None = None) ‑> None -
-
-
- -Expand source code - -
def start(self, port: int = 3000, path: str = "/slack/events", host: Optional[str] = None) -> None:
-    """Start a web server using AIOHTTP.
-    Refer to https://docs.aiohttp.org/ for more details about AIOHTTP.
-
-    Args:
-        port: The port to listen on (Default: 3000)
-        path: The path to handle request from Slack (Default: `/slack/events`)
-        host: The hostname to serve the web endpoints. (Default: 0.0.0.0)
-    """
-    self.server(port=port, path=path, host=host).start()
-
-

Start a web server using AIOHTTP. -Refer to https://docs.aiohttp.org/ for more details about AIOHTTP.

-

Args

-
-
port
-
The port to listen on (Default: 3000)
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
host
-
The hostname to serve the web endpoints. (Default: 0.0.0.0)
-
-
-
-def step(self,
callback_id: str | Pattern | AsyncWorkflowStep | AsyncWorkflowStepBuilder,
edit: Callable[..., BoltResponse | None] | AsyncListener | Sequence[Callable] | None = None,
save: Callable[..., BoltResponse | None] | AsyncListener | Sequence[Callable] | None = None,
execute: Callable[..., BoltResponse | None] | AsyncListener | Sequence[Callable] | None = None)
-
-
-
- -Expand source code - -
def step(
-    self,
-    callback_id: Union[str, Pattern, AsyncWorkflowStep, AsyncWorkflowStepBuilder],
-    edit: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None,
-    save: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None,
-    execute: Optional[Union[Callable[..., Optional[BoltResponse]], AsyncListener, Sequence[Callable]]] = None,
-):
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Registers a new step from app listener.
-
-    Unlike others, this method doesn't behave as a decorator.
-    If you want to register a step from app by a decorator, use `AsyncWorkflowStepBuilder`'s methods.
-
-        # Create a new WorkflowStep instance
-        from slack_bolt.workflows.async_step import AsyncWorkflowStep
-        ws = AsyncWorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        # Pass Step to set up listeners
-        app.step(ws)
-
-    Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-    For further information about AsyncWorkflowStep specific function arguments
-    such as `configure`, `update`, `complete`, and `fail`,
-    refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents.
-
-    Args:
-        callback_id: The Callback ID for this step from app
-        edit: The function for displaying a modal in the Workflow Builder
-        save: The function for handling configuration in the Workflow Builder
-        execute: The function for handling the step execution
-    """
-    warnings.warn(
-        (
-            "Steps from apps for legacy workflows are now deprecated. "
-            "Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/"
-        ),
-        category=DeprecationWarning,
-    )
-    step = callback_id
-    if isinstance(callback_id, (str, Pattern)):
-        step = AsyncWorkflowStep(
-            callback_id=callback_id,
-            edit=edit,  # type: ignore[arg-type]
-            save=save,  # type: ignore[arg-type]
-            execute=execute,  # type: ignore[arg-type]
-            base_logger=self._base_logger,
-        )
-    elif isinstance(step, AsyncWorkflowStepBuilder):
-        step = step.build(base_logger=self._base_logger)
-    elif not isinstance(step, AsyncWorkflowStep):
-        raise BoltError(f"Invalid step object ({type(step)})")
-
-    self.use(AsyncWorkflowStepMiddleware(step))
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Registers a new step from app listener.

-

Unlike others, this method doesn't behave as a decorator. -If you want to register a step from app by a decorator, use AsyncWorkflowStepBuilder's methods.

-
# Create a new WorkflowStep instance
-from slack_bolt.workflows.async_step import AsyncWorkflowStep
-ws = AsyncWorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-# Pass Step to set up listeners
-app.step(ws)
-
-

Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document. -For further information about AsyncWorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to the async prefixed ones in slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
callback_id
-
The Callback ID for this step from app
-
edit
-
The function for displaying a modal in the Workflow Builder
-
save
-
The function for handling configuration in the Workflow Builder
-
execute
-
The function for handling the step execution
-
-
-
-def use(self, *args) ‑> Callable | None -
-
-
- -Expand source code - -
def use(self, *args) -> Optional[Callable]:
-    """Refer to `AsyncApp#middleware()` method's docstring for details."""
-    return self.middleware(*args)
-
-

Refer to AsyncApp#middleware() method's docstring for details.

-
-
-def view(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def view(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `view_submission`/`view_closed` event listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.view("view_1")
-        async def handle_submission(ack, body, client, view):
-            # Assume there's an input block with `block_c` as the block_id and `dreamy_input`
-            hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-            user = body["user"]["id"]
-            # Validate the inputs
-            errors = {}
-            if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-                errors["block_c"] = "The value must be longer than 5 characters"
-            if len(errors) > 0:
-                await ack(response_action="errors", errors=errors)
-                return
-            # Acknowledge the view_submission event and close the modal
-            await ack()
-            # Do whatever you want with the input data - here we're saving it to a DB
-
-        # Pass a function to this method
-        app.view("view_1")(handle_submission)
-
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new view_submission/view_closed event listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.view("view_1")
-async def handle_submission(ack, body, client, view):
-    # Assume there's an input block with <code>block\_c</code> as the block_id and <code>dreamy\_input</code>
-    hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-    user = body["user"]["id"]
-    # Validate the inputs
-    errors = {}
-    if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-        errors["block_c"] = "The value must be longer than 5 characters"
-    if len(errors) > 0:
-        await ack(response_action="errors", errors=errors)
-        return
-    # Acknowledge the view_submission event and close the modal
-    await ack()
-    # Do whatever you want with the input data - here we're saving it to a DB
-
-# Pass a function to this method
-app.view("view_1")(handle_submission)
-
-

Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.async_args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def view_closed(self,
constraints: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def view_closed(
-    self,
-    constraints: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `view_closed` listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view_closed(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
- -
-
-def view_submission(self,
constraints: str | Pattern,
matchers: Sequence[Callable[..., Awaitable[bool]]] | None = None,
middleware: Sequence[Callable | AsyncMiddleware] | None = None) ‑> Callable[..., Callable[..., Awaitable[BoltResponse | None]] | None]
-
-
-
- -Expand source code - -
def view_submission(
-    self,
-    constraints: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., Awaitable[bool]]]] = None,
-    middleware: Optional[Sequence[Union[Callable, AsyncMiddleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]:
-    """Registers a new `view_submission` listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for
-    details.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view_submission(constraints, asyncio=True, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new view_submission listener. -Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for -details.

-
-
-def web_app(self, path: str = '/slack/events', port: int = 3000) ‑> aiohttp.web_app.Application -
-
-
- -Expand source code - -
def web_app(self, path: str = "/slack/events", port: int = 3000) -> web.Application:
-    """Returns a `web.Application` instance for aiohttp-devtools users.
-
-        from slack_bolt.async_app import AsyncApp
-        app = AsyncApp()
-
-        @app.event("app_mention")
-        async def event_test(body, say, logger):
-            logger.info(body)
-            await say("What's up?")
-
-        def app_factory():
-            return app.web_app()
-
-        # adev runserver --port 3000 --app-factory app_factory async_app.py
-
-    Args:
-        path: The path to receive incoming requests from Slack
-        port: The port to listen on (Default: 3000)
-    """
-    return self.server(path=path, port=port).web_app
-
-

Returns a web.Application instance for aiohttp-devtools users.

-
from slack_bolt.async_app import AsyncApp
-app = AsyncApp()
-
-@app.event("app_mention")
-async def event_test(body, say, logger):
-    logger.info(body)
-    await say("What's up?")
-
-def app_factory():
-    return app.web_app()
-
-# adev runserver --port 3000 --app-factory app_factory async_app.py
-
-

Args

-
-
path
-
The path to receive incoming requests from Slack
-
port
-
The port to listen on (Default: 3000)
-
-
-
-
-
-class AsyncAssistant -(*,
app_name: str = 'assistant',
thread_context_store: AsyncAssistantThreadContextStore | None = None,
logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncAssistant(AsyncMiddleware):
-    _thread_started_listeners: Optional[List[AsyncListener]]
-    _user_message_listeners: Optional[List[AsyncListener]]
-    _bot_message_listeners: Optional[List[AsyncListener]]
-    _thread_context_changed_listeners: Optional[List[AsyncListener]]
-
-    thread_context_store: Optional[AsyncAssistantThreadContextStore]
-    base_logger: Optional[logging.Logger]
-
-    def __init__(
-        self,
-        *,
-        app_name: str = "assistant",
-        thread_context_store: Optional[AsyncAssistantThreadContextStore] = None,
-        logger: Optional[logging.Logger] = None,
-    ):
-        self.app_name = app_name
-        self.thread_context_store = thread_context_store
-        self.base_logger = logger
-
-        self._thread_started_listeners = None
-        self._thread_context_changed_listeners = None
-        self._user_message_listeners = None
-        self._bot_message_listeners = None
-
-    def thread_started(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._thread_started_listeners is None:
-            self._thread_started_listeners = []
-        all_matchers = self._merge_matchers(
-            build_listener_matcher(
-                func=is_assistant_thread_started_event,
-                asyncio=True,
-                base_logger=self.base_logger,
-            ),  # type: ignore[arg-type]
-            matchers,
-        )
-        if is_used_without_argument(args):
-            func = args[0]
-            self._thread_started_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._thread_started_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def user_message(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._user_message_listeners is None:
-            self._user_message_listeners = []
-        all_matchers = self._merge_matchers(
-            build_listener_matcher(
-                func=is_user_message_event_in_assistant_thread,
-                asyncio=True,
-                base_logger=self.base_logger,
-            ),  # type: ignore[arg-type]
-            matchers,
-        )
-        if is_used_without_argument(args):
-            func = args[0]
-            self._user_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._user_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def bot_message(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._bot_message_listeners is None:
-            self._bot_message_listeners = []
-        all_matchers = self._merge_matchers(
-            build_listener_matcher(
-                func=is_bot_message_event_in_assistant_thread,
-                asyncio=True,
-                base_logger=self.base_logger,
-            ),  # type: ignore[arg-type]
-            matchers,
-        )
-        if is_used_without_argument(args):
-            func = args[0]
-            self._bot_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._bot_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def thread_context_changed(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._thread_context_changed_listeners is None:
-            self._thread_context_changed_listeners = []
-        all_matchers = self._merge_matchers(
-            build_listener_matcher(
-                func=is_assistant_thread_context_changed_event,
-                asyncio=True,
-                base_logger=self.base_logger,
-            ),  # type: ignore[arg-type]
-            matchers,
-        )
-        if is_used_without_argument(args):
-            func = args[0]
-            self._thread_context_changed_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._thread_context_changed_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    @staticmethod
-    def _merge_matchers(
-        primary_matcher: Union[Callable[..., bool], AsyncListenerMatcher],
-        custom_matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]],
-    ):
-        return [primary_matcher] + (custom_matchers or [])  # type: ignore[operator]
-
-    @staticmethod
-    async def default_thread_context_changed(save_thread_context: AsyncSaveThreadContext, payload: dict):
-        new_context: dict = payload["assistant_thread"]["context"]
-        await save_thread_context(new_context)
-
-    async def async_process(  # type: ignore[return]
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> Optional[BoltResponse]:
-        if self._thread_context_changed_listeners is None:
-            self.thread_context_changed(self.default_thread_context_changed)
-
-        listener_runner: AsyncioListenerRunner = req.context.listener_runner
-        for listeners in [
-            self._thread_started_listeners,
-            self._thread_context_changed_listeners,
-            self._user_message_listeners,
-            self._bot_message_listeners,
-        ]:
-            if listeners is not None:
-                for listener in listeners:
-                    if listener is not None and await listener.async_matches(req=req, resp=resp):
-                        middleware_resp, next_was_not_called = await listener.run_async_middleware(req=req, resp=resp)
-                        if next_was_not_called:
-                            if middleware_resp is not None:
-                                return middleware_resp
-                            # The listener middleware didn't call next().
-                            # Skip this listener and try the next one.
-                            continue
-                        if middleware_resp is not None:
-                            resp = middleware_resp
-                        return await listener_runner.run(
-                            request=req,
-                            response=resp,
-                            listener_name="assistant_listener",
-                            listener=listener,
-                        )
-        if is_other_message_sub_event_in_assistant_thread(req.body):
-            # message_changed, message_deleted, etc.
-            return await req.context.ack()
-
-        await next()
-
-    def build_listener(
-        self,
-        listener_or_functions: Union[AsyncListener, Callable, List[Callable]],
-        matchers: Optional[List[Union[AsyncListenerMatcher, Callable[..., Awaitable[bool]]]]] = None,
-        middleware: Optional[List[AsyncMiddleware]] = None,
-        base_logger: Optional[Logger] = None,
-    ) -> AsyncListener:
-        if isinstance(listener_or_functions, Callable):  # type: ignore[arg-type]
-            listener_or_functions = [listener_or_functions]  # type: ignore[list-item]
-
-        if isinstance(listener_or_functions, AsyncListener):
-            return listener_or_functions
-        elif isinstance(listener_or_functions, list):
-            middleware = middleware if middleware else []
-            middleware.insert(0, AsyncAttachingConversationKwargs(self.thread_context_store))
-            functions = listener_or_functions
-            ack_function = functions.pop(0)
-
-            matchers = matchers if matchers else []
-            listener_matchers: List[AsyncListenerMatcher] = []
-            for matcher in matchers:
-                if isinstance(matcher, AsyncListenerMatcher):
-                    listener_matchers.append(matcher)
-                else:
-                    listener_matchers.append(
-                        build_listener_matcher(
-                            func=matcher,  # type: ignore[arg-type]
-                            asyncio=True,
-                            base_logger=base_logger,
-                        )
-                    )
-            return AsyncCustomListener(
-                app_name=self.app_name,
-                matchers=listener_matchers,
-                middleware=middleware,
-                ack_function=ack_function,
-                lazy_functions=functions,
-                auto_acknowledgement=True,
-                base_logger=base_logger or self.base_logger,
-            )
-        else:
-            raise BoltError(f"Invalid listener: {type(listener_or_functions)} detected")
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var base_logger : logging.Logger | None
-
-

The type of the None singleton.

-
-
var thread_context_storeAsyncAssistantThreadContextStore | None
-
-

The type of the None singleton.

-
-
-

Static methods

-
-
-async def default_thread_context_changed(save_thread_context: AsyncSaveThreadContext,
payload: dict)
-
-
-
- -Expand source code - -
@staticmethod
-async def default_thread_context_changed(save_thread_context: AsyncSaveThreadContext, payload: dict):
-    new_context: dict = payload["assistant_thread"]["context"]
-    await save_thread_context(new_context)
-
-
-
-
-

Methods

-
-
-def bot_message(self,
*args,
matchers: Callable[..., bool] | AsyncListenerMatcher | None = None,
middleware: Callable | AsyncMiddleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def bot_message(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._bot_message_listeners is None:
-        self._bot_message_listeners = []
-    all_matchers = self._merge_matchers(
-        build_listener_matcher(
-            func=is_bot_message_event_in_assistant_thread,
-            asyncio=True,
-            base_logger=self.base_logger,
-        ),  # type: ignore[arg-type]
-        matchers,
-    )
-    if is_used_without_argument(args):
-        func = args[0]
-        self._bot_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._bot_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def build_listener(self,
listener_or_functions: AsyncListener | Callable | List[Callable],
matchers: List[AsyncListenerMatcher | Callable[..., Awaitable[bool]]] | None = None,
middleware: List[AsyncMiddleware] | None = None,
base_logger: logging.Logger | None = None) ‑> AsyncListener
-
-
-
- -Expand source code - -
def build_listener(
-    self,
-    listener_or_functions: Union[AsyncListener, Callable, List[Callable]],
-    matchers: Optional[List[Union[AsyncListenerMatcher, Callable[..., Awaitable[bool]]]]] = None,
-    middleware: Optional[List[AsyncMiddleware]] = None,
-    base_logger: Optional[Logger] = None,
-) -> AsyncListener:
-    if isinstance(listener_or_functions, Callable):  # type: ignore[arg-type]
-        listener_or_functions = [listener_or_functions]  # type: ignore[list-item]
-
-    if isinstance(listener_or_functions, AsyncListener):
-        return listener_or_functions
-    elif isinstance(listener_or_functions, list):
-        middleware = middleware if middleware else []
-        middleware.insert(0, AsyncAttachingConversationKwargs(self.thread_context_store))
-        functions = listener_or_functions
-        ack_function = functions.pop(0)
-
-        matchers = matchers if matchers else []
-        listener_matchers: List[AsyncListenerMatcher] = []
-        for matcher in matchers:
-            if isinstance(matcher, AsyncListenerMatcher):
-                listener_matchers.append(matcher)
-            else:
-                listener_matchers.append(
-                    build_listener_matcher(
-                        func=matcher,  # type: ignore[arg-type]
-                        asyncio=True,
-                        base_logger=base_logger,
-                    )
-                )
-        return AsyncCustomListener(
-            app_name=self.app_name,
-            matchers=listener_matchers,
-            middleware=middleware,
-            ack_function=ack_function,
-            lazy_functions=functions,
-            auto_acknowledgement=True,
-            base_logger=base_logger or self.base_logger,
-        )
-    else:
-        raise BoltError(f"Invalid listener: {type(listener_or_functions)} detected")
-
-
-
-
-def thread_context_changed(self,
*args,
matchers: Callable[..., bool] | AsyncListenerMatcher | None = None,
middleware: Callable | AsyncMiddleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def thread_context_changed(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._thread_context_changed_listeners is None:
-        self._thread_context_changed_listeners = []
-    all_matchers = self._merge_matchers(
-        build_listener_matcher(
-            func=is_assistant_thread_context_changed_event,
-            asyncio=True,
-            base_logger=self.base_logger,
-        ),  # type: ignore[arg-type]
-        matchers,
-    )
-    if is_used_without_argument(args):
-        func = args[0]
-        self._thread_context_changed_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._thread_context_changed_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def thread_started(self,
*args,
matchers: Callable[..., bool] | AsyncListenerMatcher | None = None,
middleware: Callable | AsyncMiddleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def thread_started(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._thread_started_listeners is None:
-        self._thread_started_listeners = []
-    all_matchers = self._merge_matchers(
-        build_listener_matcher(
-            func=is_assistant_thread_started_event,
-            asyncio=True,
-            base_logger=self.base_logger,
-        ),  # type: ignore[arg-type]
-        matchers,
-    )
-    if is_used_without_argument(args):
-        func = args[0]
-        self._thread_started_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._thread_started_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def user_message(self,
*args,
matchers: Callable[..., bool] | AsyncListenerMatcher | None = None,
middleware: Callable | AsyncMiddleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def user_message(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._user_message_listeners is None:
-        self._user_message_listeners = []
-    all_matchers = self._merge_matchers(
-        build_listener_matcher(
-            func=is_user_message_event_in_assistant_thread,
-            asyncio=True,
-            base_logger=self.base_logger,
-        ),  # type: ignore[arg-type]
-        matchers,
-    )
-    if is_used_without_argument(args):
-        func = args[0]
-        self._user_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._user_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-

Inherited members

- -
-
-class AsyncBoltContext -(*args, **kwargs) -
-
-
- -Expand source code - -
class AsyncBoltContext(BaseContext):
-    """Context object associated with a request from Slack."""
-
-    def to_copyable(self) -> "AsyncBoltContext":
-        new_dict = {}
-        for prop_name, prop_value in self.items():
-            if prop_name in self.copyable_standard_property_names:
-                # all the standard properties are copiable
-                new_dict[prop_name] = prop_value
-            elif prop_name in self.non_copyable_standard_property_names:
-                # Do nothing with this property (e.g., listener_runner)
-                continue
-            else:
-                try:
-                    copied_value = create_copy(prop_value)
-                    new_dict[prop_name] = copied_value
-                except TypeError as te:
-                    self.logger.debug(
-                        f"Skipped setting '{prop_name}' to a copied request for lazy listeners "
-                        f"as it's not possible to make a deep copy (error: {te})"
-                    )
-        return AsyncBoltContext(new_dict)
-
-    # The return type is intentionally string to avoid circular imports
-    @property
-    def listener_runner(self) -> "AsyncioListenerRunner":
-        """The properly configured listener_runner that is available for middleware/listeners."""
-        return self["listener_runner"]
-
-    @property
-    def client(self) -> AsyncWebClient:
-        """The `AsyncWebClient` instance available for this request.
-
-            @app.event("app_mention")
-            async def handle_events(context):
-                await context.client.chat_postMessage(
-                    channel=context.channel_id,
-                    text="Thanks!",
-                )
-
-            # You can access "client" this way too.
-            @app.event("app_mention")
-            async def handle_events(client, context):
-                await client.chat_postMessage(
-                    channel=context.channel_id,
-                    text="Thanks!",
-                )
-
-        Returns:
-            `AsyncWebClient` instance
-        """
-        if "client" not in self:
-            self["client"] = AsyncWebClient(token=None)
-        return self["client"]
-
-    @property
-    def ack(self) -> AsyncAck:
-        """`ack()` function for this request.
-
-            @app.action("button")
-            async def handle_button_clicks(context):
-                await context.ack()
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            async def handle_button_clicks(ack):
-                await ack()
-
-        Returns:
-            Callable `ack()` function
-        """
-        if "ack" not in self:
-            self["ack"] = AsyncAck()
-        return self["ack"]
-
-    @property
-    def say(self) -> AsyncSay:
-        """`say()` function for this request.
-
-            @app.action("button")
-            async def handle_button_clicks(context):
-                await context.ack()
-                await context.say("Hi!")
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            async def handle_button_clicks(ack, say):
-                await ack()
-                await say("Hi!")
-
-        Returns:
-            Callable `say()` function
-        """
-        if "say" not in self:
-            self["say"] = AsyncSay(client=self.client, channel=self.channel_id)
-        return self["say"]
-
-    @property
-    def respond(self) -> Optional[AsyncRespond]:
-        """`respond()` function for this request.
-
-            @app.action("button")
-            async def handle_button_clicks(context):
-                await context.ack()
-                await context.respond("Hi!")
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            async def handle_button_clicks(ack, respond):
-                await ack()
-                await respond("Hi!")
-
-        Returns:
-            Callable `respond()` function
-        """
-        if "respond" not in self:
-            self["respond"] = AsyncRespond(
-                response_url=self.response_url,
-                proxy=self.client.proxy,
-                ssl=self.client.ssl,
-            )
-        return self["respond"]
-
-    @property
-    def complete(self) -> AsyncComplete:
-        """`complete()` function for this request. Once a custom function's state is set to complete,
-        any outputs the function returns will be passed along to the next step of its housing workflow,
-        or complete the workflow if the function is the last step in a workflow. Additionally,
-        any interactivity handlers associated to a function invocation will no longer be invocable.
-
-            @app.function("reverse")
-            async def handle_button_clicks(ack, complete):
-                await ack()
-                await complete(outputs={"stringReverse":"olleh"})
-
-            @app.function("reverse")
-            async def handle_button_clicks(context):
-                await context.ack()
-                await context.complete(outputs={"stringReverse":"olleh"})
-
-        Returns:
-            Callable `complete()` function
-        """
-        if "complete" not in self:
-            self["complete"] = AsyncComplete(client=self.client, function_execution_id=self.function_execution_id)
-        return self["complete"]
-
-    @property
-    def fail(self) -> AsyncFail:
-        """`fail()` function for this request. Once a custom function's state is set to error,
-        its housing workflow will be interrupted and any provided error message will be passed
-        on to the end user through SlackBot. Additionally, any interactivity handlers associated
-        to a function invocation will no longer be invocable.
-
-            @app.function("reverse")
-            async def handle_button_clicks(ack, fail):
-                await ack()
-                await fail(error="something went wrong")
-
-            @app.function("reverse")
-            async def handle_button_clicks(context):
-                await context.ack()
-                await context.fail(error="something went wrong")
-
-        Returns:
-            Callable `fail()` function
-        """
-        if "fail" not in self:
-            self["fail"] = AsyncFail(client=self.client, function_execution_id=self.function_execution_id)
-        return self["fail"]
-
-    @property
-    def set_title(self) -> Optional[AsyncSetTitle]:
-        return self.get("set_title")
-
-    @property
-    def set_status(self) -> Optional[AsyncSetStatus]:
-        return self.get("set_status")
-
-    @property
-    def set_suggested_prompts(self) -> Optional[AsyncSetSuggestedPrompts]:
-        return self.get("set_suggested_prompts")
-
-    @property
-    def get_thread_context(self) -> Optional[AsyncGetThreadContext]:
-        return self.get("get_thread_context")
-
-    @property
-    def say_stream(self) -> Optional[AsyncSayStream]:
-        return self.get("say_stream")
-
-    @property
-    def save_thread_context(self) -> Optional[AsyncSaveThreadContext]:
-        return self.get("save_thread_context")
-
-

Context object associated with a request from Slack.

-

Ancestors

- -

Instance variables

-
-
prop ackAsyncAck
-
-
- -Expand source code - -
@property
-def ack(self) -> AsyncAck:
-    """`ack()` function for this request.
-
-        @app.action("button")
-        async def handle_button_clicks(context):
-            await context.ack()
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        async def handle_button_clicks(ack):
-            await ack()
-
-    Returns:
-        Callable `ack()` function
-    """
-    if "ack" not in self:
-        self["ack"] = AsyncAck()
-    return self["ack"]
-
-

ack() function for this request.

-
@app.action("button")
-async def handle_button_clicks(context):
-    await context.ack()
-
-# You can access "ack" this way too.
-@app.action("button")
-async def handle_button_clicks(ack):
-    await ack()
-
-

Returns

-

Callable ack() function

-
-
prop client : slack_sdk.web.async_client.AsyncWebClient
-
-
- -Expand source code - -
@property
-def client(self) -> AsyncWebClient:
-    """The `AsyncWebClient` instance available for this request.
-
-        @app.event("app_mention")
-        async def handle_events(context):
-            await context.client.chat_postMessage(
-                channel=context.channel_id,
-                text="Thanks!",
-            )
-
-        # You can access "client" this way too.
-        @app.event("app_mention")
-        async def handle_events(client, context):
-            await client.chat_postMessage(
-                channel=context.channel_id,
-                text="Thanks!",
-            )
-
-    Returns:
-        `AsyncWebClient` instance
-    """
-    if "client" not in self:
-        self["client"] = AsyncWebClient(token=None)
-    return self["client"]
-
-

The AsyncWebClient instance available for this request.

-
@app.event("app_mention")
-async def handle_events(context):
-    await context.client.chat_postMessage(
-        channel=context.channel_id,
-        text="Thanks!",
-    )
-
-# You can access "client" this way too.
-@app.event("app_mention")
-async def handle_events(client, context):
-    await client.chat_postMessage(
-        channel=context.channel_id,
-        text="Thanks!",
-    )
-
-

Returns

-

AsyncWebClient instance

-
-
prop completeAsyncComplete
-
-
- -Expand source code - -
@property
-def complete(self) -> AsyncComplete:
-    """`complete()` function for this request. Once a custom function's state is set to complete,
-    any outputs the function returns will be passed along to the next step of its housing workflow,
-    or complete the workflow if the function is the last step in a workflow. Additionally,
-    any interactivity handlers associated to a function invocation will no longer be invocable.
-
-        @app.function("reverse")
-        async def handle_button_clicks(ack, complete):
-            await ack()
-            await complete(outputs={"stringReverse":"olleh"})
-
-        @app.function("reverse")
-        async def handle_button_clicks(context):
-            await context.ack()
-            await context.complete(outputs={"stringReverse":"olleh"})
-
-    Returns:
-        Callable `complete()` function
-    """
-    if "complete" not in self:
-        self["complete"] = AsyncComplete(client=self.client, function_execution_id=self.function_execution_id)
-    return self["complete"]
-
-

complete() function for this request. Once a custom function's state is set to complete, -any outputs the function returns will be passed along to the next step of its housing workflow, -or complete the workflow if the function is the last step in a workflow. Additionally, -any interactivity handlers associated to a function invocation will no longer be invocable.

-
@app.function("reverse")
-async def handle_button_clicks(ack, complete):
-    await ack()
-    await complete(outputs={"stringReverse":"olleh"})
-
-@app.function("reverse")
-async def handle_button_clicks(context):
-    await context.ack()
-    await context.complete(outputs={"stringReverse":"olleh"})
-
-

Returns

-

Callable complete() function

-
-
prop failAsyncFail
-
-
- -Expand source code - -
@property
-def fail(self) -> AsyncFail:
-    """`fail()` function for this request. Once a custom function's state is set to error,
-    its housing workflow will be interrupted and any provided error message will be passed
-    on to the end user through SlackBot. Additionally, any interactivity handlers associated
-    to a function invocation will no longer be invocable.
-
-        @app.function("reverse")
-        async def handle_button_clicks(ack, fail):
-            await ack()
-            await fail(error="something went wrong")
-
-        @app.function("reverse")
-        async def handle_button_clicks(context):
-            await context.ack()
-            await context.fail(error="something went wrong")
-
-    Returns:
-        Callable `fail()` function
-    """
-    if "fail" not in self:
-        self["fail"] = AsyncFail(client=self.client, function_execution_id=self.function_execution_id)
-    return self["fail"]
-
-

fail() function for this request. Once a custom function's state is set to error, -its housing workflow will be interrupted and any provided error message will be passed -on to the end user through SlackBot. Additionally, any interactivity handlers associated -to a function invocation will no longer be invocable.

-
@app.function("reverse")
-async def handle_button_clicks(ack, fail):
-    await ack()
-    await fail(error="something went wrong")
-
-@app.function("reverse")
-async def handle_button_clicks(context):
-    await context.ack()
-    await context.fail(error="something went wrong")
-
-

Returns

-

Callable fail() function

-
-
prop get_thread_contextAsyncGetThreadContext | None
-
-
- -Expand source code - -
@property
-def get_thread_context(self) -> Optional[AsyncGetThreadContext]:
-    return self.get("get_thread_context")
-
-
-
-
prop listener_runner : AsyncioListenerRunner
-
-
- -Expand source code - -
@property
-def listener_runner(self) -> "AsyncioListenerRunner":
-    """The properly configured listener_runner that is available for middleware/listeners."""
-    return self["listener_runner"]
-
-

The properly configured listener_runner that is available for middleware/listeners.

-
-
prop respondAsyncRespond | None
-
-
- -Expand source code - -
@property
-def respond(self) -> Optional[AsyncRespond]:
-    """`respond()` function for this request.
-
-        @app.action("button")
-        async def handle_button_clicks(context):
-            await context.ack()
-            await context.respond("Hi!")
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        async def handle_button_clicks(ack, respond):
-            await ack()
-            await respond("Hi!")
-
-    Returns:
-        Callable `respond()` function
-    """
-    if "respond" not in self:
-        self["respond"] = AsyncRespond(
-            response_url=self.response_url,
-            proxy=self.client.proxy,
-            ssl=self.client.ssl,
-        )
-    return self["respond"]
-
-

respond() function for this request.

-
@app.action("button")
-async def handle_button_clicks(context):
-    await context.ack()
-    await context.respond("Hi!")
-
-# You can access "ack" this way too.
-@app.action("button")
-async def handle_button_clicks(ack, respond):
-    await ack()
-    await respond("Hi!")
-
-

Returns

-

Callable respond() function

-
-
prop save_thread_contextAsyncSaveThreadContext | None
-
-
- -Expand source code - -
@property
-def save_thread_context(self) -> Optional[AsyncSaveThreadContext]:
-    return self.get("save_thread_context")
-
-
-
-
prop sayAsyncSay
-
-
- -Expand source code - -
@property
-def say(self) -> AsyncSay:
-    """`say()` function for this request.
-
-        @app.action("button")
-        async def handle_button_clicks(context):
-            await context.ack()
-            await context.say("Hi!")
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        async def handle_button_clicks(ack, say):
-            await ack()
-            await say("Hi!")
-
-    Returns:
-        Callable `say()` function
-    """
-    if "say" not in self:
-        self["say"] = AsyncSay(client=self.client, channel=self.channel_id)
-    return self["say"]
-
-

say() function for this request.

-
@app.action("button")
-async def handle_button_clicks(context):
-    await context.ack()
-    await context.say("Hi!")
-
-# You can access "ack" this way too.
-@app.action("button")
-async def handle_button_clicks(ack, say):
-    await ack()
-    await say("Hi!")
-
-

Returns

-

Callable say() function

-
-
prop say_streamAsyncSayStream | None
-
-
- -Expand source code - -
@property
-def say_stream(self) -> Optional[AsyncSayStream]:
-    return self.get("say_stream")
-
-
-
-
prop set_statusAsyncSetStatus | None
-
-
- -Expand source code - -
@property
-def set_status(self) -> Optional[AsyncSetStatus]:
-    return self.get("set_status")
-
-
-
-
prop set_suggested_promptsAsyncSetSuggestedPrompts | None
-
-
- -Expand source code - -
@property
-def set_suggested_prompts(self) -> Optional[AsyncSetSuggestedPrompts]:
-    return self.get("set_suggested_prompts")
-
-
-
-
prop set_titleAsyncSetTitle | None
-
-
- -Expand source code - -
@property
-def set_title(self) -> Optional[AsyncSetTitle]:
-    return self.get("set_title")
-
-
-
-
-

Methods

-
-
-def to_copyable(self) ‑> AsyncBoltContext -
-
-
- -Expand source code - -
def to_copyable(self) -> "AsyncBoltContext":
-    new_dict = {}
-    for prop_name, prop_value in self.items():
-        if prop_name in self.copyable_standard_property_names:
-            # all the standard properties are copiable
-            new_dict[prop_name] = prop_value
-        elif prop_name in self.non_copyable_standard_property_names:
-            # Do nothing with this property (e.g., listener_runner)
-            continue
-        else:
-            try:
-                copied_value = create_copy(prop_value)
-                new_dict[prop_name] = copied_value
-            except TypeError as te:
-                self.logger.debug(
-                    f"Skipped setting '{prop_name}' to a copied request for lazy listeners "
-                    f"as it's not possible to make a deep copy (error: {te})"
-                )
-    return AsyncBoltContext(new_dict)
-
-
-
-
-

Inherited members

- -
-
-class AsyncBoltRequest -(*,
body: str | dict,
query: str | Dict[str, str] | Dict[str, Sequence[str]] | None = None,
headers: Dict[str, str | Sequence[str]] | None = None,
context: Dict[str, Any] | None = None,
mode: str = 'http')
-
-
-
- -Expand source code - -
class AsyncBoltRequest:
-    raw_body: str
-    body: Dict[str, Any]
-    query: Dict[str, Sequence[str]]
-    headers: Dict[str, Sequence[str]]
-    content_type: Optional[str]
-    context: AsyncBoltContext
-    lazy_only: bool
-    lazy_function_name: Optional[str]
-    mode: str  # either "http" or "socket_mode"
-
-    def __init__(
-        self,
-        *,
-        body: Union[str, dict],
-        query: Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]] = None,
-        headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None,
-        context: Optional[Dict[str, Any]] = None,
-        mode: str = "http",  # either "http" or "socket_mode"
-    ):
-        """Request to a Bolt app.
-
-        Args:
-            body: The raw request body (only plain text is supported for "http" mode)
-            query: The query string data in any data format.
-            headers: The request headers.
-            context: The context in this request.
-            mode: The mode used for this request. (either "http" or "socket_mode")
-        """
-
-        if mode == "http":
-            # HTTP Mode
-            if body is not None and not isinstance(body, str):
-                raise BoltError(error_message_raw_body_required_in_http_mode())
-            self.raw_body = body if body is not None else ""
-        else:
-            # Socket Mode
-            if body is not None and isinstance(body, str):
-                self.raw_body = body
-            else:
-                # We don't convert the dict value to str
-                # as doing so does not guarantee to keep the original structure/format.
-                self.raw_body = ""
-
-        self.query = parse_query(query)
-        self.headers = build_normalized_headers(headers)
-        self.content_type = extract_content_type(self.headers)
-
-        if isinstance(body, str):
-            self.body = parse_body(self.raw_body, self.content_type)
-        elif isinstance(body, dict):
-            self.body = body
-        else:
-            self.body = {}
-
-        self.context = build_async_context(AsyncBoltContext(context if context else {}), self.body)
-        self.lazy_only = bool(self.headers.get("x-slack-bolt-lazy-only", [False])[0])
-        self.lazy_function_name = self.headers.get("x-slack-bolt-lazy-function-name", [None])[0]
-        self.mode = mode
-
-    def to_copyable(self) -> "AsyncBoltRequest":
-        body: Union[str, dict] = self.raw_body if self.mode == "http" else self.body
-        return AsyncBoltRequest(
-            body=body,
-            query=self.query,
-            headers=self.headers,
-            context=self.context.to_copyable(),
-            mode=self.mode,
-        )
-
-

Request to a Bolt app.

-

Args

-
-
body
-
The raw request body (only plain text is supported for "http" mode)
-
query
-
The query string data in any data format.
-
headers
-
The request headers.
-
context
-
The context in this request.
-
mode
-
The mode used for this request. (either "http" or "socket_mode")
-
-

Class variables

-
-
var body : Dict[str, Any]
-
-

The type of the None singleton.

-
-
var content_type : str | None
-
-

The type of the None singleton.

-
-
var contextAsyncBoltContext
-
-

The type of the None singleton.

-
-
var headers : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var lazy_function_name : str | None
-
-

The type of the None singleton.

-
-
var lazy_only : bool
-
-

The type of the None singleton.

-
-
var mode : str
-
-

The type of the None singleton.

-
-
var query : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var raw_body : str
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def to_copyable(self) ‑> AsyncBoltRequest -
-
-
- -Expand source code - -
def to_copyable(self) -> "AsyncBoltRequest":
-    body: Union[str, dict] = self.raw_body if self.mode == "http" else self.body
-    return AsyncBoltRequest(
-        body=body,
-        query=self.query,
-        headers=self.headers,
-        context=self.context.to_copyable(),
-        mode=self.mode,
-    )
-
-
-
-
-
-
-class AsyncCustomListenerMatcher -(*,
app_name: str,
func: Callable[..., Awaitable[bool]],
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncCustomListenerMatcher(AsyncListenerMatcher):
-    app_name: str
-    func: Callable[..., Awaitable[bool]]
-    arg_names: Sequence[str]
-    logger: Logger
-
-    def __init__(self, *, app_name: str, func: Callable[..., Awaitable[bool]], base_logger: Optional[Logger] = None):
-        self.app_name = app_name
-        self.func = func
-        self.arg_names = get_arg_names_of_callable(func)
-        self.logger = get_bolt_app_logger(self.app_name, self.func, base_logger)
-
-    async def async_matches(self, req: AsyncBoltRequest, resp: BoltResponse) -> bool:
-        return await self.func(
-            **build_async_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,  # type: ignore[arg-type]
-                request=req,
-                response=resp,
-                this_func=self.func,
-            )
-        )
-
-
-

Ancestors

- -

Class variables

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : Sequence[str]
-
-

The type of the None singleton.

-
-
var func : Callable[..., Awaitable[bool]]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class AsyncGetThreadContext -(thread_context_store: AsyncAssistantThreadContextStore,
channel_id: str,
thread_ts: str,
payload: dict)
-
-
-
- -Expand source code - -
class AsyncGetThreadContext:
-    thread_context_store: AsyncAssistantThreadContextStore
-    payload: dict
-    channel_id: str
-    thread_ts: str
-
-    _thread_context: Optional[AssistantThreadContext]
-    thread_context_loaded: bool
-
-    def __init__(
-        self,
-        thread_context_store: AsyncAssistantThreadContextStore,
-        channel_id: str,
-        thread_ts: str,
-        payload: dict,
-    ):
-        self.thread_context_store = thread_context_store
-        self.payload = payload
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-        self._thread_context: Optional[AssistantThreadContext] = None
-        self.thread_context_loaded = False
-
-    async def __call__(self) -> Optional[AssistantThreadContext]:
-        if self.thread_context_loaded is True:
-            return self._thread_context
-
-        thread = self.payload.get("assistant_thread")
-        if isinstance(thread, dict) and thread.get("context", {}).get("channel_id") is not None:
-            # assistant_thread_started
-            self._thread_context = AssistantThreadContext(thread["context"])
-            # for this event, the context will never be changed
-            self.thread_context_loaded = True
-        elif self.payload.get("channel") is not None and self.payload.get("thread_ts") is not None:
-            # message event
-            self._thread_context = await self.thread_context_store.find(channel_id=self.channel_id, thread_ts=self.thread_ts)
-
-        return self._thread_context
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var payload : dict
-
-

The type of the None singleton.

-
-
var thread_context_loaded : bool
-
-

The type of the None singleton.

-
-
var thread_context_storeAsyncAssistantThreadContextStore
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-class AsyncListener -
-
-
- -Expand source code - -
class AsyncListener(metaclass=ABCMeta):
-    matchers: Sequence[AsyncListenerMatcher]
-    middleware: Sequence[AsyncMiddleware]
-    ack_function: Callable[..., Awaitable[BoltResponse]]
-    lazy_functions: Sequence[Callable[..., Awaitable[None]]]
-    auto_acknowledgement: bool
-    ack_timeout: int
-
-    async def async_matches(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-    ) -> bool:
-        is_matched: bool = False
-        for matcher in self.matchers:
-            is_matched = await matcher.async_matches(req, resp)
-            if not is_matched:
-                return is_matched
-        return is_matched
-
-    async def run_async_middleware(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-    ) -> Tuple[Optional[BoltResponse], bool]:
-        """Runs an async middleware.
-
-        Args:
-            req: The incoming request
-            resp: The current response
-
-        Returns:
-            A tuple of the processed response and a flag indicating termination
-        """
-        for m in self.middleware:
-            middleware_state = {"next_called": False}
-
-            async def _next():
-                middleware_state["next_called"] = True
-
-            resp = await m.async_process(req=req, resp=resp, next=_next)  # type: ignore[assignment]
-            if not middleware_state["next_called"]:
-                # next() was not called in this middleware
-                return (resp, True)
-        return (resp, False)
-
-    @abstractmethod
-    async def run_ack_function(self, *, request: AsyncBoltRequest, response: BoltResponse) -> Optional[BoltResponse]:
-        """Runs all the registered middleware and then run the listener function.
-
-        Args:
-            request: The incoming request
-            response: The current response
-
-        Returns:
-            The processed response
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Class variables

-
-
var ack_function : Callable[..., Awaitable[BoltResponse]]
-
-

The type of the None singleton.

-
-
var ack_timeout : int
-
-

The type of the None singleton.

-
-
var auto_acknowledgement : bool
-
-

The type of the None singleton.

-
-
var lazy_functions : Sequence[Callable[..., Awaitable[None]]]
-
-

The type of the None singleton.

-
-
var matchers : Sequence[AsyncListenerMatcher]
-
-

The type of the None singleton.

-
-
var middleware : Sequence[AsyncMiddleware]
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-async def async_matches(self,
*,
req: AsyncBoltRequest,
resp: BoltResponse) ‑> bool
-
-
-
- -Expand source code - -
async def async_matches(
-    self,
-    *,
-    req: AsyncBoltRequest,
-    resp: BoltResponse,
-) -> bool:
-    is_matched: bool = False
-    for matcher in self.matchers:
-        is_matched = await matcher.async_matches(req, resp)
-        if not is_matched:
-            return is_matched
-    return is_matched
-
-
-
-
-async def run_ack_function(self,
*,
request: AsyncBoltRequest,
response: BoltResponse) ‑> BoltResponse | None
-
-
-
- -Expand source code - -
@abstractmethod
-async def run_ack_function(self, *, request: AsyncBoltRequest, response: BoltResponse) -> Optional[BoltResponse]:
-    """Runs all the registered middleware and then run the listener function.
-
-    Args:
-        request: The incoming request
-        response: The current response
-
-    Returns:
-        The processed response
-    """
-    raise NotImplementedError()
-
-

Runs all the registered middleware and then run the listener function.

-

Args

-
-
request
-
The incoming request
-
response
-
The current response
-
-

Returns

-

The processed response

-
-
-async def run_async_middleware(self,
*,
req: AsyncBoltRequest,
resp: BoltResponse) ‑> Tuple[BoltResponse | None, bool]
-
-
-
- -Expand source code - -
async def run_async_middleware(
-    self,
-    *,
-    req: AsyncBoltRequest,
-    resp: BoltResponse,
-) -> Tuple[Optional[BoltResponse], bool]:
-    """Runs an async middleware.
-
-    Args:
-        req: The incoming request
-        resp: The current response
-
-    Returns:
-        A tuple of the processed response and a flag indicating termination
-    """
-    for m in self.middleware:
-        middleware_state = {"next_called": False}
-
-        async def _next():
-            middleware_state["next_called"] = True
-
-        resp = await m.async_process(req=req, resp=resp, next=_next)  # type: ignore[assignment]
-        if not middleware_state["next_called"]:
-            # next() was not called in this middleware
-            return (resp, True)
-    return (resp, False)
-
-

Runs an async middleware.

-

Args

-
-
req
-
The incoming request
-
resp
-
The current response
-
-

Returns

-

A tuple of the processed response and a flag indicating termination

-
-
-
-
-class AsyncRespond -(*,
response_url: str | None,
proxy: str | None = None,
ssl: ssl.SSLContext | None = None)
-
-
-
- -Expand source code - -
class AsyncRespond:
-    response_url: Optional[str]
-    proxy: Optional[str]
-    ssl: Optional[SSLContext]
-
-    def __init__(
-        self,
-        *,
-        response_url: Optional[str],
-        proxy: Optional[str] = None,
-        ssl: Optional[SSLContext] = None,
-    ):
-        self.response_url = response_url
-        self.proxy = proxy
-        self.ssl = ssl
-
-    async def __call__(
-        self,
-        text: Union[str, dict] = "",
-        blocks: Optional[Sequence[Union[dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[dict, Attachment]]] = None,
-        response_type: Optional[str] = None,
-        replace_original: Optional[bool] = None,
-        delete_original: Optional[bool] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        thread_ts: Optional[str] = None,
-        metadata: Optional[Dict[str, Any]] = None,
-    ) -> WebhookResponse:
-        if self.response_url is not None:
-            client = AsyncWebhookClient(
-                url=self.response_url,
-                proxy=self.proxy,
-                ssl=self.ssl,
-            )
-            text_or_whole_response: Union[str, dict] = text
-            if isinstance(text_or_whole_response, str):
-                message = _build_message(
-                    text=text,  # type: ignore[arg-type]
-                    blocks=blocks,
-                    attachments=attachments,
-                    response_type=response_type,
-                    replace_original=replace_original,
-                    delete_original=delete_original,
-                    unfurl_links=unfurl_links,
-                    unfurl_media=unfurl_media,
-                    thread_ts=thread_ts,
-                    metadata=metadata,
-                )
-                return await client.send_dict(message)
-            elif isinstance(text_or_whole_response, dict):
-                whole_response: dict = text_or_whole_response
-                message = _build_message(**whole_response)
-                return await client.send_dict(message)
-            else:
-                raise ValueError(f"The arg is unexpected type ({type(text)})")
-        else:
-            raise ValueError("respond is unsupported here as there is no response_url")
-
-
-

Class variables

-
-
var proxy : str | None
-
-

The type of the None singleton.

-
-
var response_url : str | None
-
-

The type of the None singleton.

-
-
var ssl : ssl.SSLContext | None
-
-

The type of the None singleton.

-
-
-
-
-class AsyncSaveThreadContext -(thread_context_store: AsyncAssistantThreadContextStore,
channel_id: str,
thread_ts: str)
-
-
-
- -Expand source code - -
class AsyncSaveThreadContext:
-    thread_context_store: AsyncAssistantThreadContextStore
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        thread_context_store: AsyncAssistantThreadContextStore,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.thread_context_store = thread_context_store
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    async def __call__(self, new_context: Dict[str, str]) -> None:
-        await self.thread_context_store.save(
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-            context=new_context,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var thread_context_storeAsyncAssistantThreadContextStore
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-class AsyncSay -(client: slack_sdk.web.async_client.AsyncWebClient | None,
channel: str | None,
thread_ts: str | None = None,
build_metadata: Callable[[], Awaitable[Dict | slack_sdk.models.metadata.Metadata]] | None = None)
-
-
-
- -Expand source code - -
class AsyncSay:
-    client: Optional[AsyncWebClient]
-    channel: Optional[str]
-    thread_ts: Optional[str]
-    build_metadata: Optional[Callable[[], Awaitable[Union[Dict, Metadata]]]]
-
-    def __init__(
-        self,
-        client: Optional[AsyncWebClient],
-        channel: Optional[str],
-        thread_ts: Optional[str] = None,
-        build_metadata: Optional[Callable[[], Awaitable[Union[Dict, Metadata]]]] = None,
-    ):
-        self.client = client
-        self.channel = channel
-        self.thread_ts = thread_ts
-        self.build_metadata = build_metadata
-
-    async def __call__(
-        self,
-        text: Union[str, dict] = "",
-        blocks: Optional[Sequence[Union[Dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[Dict, Attachment]]] = None,
-        channel: Optional[str] = None,
-        as_user: Optional[bool] = None,
-        thread_ts: Optional[str] = None,
-        reply_broadcast: Optional[bool] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        markdown_text: Optional[str] = None,
-        mrkdwn: Optional[bool] = None,
-        link_names: Optional[bool] = None,
-        parse: Optional[str] = None,  # none, full
-        metadata: Optional[Union[Dict, Metadata]] = None,
-        **kwargs,
-    ) -> AsyncSlackResponse:
-        if _can_say(self, channel):
-            if metadata is None and self.build_metadata is not None:
-                metadata = await self.build_metadata()
-            text_or_whole_response: Union[str, dict] = text
-            if isinstance(text_or_whole_response, str):
-                text = text_or_whole_response
-                return await self.client.chat_postMessage(  # type: ignore[union-attr]
-                    channel=channel or self.channel,  # type: ignore[arg-type]
-                    text=text,
-                    blocks=blocks,
-                    attachments=attachments,
-                    as_user=as_user,
-                    thread_ts=thread_ts or self.thread_ts,
-                    reply_broadcast=reply_broadcast,
-                    unfurl_links=unfurl_links,
-                    unfurl_media=unfurl_media,
-                    icon_emoji=icon_emoji,
-                    icon_url=icon_url,
-                    username=username,
-                    markdown_text=markdown_text,
-                    mrkdwn=mrkdwn,
-                    link_names=link_names,
-                    parse=parse,
-                    metadata=metadata,
-                    **kwargs,
-                )
-            elif isinstance(text_or_whole_response, dict):
-                message: dict = create_copy(text_or_whole_response)
-                if "channel" not in message:
-                    message["channel"] = channel or self.channel
-                if "thread_ts" not in message:
-                    message["thread_ts"] = thread_ts or self.thread_ts
-                if "metadata" not in message:
-                    message["metadata"] = metadata
-                return await self.client.chat_postMessage(**message)  # type: ignore[union-attr]
-            else:
-                raise ValueError(f"The arg is unexpected type ({type(text_or_whole_response)})")
-        else:
-            raise ValueError("say without channel_id here is unsupported")
-
-
-

Class variables

-
-
var build_metadata : Callable[[], Awaitable[Dict | slack_sdk.models.metadata.Metadata]] | None
-
-

The type of the None singleton.

-
-
var channel : str | None
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.async_client.AsyncWebClient | None
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-class AsyncSayStream -(*,
client: slack_sdk.web.async_client.AsyncWebClient,
channel: str | None = None,
recipient_team_id: str | None = None,
recipient_user_id: str | None = None,
thread_ts: str | None = None)
-
-
-
- -Expand source code - -
class AsyncSayStream:
-    client: AsyncWebClient
-    channel: Optional[str]
-    recipient_team_id: Optional[str]
-    recipient_user_id: Optional[str]
-    thread_ts: Optional[str]
-
-    def __init__(
-        self,
-        *,
-        client: AsyncWebClient,
-        channel: Optional[str] = None,
-        recipient_team_id: Optional[str] = None,
-        recipient_user_id: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-    ):
-        self.client = client
-        self.channel = channel
-        self.recipient_team_id = recipient_team_id
-        self.recipient_user_id = recipient_user_id
-        self.thread_ts = thread_ts
-
-    async def __call__(
-        self,
-        *,
-        buffer_size: Optional[int] = None,
-        channel: Optional[str] = None,
-        recipient_team_id: Optional[str] = None,
-        recipient_user_id: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        **kwargs,
-    ) -> AsyncChatStream:
-        """Starts a new chat stream with context."""
-        channel = channel or self.channel
-        thread_ts = thread_ts or self.thread_ts
-        if channel is None:
-            raise ValueError("say_stream without channel here is unsupported")
-        if thread_ts is None:
-            raise ValueError("say_stream without thread_ts here is unsupported")
-
-        if buffer_size is not None:
-            return await self.client.chat_stream(
-                buffer_size=buffer_size,
-                channel=channel,
-                recipient_team_id=recipient_team_id or self.recipient_team_id,
-                recipient_user_id=recipient_user_id or self.recipient_user_id,
-                thread_ts=thread_ts,
-                icon_emoji=icon_emoji,
-                icon_url=icon_url,
-                username=username,
-                **kwargs,
-            )
-        return await self.client.chat_stream(
-            channel=channel,
-            recipient_team_id=recipient_team_id or self.recipient_team_id,
-            recipient_user_id=recipient_user_id or self.recipient_user_id,
-            thread_ts=thread_ts,
-            icon_emoji=icon_emoji,
-            icon_url=icon_url,
-            username=username,
-            **kwargs,
-        )
-
-
-

Class variables

-
-
var channel : str | None
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var recipient_team_id : str | None
-
-

The type of the None singleton.

-
-
var recipient_user_id : str | None
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-class AsyncSetStatus -(client: slack_sdk.web.async_client.AsyncWebClient,
channel_id: str,
thread_ts: str)
-
-
-
- -Expand source code - -
class AsyncSetStatus:
-    client: AsyncWebClient
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        client: AsyncWebClient,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    async def __call__(
-        self,
-        status: str,
-        loading_messages: Optional[List[str]] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        **kwargs,
-    ) -> AsyncSlackResponse:
-        return await self.client.assistant_threads_setStatus(
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-            status=status,
-            loading_messages=loading_messages,
-            icon_emoji=icon_emoji,
-            icon_url=icon_url,
-            username=username,
-            **kwargs,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-class AsyncSetSuggestedPrompts -(client: slack_sdk.web.async_client.AsyncWebClient,
channel_id: str,
thread_ts: str | None = None)
-
-
-
- -Expand source code - -
class AsyncSetSuggestedPrompts:
-    client: AsyncWebClient
-    channel_id: str
-    thread_ts: Optional[str]
-
-    def __init__(
-        self,
-        client: AsyncWebClient,
-        channel_id: str,
-        thread_ts: Optional[str] = None,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    async def __call__(
-        self,
-        prompts: Sequence[Union[str, Dict[str, str]]],
-        title: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-    ) -> AsyncSlackResponse:
-        prompts_arg: List[Dict[str, str]] = []
-        for prompt in prompts:
-            if isinstance(prompt, str):
-                prompts_arg.append({"title": prompt, "message": prompt})
-            else:
-                prompts_arg.append(prompt)
-
-        return await self.client.assistant_threads_setSuggestedPrompts(
-            channel_id=self.channel_id,
-            thread_ts=thread_ts if thread_ts is not None else self.thread_ts,
-            prompts=prompts_arg,
-            title=title,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-class AsyncSetTitle -(client: slack_sdk.web.async_client.AsyncWebClient,
channel_id: str,
thread_ts: str)
-
-
-
- -Expand source code - -
class AsyncSetTitle:
-    client: AsyncWebClient
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        client: AsyncWebClient,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    async def __call__(self, title: str) -> AsyncSlackResponse:
-        return await self.client.assistant_threads_setTitle(
-            title=title,
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/authorization/async_authorize.html b/docs/reference/authorization/async_authorize.html deleted file mode 100644 index b4dfa2682..000000000 --- a/docs/reference/authorization/async_authorize.html +++ /dev/null @@ -1,524 +0,0 @@ - - - - - - -slack_bolt.authorization.async_authorize API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.authorization.async_authorize

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncAuthorize -
-
-
- -Expand source code - -
class AsyncAuthorize:
-    """This provides authorize function that returns AuthorizeResult
-    for an incoming request from Slack."""
-
-    def __init__(self):
-        pass
-
-    async def __call__(
-        self,
-        *,
-        context: AsyncBoltContext,
-        enterprise_id: Optional[str],
-        team_id: Optional[str],  # can be None for org-wide installed apps
-        user_id: Optional[str],
-        # actor_* can be used only when user_token_resolution: "actor" is set
-        actor_enterprise_id: Optional[str] = None,
-        actor_team_id: Optional[str] = None,
-        actor_user_id: Optional[str] = None,
-    ) -> Optional[AuthorizeResult]:
-        raise NotImplementedError()
-
-

This provides authorize function that returns AuthorizeResult -for an incoming request from Slack.

-

Subclasses

- -
-
-class AsyncCallableAuthorize -(*,
logger: logging.Logger,
func: Callable[..., Awaitable[AuthorizeResult]])
-
-
-
- -Expand source code - -
class AsyncCallableAuthorize(AsyncAuthorize):
-    """When you pass the authorize argument in AsyncApp constructor,
-    This authorize implementation will be used.
-    """
-
-    def __init__(self, *, logger: Logger, func: Callable[..., Awaitable[AuthorizeResult]]):
-        self.logger = logger
-        self.func = func
-        self.arg_names = get_arg_names_of_callable(func)
-
-    async def __call__(
-        self,
-        *,
-        context: AsyncBoltContext,
-        enterprise_id: Optional[str],
-        team_id: Optional[str],  # can be None for org-wide installed apps
-        user_id: Optional[str],
-        # actor_* can be used only when user_token_resolution: "actor" is set
-        actor_enterprise_id: Optional[str] = None,
-        actor_team_id: Optional[str] = None,
-        actor_user_id: Optional[str] = None,
-    ) -> Optional[AuthorizeResult]:
-        try:
-            all_available_args = {
-                "args": AsyncAuthorizeArgs(
-                    context=context,
-                    enterprise_id=enterprise_id,
-                    team_id=team_id,
-                    user_id=user_id,
-                ),
-                "logger": context.logger,
-                "client": context.client,
-                "context": context,
-                "enterprise_id": enterprise_id,
-                "team_id": team_id,
-                "user_id": user_id,
-                "actor_enterprise_id": actor_enterprise_id,
-                "actor_team_id": actor_team_id,
-                "actor_user_id": actor_user_id,
-            }
-            for k, v in context.items():
-                if k not in all_available_args:
-                    all_available_args[k] = v
-
-            kwargs: Dict[str, Any] = {k: v for k, v in all_available_args.items() if k in self.arg_names}
-            found_arg_names = kwargs.keys()
-            for name in self.arg_names:
-                if name not in found_arg_names:
-                    self.logger.warning(f"{name} is not a valid argument")
-                    kwargs[name] = None
-
-            auth_result: Optional[AuthorizeResult] = await self.func(**kwargs)
-            if auth_result is None:
-                return auth_result
-
-            if isinstance(auth_result, AuthorizeResult):
-                return auth_result
-            else:
-                raise ValueError(f"Unexpected returned value from authorize function (type: {type(auth_result)})")
-        except SlackApiError as err:
-            self.logger.debug(
-                f"The stored bot token for enterprise_id: {enterprise_id} team_id: {team_id} "
-                f"is no longer valid. (response: {err.response})"
-            )
-            return None
-
-

When you pass the authorize argument in AsyncApp constructor, -This authorize implementation will be used.

-

Ancestors

- -
-
-class AsyncInstallationStoreAuthorize -(*,
logger: logging.Logger,
installation_store: slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore,
client_id: str | None = None,
client_secret: str | None = None,
token_rotation_expiration_minutes: int | None = None,
bot_only: bool = False,
cache_enabled: bool = False,
client: slack_sdk.web.async_client.AsyncWebClient | None = None,
user_token_resolution: str = 'authed_user')
-
-
-
- -Expand source code - -
class AsyncInstallationStoreAuthorize(AsyncAuthorize):
-    """If you use the OAuth flow settings, this authorize implementation will be used.
-    As long as your own InstallationStore (or the built-in ones) works as you expect,
-    you can expect that the authorize layer should work for you without any customization.
-    """
-
-    authorize_result_cache: Dict[str, AuthorizeResult]
-    bot_only: bool
-    user_token_resolution: str
-    find_installation_available: Optional[bool]
-    find_bot_available: Optional[bool]
-    token_rotator: Optional[AsyncTokenRotator]
-
-    _config_error_message: str = "AsyncInstallationStore with client_id/client_secret are required for token rotation"
-
-    def __init__(
-        self,
-        *,
-        logger: Logger,
-        installation_store: AsyncInstallationStore,
-        client_id: Optional[str] = None,
-        client_secret: Optional[str] = None,
-        token_rotation_expiration_minutes: Optional[int] = None,
-        # For v1.0.x compatibility and people who still want its simplicity
-        # use only InstallationStore#find_bot(enterprise_id, team_id)
-        bot_only: bool = False,
-        cache_enabled: bool = False,
-        client: Optional[AsyncWebClient] = None,
-        # Since v1.27, user token resolution can be actor ID based when the mode is enabled
-        user_token_resolution: str = "authed_user",
-    ):
-        self.logger = logger
-        self.installation_store = installation_store
-        self.bot_only = bot_only
-        self.user_token_resolution = user_token_resolution
-        self.cache_enabled = cache_enabled
-        self.authorize_result_cache = {}
-        self.find_installation_available = None
-        self.find_bot_available = None
-        if client_id is not None and client_secret is not None:
-            self.token_rotator = AsyncTokenRotator(
-                client_id=client_id,
-                client_secret=client_secret,
-                client=client,
-            )
-        else:
-            self.token_rotator = None
-        self.token_rotation_expiration_minutes = token_rotation_expiration_minutes or 120
-
-    async def __call__(
-        self,
-        *,
-        context: AsyncBoltContext,
-        enterprise_id: Optional[str],
-        team_id: Optional[str],  # can be None for org-wide installed apps
-        user_id: Optional[str],
-        # actor_* can be used only when user_token_resolution: "actor" is set
-        actor_enterprise_id: Optional[str] = None,
-        actor_team_id: Optional[str] = None,
-        actor_user_id: Optional[str] = None,
-    ) -> Optional[AuthorizeResult]:
-
-        if self.find_installation_available is None:
-            self.find_installation_available = hasattr(self.installation_store, "async_find_installation")
-        if self.find_bot_available is None:
-            self.find_bot_available = hasattr(self.installation_store, "async_find_bot")
-
-        bot_token: Optional[str] = None
-        user_token: Optional[str] = None
-        bot_scopes: Optional[Sequence[str]] = None
-        user_scopes: Optional[Sequence[str]] = None
-        latest_bot_installation: Optional[Installation] = None
-        this_user_installation: Optional[Installation] = None
-
-        if not self.bot_only and self.find_installation_available:
-            # Since v1.1, this is the default way.
-            # If you want to use find_bot / delete_bot only, you can set bot_only as True.
-            try:
-                # Note that this is the latest information for the org/workspace.
-                # The installer may not be the user associated with this incoming request.
-                latest_bot_installation = await self.installation_store.async_find_installation(
-                    enterprise_id=enterprise_id,
-                    team_id=team_id,
-                    is_enterprise_install=context.is_enterprise_install,
-                )
-                # If the user_token in the latest_installation is not for the user associated with this request,
-                # we'll fetch a different installation for the user below
-                # The example use cases are:
-                # - The app's installation requires both bot and user tokens
-                # - The app has two installation paths 1) bot installation 2) individual user authorization
-                if latest_bot_installation is not None:
-                    # Save the latest bot token
-                    bot_token = latest_bot_installation.bot_token  # this still can be None
-                    user_token = latest_bot_installation.user_token  # this still can be None
-                    bot_scopes = latest_bot_installation.bot_scopes  # this still can be None
-                    user_scopes = latest_bot_installation.user_scopes  # this still can be None
-
-                    if latest_bot_installation.user_id != user_id:
-                        # First off, remove the user token as the installer is a different user
-                        user_token = None
-                        user_scopes = None
-                        latest_bot_installation.user_token = None
-                        latest_bot_installation.user_refresh_token = None
-                        latest_bot_installation.user_token_expires_at = None
-                        latest_bot_installation.user_scopes = None
-
-                        # try to fetch the request user's installation
-                        # to reflect the user's access token if exists
-                        # try to fetch the request user's installation
-                        # to reflect the user's access token if exists
-                        if self.user_token_resolution == "actor":
-                            if actor_enterprise_id is not None or actor_team_id is not None:
-                                # Note that actor_team_id can be absent for app_mention events
-                                this_user_installation = await self.installation_store.async_find_installation(
-                                    enterprise_id=actor_enterprise_id,
-                                    team_id=actor_team_id,
-                                    user_id=actor_user_id,
-                                    is_enterprise_install=None,
-                                )
-                        else:
-                            this_user_installation = await self.installation_store.async_find_installation(
-                                enterprise_id=enterprise_id,
-                                team_id=team_id,
-                                user_id=user_id,
-                                is_enterprise_install=context.is_enterprise_install,
-                            )
-                        if this_user_installation is not None:
-                            user_token = this_user_installation.user_token
-                            user_scopes = this_user_installation.user_scopes
-                            if (
-                                latest_bot_installation.bot_token is None
-                                # enterprise_id/team_id can be different for Slack Connect channel events
-                                # when enabling user_token_resolution: "actor"
-                                and latest_bot_installation.enterprise_id == this_user_installation.enterprise_id
-                                and latest_bot_installation.team_id == this_user_installation.team_id
-                            ):
-                                # If latest_installation has a bot token, we never overwrite the value
-                                bot_token = this_user_installation.bot_token
-                                bot_scopes = this_user_installation.bot_scopes
-
-                            # If token rotation is enabled, running rotation may be needed here
-                            refreshed = await self._rotate_and_save_tokens_if_necessary(this_user_installation)
-                            if refreshed is not None:
-                                user_token = refreshed.user_token
-                                user_scopes = refreshed.user_scopes
-                                if (
-                                    latest_bot_installation.bot_token is None
-                                    # enterprise_id/team_id can be different for Slack Connect channel events
-                                    # when enabling user_token_resolution: "actor"
-                                    and latest_bot_installation.enterprise_id == this_user_installation.enterprise_id
-                                    and latest_bot_installation.team_id == this_user_installation.team_id
-                                ):
-                                    # If latest_installation has a bot token, we never overwrite the value
-                                    bot_token = refreshed.bot_token
-                                    bot_scopes = refreshed.bot_scopes
-
-                    # If token rotation is enabled, running rotation may be needed here
-                    refreshed = await self._rotate_and_save_tokens_if_necessary(latest_bot_installation)
-                    if refreshed is not None:
-                        bot_token = refreshed.bot_token
-                        bot_scopes = refreshed.bot_scopes
-                        if this_user_installation is None:
-                            # Only when we don't have `this_user_installation` here,
-                            # the `user_token` is for the user associated with this request
-                            user_token = refreshed.user_token
-                            user_scopes = refreshed.user_scopes
-
-            except SlackTokenRotationError as rotation_error:
-                # When token rotation fails, it is usually unrecoverable
-                # So, this built-in middleware gives up continuing with the following middleware and listeners
-                self.logger.error(f"Failed to rotate tokens due to {rotation_error}")
-                return None
-            except NotImplementedError as _:
-                self.find_installation_available = False
-
-        if (
-            # If you intentionally use only `find_bot` / `delete_bot`,
-            self.bot_only
-            # If the `find_installation` method is not available,
-            or not self.find_installation_available
-            # If the `find_installation` method did not return data and find_bot method is available,
-            or (self.find_bot_available is True and bot_token is None and user_token is None)
-        ):
-            try:
-                bot: Optional[Bot] = await self.installation_store.async_find_bot(
-                    enterprise_id=enterprise_id,
-                    team_id=team_id,
-                    is_enterprise_install=context.is_enterprise_install,
-                )
-                if bot is not None:
-                    bot_token = bot.bot_token
-                    bot_scopes = bot.bot_scopes
-                    if bot.bot_refresh_token is not None:
-                        # Token rotation
-                        if self.token_rotator is None:
-                            raise BoltError(self._config_error_message)
-                        refreshed_bot = await self.token_rotator.perform_bot_token_rotation(
-                            bot=bot,
-                            minutes_before_expiration=self.token_rotation_expiration_minutes,
-                        )
-                        if refreshed_bot is not None:
-                            await self.installation_store.async_save_bot(refreshed_bot)
-                            bot_token = refreshed_bot.bot_token
-                            bot_scopes = refreshed_bot.bot_scopes
-
-            except SlackTokenRotationError as rotation_error:
-                # When token rotation fails, it is usually unrecoverable
-                # So, this built-in middleware gives up continuing with the following middleware and listeners
-                self.logger.error(f"Failed to rotate tokens due to {rotation_error}")
-                return None
-            except NotImplementedError as _:
-                self.find_bot_available = False
-            except Exception as e:
-                self.logger.info(f"Failed to call find_bot method: {e}")
-
-        token: Optional[str] = bot_token or user_token
-        if token is None:
-            # No valid token was found
-            self._debug_log_for_not_found(enterprise_id, team_id)
-            return None
-
-        # Check cache to see if the bot object already exists
-        if self.cache_enabled and token in self.authorize_result_cache:
-            return self.authorize_result_cache[token]
-
-        try:
-            auth_test_api_response = await context.client.auth_test(token=token)
-            user_auth_test_response = None
-            if user_token is not None and token != user_token:
-                user_auth_test_response = await context.client.auth_test(token=user_token)
-            authorize_result = AuthorizeResult.from_auth_test_response(
-                auth_test_response=auth_test_api_response,
-                user_auth_test_response=user_auth_test_response,
-                bot_token=bot_token,
-                user_token=user_token,
-                bot_scopes=bot_scopes,
-                user_scopes=user_scopes,
-            )
-            if self.cache_enabled:
-                self.authorize_result_cache[token] = authorize_result
-            return authorize_result
-        except SlackApiError as err:
-            self.logger.debug(
-                f"The stored bot token for enterprise_id: {enterprise_id} team_id: {team_id} "
-                f"is no longer valid. (response: {err.response})"
-            )
-            return None
-
-    # ------------------------------------------------
-
-    def _debug_log_for_not_found(self, enterprise_id: Optional[str], team_id: Optional[str]):
-        self.logger.debug("No installation data found " f"for enterprise_id: {enterprise_id} team_id: {team_id}")
-
-    async def _rotate_and_save_tokens_if_necessary(self, installation: Optional[Installation]) -> Optional[Installation]:
-        if installation is None or (installation.user_refresh_token is None and installation.bot_refresh_token is None):
-            # No need to rotate tokens
-            return None
-
-        if self.token_rotator is None:
-            # Token rotation is required but this Bolt app is not properly configured
-            raise BoltError(self._config_error_message)
-
-        refreshed: Optional[Installation] = await self.token_rotator.perform_token_rotation(
-            installation=installation,
-            minutes_before_expiration=self.token_rotation_expiration_minutes,
-        )
-        if refreshed is not None:
-            # Save the refreshed data in database for following requests
-            await self.installation_store.async_save(refreshed)
-        return refreshed
-
-

If you use the OAuth flow settings, this authorize implementation will be used. -As long as your own InstallationStore (or the built-in ones) works as you expect, -you can expect that the authorize layer should work for you without any customization.

-

Ancestors

- -

Class variables

-
-
var authorize_result_cache : Dict[str, AuthorizeResult]
-
-

The type of the None singleton.

-
-
var bot_only : bool
-
-

The type of the None singleton.

-
-
var find_bot_available : bool | None
-
-

The type of the None singleton.

-
-
var find_installation_available : bool | None
-
-

The type of the None singleton.

-
-
var token_rotator : slack_sdk.oauth.token_rotation.async_rotator.AsyncTokenRotator | None
-
-

The type of the None singleton.

-
-
var user_token_resolution : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/authorization/async_authorize_args.html b/docs/reference/authorization/async_authorize_args.html deleted file mode 100644 index 5de20f757..000000000 --- a/docs/reference/authorization/async_authorize_args.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - -slack_bolt.authorization.async_authorize_args API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.authorization.async_authorize_args

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncAuthorizeArgs -(*,
context: AsyncBoltContext,
enterprise_id: str | None,
team_id: str | None,
user_id: str | None)
-
-
-
- -Expand source code - -
class AsyncAuthorizeArgs:
-    context: AsyncBoltContext
-    logger: Logger
-    client: AsyncWebClient
-    enterprise_id: Optional[str]
-    team_id: Optional[str]
-    user_id: Optional[str]
-
-    def __init__(
-        self,
-        *,
-        context: AsyncBoltContext,
-        enterprise_id: Optional[str],
-        team_id: Optional[str],  # can be None for org-wide installed apps
-        user_id: Optional[str],
-    ):
-        """The full list of the arguments passed to `authorize` function.
-
-        Args:
-            context: The request context
-            enterprise_id: The Organization ID (Enterprise Grid)
-            team_id: The workspace ID
-            user_id: The request user ID
-        """
-        self.context = context
-        self.logger = context.logger
-        self.client = context.client
-        self.enterprise_id = enterprise_id
-        self.team_id = team_id
-        self.user_id = user_id
-
-

The full list of the arguments passed to authorize function.

-

Args

-
-
context
-
The request context
-
enterprise_id
-
The Organization ID (Enterprise Grid)
-
team_id
-
The workspace ID
-
user_id
-
The request user ID
-
-

Class variables

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var contextAsyncBoltContext
-
-

The type of the None singleton.

-
-
var enterprise_id : str | None
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
var team_id : str | None
-
-

The type of the None singleton.

-
-
var user_id : str | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/authorization/authorize.html b/docs/reference/authorization/authorize.html deleted file mode 100644 index 33b50be02..000000000 --- a/docs/reference/authorization/authorize.html +++ /dev/null @@ -1,522 +0,0 @@ - - - - - - -slack_bolt.authorization.authorize API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.authorization.authorize

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Authorize -
-
-
- -Expand source code - -
class Authorize:
-    """This provides authorize function that returns AuthorizeResult
-    for an incoming request from Slack."""
-
-    def __init__(self):
-        pass
-
-    def __call__(
-        self,
-        *,
-        context: BoltContext,
-        enterprise_id: Optional[str],
-        team_id: Optional[str],  # can be None for org-wide installed apps
-        user_id: Optional[str],
-        # actor_* can be used only when user_token_resolution: "actor" is set
-        actor_enterprise_id: Optional[str] = None,
-        actor_team_id: Optional[str] = None,
-        actor_user_id: Optional[str] = None,
-    ) -> Optional[AuthorizeResult]:
-        raise NotImplementedError()
-
-

This provides authorize function that returns AuthorizeResult -for an incoming request from Slack.

-

Subclasses

- -
-
-class CallableAuthorize -(*,
logger: logging.Logger,
func: Callable[..., AuthorizeResult])
-
-
-
- -Expand source code - -
class CallableAuthorize(Authorize):
-    """When you pass the `authorize` argument in AsyncApp constructor,
-    This `authorize` implementation will be used.
-    """
-
-    def __init__(
-        self,
-        *,
-        logger: Logger,
-        func: Callable[..., AuthorizeResult],
-    ):
-        self.logger = logger
-        self.func = func
-        self.arg_names = get_arg_names_of_callable(func)
-
-    def __call__(
-        self,
-        *,
-        context: BoltContext,
-        enterprise_id: Optional[str],
-        team_id: Optional[str],  # can be None for org-wide installed apps
-        user_id: Optional[str],
-        # actor_* can be used only when user_token_resolution: "actor" is set
-        actor_enterprise_id: Optional[str] = None,
-        actor_team_id: Optional[str] = None,
-        actor_user_id: Optional[str] = None,
-    ) -> Optional[AuthorizeResult]:
-        try:
-            all_available_args = {
-                "args": AuthorizeArgs(
-                    context=context,
-                    enterprise_id=enterprise_id,
-                    team_id=team_id,
-                    user_id=user_id,
-                ),
-                "logger": context.logger,
-                "client": context.client,
-                "context": context,
-                "enterprise_id": enterprise_id,
-                "team_id": team_id,
-                "user_id": user_id,
-                "actor_enterprise_id": actor_enterprise_id,
-                "actor_team_id": actor_team_id,
-                "actor_user_id": actor_user_id,
-            }
-            for k, v in context.items():
-                if k not in all_available_args:
-                    all_available_args[k] = v
-
-            kwargs: Dict[str, Any] = {k: v for k, v in all_available_args.items() if k in self.arg_names}
-            found_arg_names = kwargs.keys()
-            for name in self.arg_names:
-                if name not in found_arg_names:
-                    self.logger.warning(f"{name} is not a valid argument")
-                    kwargs[name] = None
-
-            auth_result = self.func(**kwargs)
-            if auth_result is None:
-                return auth_result
-
-            if isinstance(auth_result, AuthorizeResult):
-                return auth_result
-            else:
-                raise ValueError(f"Unexpected returned value from authorize function (type: {type(auth_result)})")
-        except SlackApiError as err:
-            self.logger.debug(
-                f"The stored bot token for enterprise_id: {enterprise_id} team_id: {team_id} "
-                f"is no longer valid. (response: {err.response})"
-            )
-            return None
-
-

When you pass the authorize argument in AsyncApp constructor, -This authorize implementation will be used.

-

Ancestors

- -
-
-class InstallationStoreAuthorize -(*,
logger: logging.Logger,
installation_store: slack_sdk.oauth.installation_store.installation_store.InstallationStore,
client_id: str | None = None,
client_secret: str | None = None,
token_rotation_expiration_minutes: int | None = None,
bot_only: bool = False,
cache_enabled: bool = False,
client: slack_sdk.web.client.WebClient | None = None,
user_token_resolution: str = 'authed_user')
-
-
-
- -Expand source code - -
class InstallationStoreAuthorize(Authorize):
-    """If you use the OAuth flow settings, this `authorize` implementation will be used.
-    As long as your own InstallationStore (or the built-in ones) works as you expect,
-    you can expect that the `authorize` layer should work for you without any customization.
-    """
-
-    authorize_result_cache: Dict[str, AuthorizeResult]
-    bot_only: bool
-    user_token_resolution: str
-    find_installation_available: bool
-    find_bot_available: bool
-    token_rotator: Optional[TokenRotator]
-
-    _config_error_message: str = "InstallationStore with client_id/client_secret are required for token rotation"
-
-    def __init__(
-        self,
-        *,
-        logger: Logger,
-        installation_store: InstallationStore,
-        client_id: Optional[str] = None,
-        client_secret: Optional[str] = None,
-        token_rotation_expiration_minutes: Optional[int] = None,
-        # For v1.0.x compatibility and people who still want its simplicity
-        # use only InstallationStore#find_bot(enterprise_id, team_id)
-        bot_only: bool = False,
-        cache_enabled: bool = False,
-        client: Optional[WebClient] = None,
-        # Since v1.27, user token resolution can be actor ID based when the mode is enabled
-        user_token_resolution: str = "authed_user",
-    ):
-        self.logger = logger
-        self.installation_store = installation_store
-        self.bot_only = bot_only
-        self.user_token_resolution = user_token_resolution
-        self.cache_enabled = cache_enabled
-        self.authorize_result_cache = {}
-        self.find_installation_available = hasattr(installation_store, "find_installation")
-        self.find_bot_available = hasattr(installation_store, "find_bot")
-        if client_id is not None and client_secret is not None:
-            self.token_rotator = TokenRotator(
-                client_id=client_id,
-                client_secret=client_secret,
-                client=client,
-            )
-        else:
-            self.token_rotator = None
-        self.token_rotation_expiration_minutes = token_rotation_expiration_minutes or 120
-
-    def __call__(
-        self,
-        *,
-        context: BoltContext,
-        enterprise_id: Optional[str],
-        team_id: Optional[str],  # can be None for org-wide installed apps
-        user_id: Optional[str],
-        # actor_* can be used only when user_token_resolution: "actor" is set
-        actor_enterprise_id: Optional[str] = None,
-        actor_team_id: Optional[str] = None,
-        actor_user_id: Optional[str] = None,
-    ) -> Optional[AuthorizeResult]:
-
-        bot_token: Optional[str] = None
-        user_token: Optional[str] = None
-        bot_scopes: Optional[Sequence[str]] = None
-        user_scopes: Optional[Sequence[str]] = None
-        latest_bot_installation: Optional[Installation] = None
-        this_user_installation: Optional[Installation] = None
-
-        if not self.bot_only and self.find_installation_available:
-            # Since v1.1, this is the default way.
-            # If you want to use find_bot / delete_bot only, you can set bot_only as True.
-            try:
-                # Note that this is the latest information for the org/workspace.
-                # The installer may not be the user associated with this incoming request.
-                latest_bot_installation = self.installation_store.find_installation(
-                    enterprise_id=enterprise_id,
-                    team_id=team_id,
-                    is_enterprise_install=context.is_enterprise_install,
-                )
-                # If the user_token in the latest_installation is not for the user associated with this request,
-                # we'll fetch a different installation for the user below.
-                # The example use cases are:
-                # - The app's installation requires both bot and user tokens
-                # - The app has two installation paths 1) bot installation 2) individual user authorization
-                if latest_bot_installation is not None:
-                    # Save the latest bot token
-                    bot_token = latest_bot_installation.bot_token  # this still can be None
-                    user_token = latest_bot_installation.user_token  # this still can be None
-                    bot_scopes = latest_bot_installation.bot_scopes  # this still can be None
-                    user_scopes = latest_bot_installation.user_scopes  # this still can be None
-
-                    if latest_bot_installation.user_id != user_id:
-                        # First off, remove the user token as the installer is a different user
-                        user_token = None
-                        user_scopes = None
-                        latest_bot_installation.user_token = None
-                        latest_bot_installation.user_refresh_token = None
-                        latest_bot_installation.user_token_expires_at = None
-                        latest_bot_installation.user_scopes = None
-
-                        # try to fetch the request user's installation
-                        # to reflect the user's access token if exists
-                        if self.user_token_resolution == "actor":
-                            if actor_enterprise_id is not None or actor_team_id is not None:
-                                # Note that actor_team_id can be absent for app_mention events
-                                this_user_installation = self.installation_store.find_installation(
-                                    enterprise_id=actor_enterprise_id,
-                                    team_id=actor_team_id,
-                                    user_id=actor_user_id,
-                                    is_enterprise_install=None,
-                                )
-                        else:
-                            this_user_installation = self.installation_store.find_installation(
-                                enterprise_id=enterprise_id,
-                                team_id=team_id,
-                                user_id=user_id,
-                                is_enterprise_install=context.is_enterprise_install,
-                            )
-                        if this_user_installation is not None:
-                            user_token = this_user_installation.user_token
-                            user_scopes = this_user_installation.user_scopes
-                            if (
-                                latest_bot_installation.bot_token is None
-                                # enterprise_id/team_id can be different for Slack Connect channel events
-                                # when enabling user_token_resolution: "actor"
-                                and latest_bot_installation.enterprise_id == this_user_installation.enterprise_id
-                                and latest_bot_installation.team_id == this_user_installation.team_id
-                            ):
-                                # If latest_installation has a bot token, we never overwrite the value
-                                bot_token = this_user_installation.bot_token
-                                bot_scopes = this_user_installation.bot_scopes
-
-                            # If token rotation is enabled, running rotation may be needed here
-                            refreshed = self._rotate_and_save_tokens_if_necessary(this_user_installation)
-                            if refreshed is not None:
-                                user_token = refreshed.user_token
-                                user_scopes = refreshed.user_scopes
-                                if (
-                                    latest_bot_installation.bot_token is None
-                                    # enterprise_id/team_id can be different for Slack Connect channel events
-                                    # when enabling user_token_resolution: "actor"
-                                    and latest_bot_installation.enterprise_id == this_user_installation.enterprise_id
-                                    and latest_bot_installation.team_id == this_user_installation.team_id
-                                ):
-                                    # If latest_installation has a bot token, we never overwrite the value
-                                    bot_token = refreshed.bot_token
-                                    bot_scopes = refreshed.bot_scopes
-
-                    # If token rotation is enabled, running rotation may be needed here
-                    refreshed = self._rotate_and_save_tokens_if_necessary(latest_bot_installation)
-                    if refreshed is not None:
-                        bot_token = refreshed.bot_token
-                        bot_scopes = refreshed.bot_scopes
-                        if this_user_installation is None:
-                            # Only when we don't have `this_user_installation` here,
-                            # the `user_token` is for the user associated with this request
-                            user_token = refreshed.user_token
-                            user_scopes = refreshed.user_scopes
-
-            except SlackTokenRotationError as rotation_error:
-                # When token rotation fails, it is usually unrecoverable
-                # So, this built-in middleware gives up continuing with the following middleware and listeners
-                self.logger.error(f"Failed to rotate tokens due to {rotation_error}")
-                return None
-            except NotImplementedError as _:
-                self.find_installation_available = False
-
-        if (
-            # If you intentionally use only `find_bot` / `delete_bot`,
-            self.bot_only
-            # If the `find_installation` method is not available,
-            or not self.find_installation_available
-            # If the `find_installation` method did not return data and find_bot method is available,
-            or (self.find_bot_available is True and bot_token is None and user_token is None)
-        ):
-            try:
-                bot: Optional[Bot] = self.installation_store.find_bot(
-                    enterprise_id=enterprise_id,
-                    team_id=team_id,
-                    is_enterprise_install=context.is_enterprise_install,
-                )
-                if bot is not None:
-                    bot_token = bot.bot_token
-                    bot_scopes = bot.bot_scopes
-                    if bot.bot_refresh_token is not None:
-                        # Token rotation
-                        if self.token_rotator is None:
-                            raise BoltError(self._config_error_message)
-                        refreshed_bot = self.token_rotator.perform_bot_token_rotation(
-                            bot=bot,
-                            minutes_before_expiration=self.token_rotation_expiration_minutes,
-                        )
-                        if refreshed_bot is not None:
-                            self.installation_store.save_bot(refreshed_bot)
-                            bot_token = refreshed_bot.bot_token
-                            bot_scopes = refreshed_bot.bot_scopes
-
-            except SlackTokenRotationError as rotation_error:
-                # When token rotation fails, it is usually unrecoverable
-                # So, this built-in middleware gives up continuing with the following middleware and listeners
-                self.logger.error(f"Failed to rotate tokens due to {rotation_error}")
-                return None
-            except NotImplementedError as _:
-                self.find_bot_available = False
-            except Exception as e:
-                self.logger.info(f"Failed to call find_bot method: {e}")
-
-        token: Optional[str] = bot_token or user_token
-        if token is None:
-            # No valid token was found
-            self._debug_log_for_not_found(enterprise_id, team_id)
-            return None
-
-        # Check cache to see if the bot object already exists
-        if self.cache_enabled and token in self.authorize_result_cache:
-            return self.authorize_result_cache[token]
-
-        try:
-            auth_test_api_response = context.client.auth_test(token=token)
-            user_auth_test_response = None
-            if user_token is not None and token != user_token:
-                user_auth_test_response = context.client.auth_test(token=user_token)
-            authorize_result = AuthorizeResult.from_auth_test_response(
-                auth_test_response=auth_test_api_response,
-                user_auth_test_response=user_auth_test_response,
-                bot_token=bot_token,
-                user_token=user_token,
-                bot_scopes=bot_scopes,
-                user_scopes=user_scopes,
-            )
-            if self.cache_enabled:
-                self.authorize_result_cache[token] = authorize_result
-            return authorize_result
-        except SlackApiError as err:
-            self.logger.debug(
-                f"The stored bot token for enterprise_id: {enterprise_id} team_id: {team_id} "
-                f"is no longer valid. (response: {err.response})"
-            )
-            return None
-
-    # ------------------------------------------------
-
-    def _debug_log_for_not_found(self, enterprise_id: Optional[str], team_id: Optional[str]):
-        self.logger.debug("No installation data found " f"for enterprise_id: {enterprise_id} team_id: {team_id}")
-
-    def _rotate_and_save_tokens_if_necessary(self, installation: Optional[Installation]) -> Optional[Installation]:
-        if installation is None or (installation.user_refresh_token is None and installation.bot_refresh_token is None):
-            # No need to rotate tokens
-            return None
-
-        if self.token_rotator is None:
-            # Token rotation is required but this Bolt app is not properly configured
-            raise BoltError(self._config_error_message)
-
-        refreshed: Optional[Installation] = self.token_rotator.perform_token_rotation(
-            installation=installation,
-            minutes_before_expiration=self.token_rotation_expiration_minutes,
-        )
-        if refreshed is not None:
-            # Save the refreshed data in database for following requests
-            self.installation_store.save(refreshed)
-        return refreshed
-
-

If you use the OAuth flow settings, this authorize implementation will be used. -As long as your own InstallationStore (or the built-in ones) works as you expect, -you can expect that the authorize layer should work for you without any customization.

-

Ancestors

- -

Class variables

-
-
var authorize_result_cache : Dict[str, AuthorizeResult]
-
-

The type of the None singleton.

-
-
var bot_only : bool
-
-

The type of the None singleton.

-
-
var find_bot_available : bool
-
-

The type of the None singleton.

-
-
var find_installation_available : bool
-
-

The type of the None singleton.

-
-
var token_rotator : slack_sdk.oauth.token_rotation.rotator.TokenRotator | None
-
-

The type of the None singleton.

-
-
var user_token_resolution : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/authorization/authorize_args.html b/docs/reference/authorization/authorize_args.html deleted file mode 100644 index 78423fc40..000000000 --- a/docs/reference/authorization/authorize_args.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - -slack_bolt.authorization.authorize_args API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.authorization.authorize_args

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AuthorizeArgs -(*,
context: BoltContext,
enterprise_id: str | None,
team_id: str | None,
user_id: str | None)
-
-
-
- -Expand source code - -
class AuthorizeArgs:
-    context: BoltContext
-    logger: Logger
-    client: WebClient
-    enterprise_id: Optional[str]
-    team_id: Optional[str]
-    user_id: Optional[str]
-
-    def __init__(
-        self,
-        *,
-        context: BoltContext,
-        enterprise_id: Optional[str],
-        team_id: Optional[str],  # can be None for org-wide installed apps
-        user_id: Optional[str],
-    ):
-        """The full list of the arguments passed to `authorize` function.
-
-        Args:
-            context: The request context
-            enterprise_id: The Organization ID (Enterprise Grid)
-            team_id: The workspace ID
-            user_id: The request user ID
-        """
-        self.context = context
-        self.logger = context.logger
-        self.client = context.client
-        self.enterprise_id = enterprise_id
-        self.team_id = team_id
-        self.user_id = user_id
-
-

The full list of the arguments passed to authorize function.

-

Args

-
-
context
-
The request context
-
enterprise_id
-
The Organization ID (Enterprise Grid)
-
team_id
-
The workspace ID
-
user_id
-
The request user ID
-
-

Class variables

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var contextBoltContext
-
-

The type of the None singleton.

-
-
var enterprise_id : str | None
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
var team_id : str | None
-
-

The type of the None singleton.

-
-
var user_id : str | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/authorization/authorize_result.html b/docs/reference/authorization/authorize_result.html deleted file mode 100644 index d53c5cd5c..000000000 --- a/docs/reference/authorization/authorize_result.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - -slack_bolt.authorization.authorize_result API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.authorization.authorize_result

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AuthorizeResult -(*,
enterprise_id: str | None,
team_id: str | None,
team: str | None = None,
url: str | None = None,
bot_user_id: str | None = None,
bot_id: str | None = None,
bot_token: str | None = None,
bot_scopes: Sequence[str] | str | None = None,
user_id: str | None = None,
user: str | None = None,
user_token: str | None = None,
user_scopes: Sequence[str] | str | None = None)
-
-
-
- -Expand source code - -
class AuthorizeResult(dict):
-    """Authorize function call result"""
-
-    enterprise_id: Optional[str]
-    team_id: Optional[str]
-    team: Optional[str]  # since v1.18
-    url: Optional[str]  # since v1.18
-
-    bot_id: Optional[str]
-    bot_user_id: Optional[str]
-    bot_token: Optional[str]
-    bot_scopes: Optional[Sequence[str]]  # since v1.17
-
-    user_id: Optional[str]
-    user: Optional[str]  # since v1.18
-    user_token: Optional[str]
-    user_scopes: Optional[Sequence[str]]  # since v1.17
-
-    def __init__(
-        self,
-        *,
-        enterprise_id: Optional[str],
-        team_id: Optional[str],
-        team: Optional[str] = None,
-        url: Optional[str] = None,
-        # bot
-        bot_user_id: Optional[str] = None,
-        bot_id: Optional[str] = None,
-        bot_token: Optional[str] = None,
-        bot_scopes: Optional[Union[Sequence[str], str]] = None,
-        # user
-        user_id: Optional[str] = None,
-        user: Optional[str] = None,
-        user_token: Optional[str] = None,
-        user_scopes: Optional[Union[Sequence[str], str]] = None,
-    ):
-        """
-        Args:
-            enterprise_id: Organization ID (Enterprise Grid) starting with `E`
-            team_id: Workspace ID starting with `T`
-            team: Workspace name
-            url: Workspace slack.com URL
-            bot_user_id: Bot user's User ID starting with either `U` or `W`
-            bot_id: Bot ID starting with `B`
-            bot_token: Bot user access token starting with `xoxb-`
-            bot_scopes: The scopes associated with the bot token
-            user_id: The request user ID
-            user: The request user's name
-            user_token: User access token starting with `xoxp-`
-            user_scopes: The scopes associated wth the user token
-        """
-        self["enterprise_id"] = self.enterprise_id = enterprise_id
-        self["team_id"] = self.team_id = team_id
-        self["team"] = self.team = team
-        self["url"] = self.url = url
-        # bot
-        self["bot_user_id"] = self.bot_user_id = bot_user_id
-        self["bot_id"] = self.bot_id = bot_id
-        self["bot_token"] = self.bot_token = bot_token
-        if bot_scopes is not None and isinstance(bot_scopes, str):
-            bot_scopes = [scope.strip() for scope in bot_scopes.split(",")]
-        self["bot_scopes"] = self.bot_scopes = bot_scopes
-        # user
-        self["user_id"] = self.user_id = user_id
-        self["user"] = self.user = user
-        self["user_token"] = self.user_token = user_token
-        if user_scopes is not None and isinstance(user_scopes, str):
-            user_scopes = [scope.strip() for scope in user_scopes.split(",")]
-        self["user_scopes"] = self.user_scopes = user_scopes
-
-    @classmethod
-    def from_auth_test_response(
-        cls,
-        *,
-        bot_token: Optional[str] = None,
-        user_token: Optional[str] = None,
-        bot_scopes: Optional[Union[Sequence[str], str]] = None,
-        user_scopes: Optional[Union[Sequence[str], str]] = None,
-        auth_test_response: Union[SlackResponse, "AsyncSlackResponse"],  # type: ignore[name-defined]
-        user_auth_test_response: Optional[Union[SlackResponse, "AsyncSlackResponse"]] = None,  # type: ignore[name-defined]
-    ) -> "AuthorizeResult":
-        bot_user_id: Optional[str] = (
-            auth_test_response.get("user_id") if auth_test_response.get("bot_id") is not None else None
-        )
-        user_id: Optional[str] = auth_test_response.get("user_id") if auth_test_response.get("bot_id") is None else None
-        user_name: Optional[str] = auth_test_response.get("user")
-        if user_id is None and user_auth_test_response is not None:
-            user_id = user_auth_test_response.get("user_id")
-            user_name = user_auth_test_response.get("user")
-
-        return AuthorizeResult(
-            enterprise_id=auth_test_response.get("enterprise_id"),
-            team_id=auth_test_response.get("team_id"),
-            team=auth_test_response.get("team"),
-            url=auth_test_response.get("url"),
-            bot_id=auth_test_response.get("bot_id"),
-            bot_user_id=bot_user_id,
-            bot_scopes=bot_scopes,
-            user_id=user_id,
-            user=user_name,
-            bot_token=bot_token,
-            user_token=user_token,
-            user_scopes=user_scopes,
-        )
-
-

Authorize function call result

-

Args

-
-
enterprise_id
-
Organization ID (Enterprise Grid) starting with E
-
team_id
-
Workspace ID starting with T
-
team
-
Workspace name
-
url
-
Workspace slack.com URL
-
bot_user_id
-
Bot user's User ID starting with either U or W
-
bot_id
-
Bot ID starting with B
-
bot_token
-
Bot user access token starting with xoxb-
-
bot_scopes
-
The scopes associated with the bot token
-
user_id
-
The request user ID
-
user
-
The request user's name
-
user_token
-
User access token starting with xoxp-
-
user_scopes
-
The scopes associated wth the user token
-
-

Ancestors

-
    -
  • builtins.dict
  • -
-

Class variables

-
-
var bot_id : str | None
-
-

The type of the None singleton.

-
-
var bot_scopes : Sequence[str] | None
-
-

The type of the None singleton.

-
-
var bot_token : str | None
-
-

The type of the None singleton.

-
-
var bot_user_id : str | None
-
-

The type of the None singleton.

-
-
var enterprise_id : str | None
-
-

The type of the None singleton.

-
-
var team : str | None
-
-

The type of the None singleton.

-
-
var team_id : str | None
-
-

The type of the None singleton.

-
-
var url : str | None
-
-

The type of the None singleton.

-
-
var user : str | None
-
-

The type of the None singleton.

-
-
var user_id : str | None
-
-

The type of the None singleton.

-
-
var user_scopes : Sequence[str] | None
-
-

The type of the None singleton.

-
-
var user_token : str | None
-
-

The type of the None singleton.

-
-
-

Static methods

-
-
-def from_auth_test_response(*,
bot_token: str | None = None,
user_token: str | None = None,
bot_scopes: Sequence[str] | str | None = None,
user_scopes: Sequence[str] | str | None = None,
auth_test_response: slack_sdk.web.slack_response.SlackResponse | AsyncSlackResponse,
user_auth_test_response: slack_sdk.web.slack_response.SlackResponse | AsyncSlackResponse | None = None)
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/authorization/index.html b/docs/reference/authorization/index.html deleted file mode 100644 index 2fdd1f916..000000000 --- a/docs/reference/authorization/index.html +++ /dev/null @@ -1,334 +0,0 @@ - - - - - - -slack_bolt.authorization API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.authorization

-
-
-

Authorization is the process of determining which Slack credentials should be available -while processing an incoming Slack event.

-

Refer to https://docs.slack.dev/tools/bolt-python/concepts/authorization for details.

-
-
-

Sub-modules

-
-
slack_bolt.authorization.async_authorize
-
-
-
-
slack_bolt.authorization.async_authorize_args
-
-
-
-
slack_bolt.authorization.authorize
-
-
-
-
slack_bolt.authorization.authorize_args
-
-
-
-
slack_bolt.authorization.authorize_result
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AuthorizeResult -(*,
enterprise_id: str | None,
team_id: str | None,
team: str | None = None,
url: str | None = None,
bot_user_id: str | None = None,
bot_id: str | None = None,
bot_token: str | None = None,
bot_scopes: Sequence[str] | str | None = None,
user_id: str | None = None,
user: str | None = None,
user_token: str | None = None,
user_scopes: Sequence[str] | str | None = None)
-
-
-
- -Expand source code - -
class AuthorizeResult(dict):
-    """Authorize function call result"""
-
-    enterprise_id: Optional[str]
-    team_id: Optional[str]
-    team: Optional[str]  # since v1.18
-    url: Optional[str]  # since v1.18
-
-    bot_id: Optional[str]
-    bot_user_id: Optional[str]
-    bot_token: Optional[str]
-    bot_scopes: Optional[Sequence[str]]  # since v1.17
-
-    user_id: Optional[str]
-    user: Optional[str]  # since v1.18
-    user_token: Optional[str]
-    user_scopes: Optional[Sequence[str]]  # since v1.17
-
-    def __init__(
-        self,
-        *,
-        enterprise_id: Optional[str],
-        team_id: Optional[str],
-        team: Optional[str] = None,
-        url: Optional[str] = None,
-        # bot
-        bot_user_id: Optional[str] = None,
-        bot_id: Optional[str] = None,
-        bot_token: Optional[str] = None,
-        bot_scopes: Optional[Union[Sequence[str], str]] = None,
-        # user
-        user_id: Optional[str] = None,
-        user: Optional[str] = None,
-        user_token: Optional[str] = None,
-        user_scopes: Optional[Union[Sequence[str], str]] = None,
-    ):
-        """
-        Args:
-            enterprise_id: Organization ID (Enterprise Grid) starting with `E`
-            team_id: Workspace ID starting with `T`
-            team: Workspace name
-            url: Workspace slack.com URL
-            bot_user_id: Bot user's User ID starting with either `U` or `W`
-            bot_id: Bot ID starting with `B`
-            bot_token: Bot user access token starting with `xoxb-`
-            bot_scopes: The scopes associated with the bot token
-            user_id: The request user ID
-            user: The request user's name
-            user_token: User access token starting with `xoxp-`
-            user_scopes: The scopes associated wth the user token
-        """
-        self["enterprise_id"] = self.enterprise_id = enterprise_id
-        self["team_id"] = self.team_id = team_id
-        self["team"] = self.team = team
-        self["url"] = self.url = url
-        # bot
-        self["bot_user_id"] = self.bot_user_id = bot_user_id
-        self["bot_id"] = self.bot_id = bot_id
-        self["bot_token"] = self.bot_token = bot_token
-        if bot_scopes is not None and isinstance(bot_scopes, str):
-            bot_scopes = [scope.strip() for scope in bot_scopes.split(",")]
-        self["bot_scopes"] = self.bot_scopes = bot_scopes
-        # user
-        self["user_id"] = self.user_id = user_id
-        self["user"] = self.user = user
-        self["user_token"] = self.user_token = user_token
-        if user_scopes is not None and isinstance(user_scopes, str):
-            user_scopes = [scope.strip() for scope in user_scopes.split(",")]
-        self["user_scopes"] = self.user_scopes = user_scopes
-
-    @classmethod
-    def from_auth_test_response(
-        cls,
-        *,
-        bot_token: Optional[str] = None,
-        user_token: Optional[str] = None,
-        bot_scopes: Optional[Union[Sequence[str], str]] = None,
-        user_scopes: Optional[Union[Sequence[str], str]] = None,
-        auth_test_response: Union[SlackResponse, "AsyncSlackResponse"],  # type: ignore[name-defined]
-        user_auth_test_response: Optional[Union[SlackResponse, "AsyncSlackResponse"]] = None,  # type: ignore[name-defined]
-    ) -> "AuthorizeResult":
-        bot_user_id: Optional[str] = (
-            auth_test_response.get("user_id") if auth_test_response.get("bot_id") is not None else None
-        )
-        user_id: Optional[str] = auth_test_response.get("user_id") if auth_test_response.get("bot_id") is None else None
-        user_name: Optional[str] = auth_test_response.get("user")
-        if user_id is None and user_auth_test_response is not None:
-            user_id = user_auth_test_response.get("user_id")
-            user_name = user_auth_test_response.get("user")
-
-        return AuthorizeResult(
-            enterprise_id=auth_test_response.get("enterprise_id"),
-            team_id=auth_test_response.get("team_id"),
-            team=auth_test_response.get("team"),
-            url=auth_test_response.get("url"),
-            bot_id=auth_test_response.get("bot_id"),
-            bot_user_id=bot_user_id,
-            bot_scopes=bot_scopes,
-            user_id=user_id,
-            user=user_name,
-            bot_token=bot_token,
-            user_token=user_token,
-            user_scopes=user_scopes,
-        )
-
-

Authorize function call result

-

Args

-
-
enterprise_id
-
Organization ID (Enterprise Grid) starting with E
-
team_id
-
Workspace ID starting with T
-
team
-
Workspace name
-
url
-
Workspace slack.com URL
-
bot_user_id
-
Bot user's User ID starting with either U or W
-
bot_id
-
Bot ID starting with B
-
bot_token
-
Bot user access token starting with xoxb-
-
bot_scopes
-
The scopes associated with the bot token
-
user_id
-
The request user ID
-
user
-
The request user's name
-
user_token
-
User access token starting with xoxp-
-
user_scopes
-
The scopes associated wth the user token
-
-

Ancestors

-
    -
  • builtins.dict
  • -
-

Class variables

-
-
var bot_id : str | None
-
-

The type of the None singleton.

-
-
var bot_scopes : Sequence[str] | None
-
-

The type of the None singleton.

-
-
var bot_token : str | None
-
-

The type of the None singleton.

-
-
var bot_user_id : str | None
-
-

The type of the None singleton.

-
-
var enterprise_id : str | None
-
-

The type of the None singleton.

-
-
var team : str | None
-
-

The type of the None singleton.

-
-
var team_id : str | None
-
-

The type of the None singleton.

-
-
var url : str | None
-
-

The type of the None singleton.

-
-
var user : str | None
-
-

The type of the None singleton.

-
-
var user_id : str | None
-
-

The type of the None singleton.

-
-
var user_scopes : Sequence[str] | None
-
-

The type of the None singleton.

-
-
var user_token : str | None
-
-

The type of the None singleton.

-
-
-

Static methods

-
-
-def from_auth_test_response(*,
bot_token: str | None = None,
user_token: str | None = None,
bot_scopes: Sequence[str] | str | None = None,
user_scopes: Sequence[str] | str | None = None,
auth_test_response: slack_sdk.web.slack_response.SlackResponse | AsyncSlackResponse,
user_auth_test_response: slack_sdk.web.slack_response.SlackResponse | AsyncSlackResponse | None = None)
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/ack/ack.html b/docs/reference/context/ack/ack.html deleted file mode 100644 index a8b808d86..000000000 --- a/docs/reference/context/ack/ack.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - -slack_bolt.context.ack.ack API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.ack.ack

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Ack -
-
-
- -Expand source code - -
class Ack:
-    response: Optional[BoltResponse]
-
-    def __init__(self):
-        self.response: Optional[BoltResponse] = None
-
-    def __call__(
-        self,
-        text: Union[str, dict] = "",  # text: str or whole_response: dict
-        blocks: Optional[Sequence[Union[dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[dict, Attachment]]] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        response_type: Optional[str] = None,  # in_channel / ephemeral
-        # block_suggestion / dialog_suggestion
-        options: Optional[Sequence[Union[dict, Option]]] = None,
-        option_groups: Optional[Sequence[Union[dict, OptionGroup]]] = None,
-        # view_submission
-        response_action: Optional[str] = None,  # errors / update / push / clear
-        errors: Optional[Dict[str, str]] = None,
-        view: Optional[Union[dict, View]] = None,
-    ) -> BoltResponse:
-        return _set_response(
-            self,
-            text_or_whole_response=text,
-            blocks=blocks,
-            attachments=attachments,
-            unfurl_links=unfurl_links,
-            unfurl_media=unfurl_media,
-            response_type=response_type,
-            options=options,
-            option_groups=option_groups,
-            response_action=response_action,
-            errors=errors,
-            view=view,
-        )
-
-
-

Class variables

-
-
var responseBoltResponse | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/ack/async_ack.html b/docs/reference/context/ack/async_ack.html deleted file mode 100644 index f744d5693..000000000 --- a/docs/reference/context/ack/async_ack.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - -slack_bolt.context.ack.async_ack API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.ack.async_ack

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncAck -
-
-
- -Expand source code - -
class AsyncAck:
-    response: Optional[BoltResponse]
-
-    def __init__(self):
-        self.response: Optional[BoltResponse] = None
-
-    async def __call__(
-        self,
-        text: Union[str, dict] = "",  # text: str or whole_response: dict
-        blocks: Optional[Sequence[Union[dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[dict, Attachment]]] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        response_type: Optional[str] = None,  # in_channel / ephemeral
-        # block_suggestion / dialog_suggestion
-        options: Optional[Sequence[Union[dict, Option]]] = None,
-        option_groups: Optional[Sequence[Union[dict, OptionGroup]]] = None,
-        # view_submission
-        response_action: Optional[str] = None,  # errors / update / push / clear
-        errors: Optional[Dict[str, str]] = None,
-        view: Optional[Union[dict, View]] = None,
-    ) -> BoltResponse:
-        return _set_response(
-            self,
-            text_or_whole_response=text,
-            blocks=blocks,
-            attachments=attachments,
-            unfurl_links=unfurl_links,
-            unfurl_media=unfurl_media,
-            response_type=response_type,
-            options=options,
-            option_groups=option_groups,
-            response_action=response_action,
-            errors=errors,
-            view=view,
-        )
-
-
-

Class variables

-
-
var responseBoltResponse | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/ack/index.html b/docs/reference/context/ack/index.html deleted file mode 100644 index 89f0600e8..000000000 --- a/docs/reference/context/ack/index.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - -slack_bolt.context.ack API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.ack

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.ack.ack
-
-
-
-
slack_bolt.context.ack.async_ack
-
-
-
-
slack_bolt.context.ack.internals
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Ack -
-
-
- -Expand source code - -
class Ack:
-    response: Optional[BoltResponse]
-
-    def __init__(self):
-        self.response: Optional[BoltResponse] = None
-
-    def __call__(
-        self,
-        text: Union[str, dict] = "",  # text: str or whole_response: dict
-        blocks: Optional[Sequence[Union[dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[dict, Attachment]]] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        response_type: Optional[str] = None,  # in_channel / ephemeral
-        # block_suggestion / dialog_suggestion
-        options: Optional[Sequence[Union[dict, Option]]] = None,
-        option_groups: Optional[Sequence[Union[dict, OptionGroup]]] = None,
-        # view_submission
-        response_action: Optional[str] = None,  # errors / update / push / clear
-        errors: Optional[Dict[str, str]] = None,
-        view: Optional[Union[dict, View]] = None,
-    ) -> BoltResponse:
-        return _set_response(
-            self,
-            text_or_whole_response=text,
-            blocks=blocks,
-            attachments=attachments,
-            unfurl_links=unfurl_links,
-            unfurl_media=unfurl_media,
-            response_type=response_type,
-            options=options,
-            option_groups=option_groups,
-            response_action=response_action,
-            errors=errors,
-            view=view,
-        )
-
-
-

Class variables

-
-
var responseBoltResponse | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/ack/internals.html b/docs/reference/context/ack/internals.html deleted file mode 100644 index f7f776241..000000000 --- a/docs/reference/context/ack/internals.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - -slack_bolt.context.ack.internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.ack.internals

-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/assistant/assistant_utilities.html b/docs/reference/context/assistant/assistant_utilities.html deleted file mode 100644 index 2200c4f10..000000000 --- a/docs/reference/context/assistant/assistant_utilities.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - -slack_bolt.context.assistant.assistant_utilities API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.assistant.assistant_utilities

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AssistantUtilities -(*,
payload: dict,
context: BoltContext,
thread_context_store: AssistantThreadContextStore | None = None)
-
-
-
- -Expand source code - -
class AssistantUtilities:
-    payload: dict
-    client: WebClient
-    channel_id: str
-    thread_ts: str
-    thread_context_store: AssistantThreadContextStore
-
-    def __init__(
-        self,
-        *,
-        payload: dict,
-        context: BoltContext,
-        thread_context_store: Optional[AssistantThreadContextStore] = None,
-    ):
-        self.payload = payload
-        self.client = context.client
-        self.thread_context_store = thread_context_store or DefaultAssistantThreadContextStore(context)
-
-        if has_channel_id_and_thread_ts(self.payload):
-            # assistant_thread_started
-            thread = self.payload["assistant_thread"]
-            self.channel_id = thread["channel_id"]
-            self.thread_ts = thread["thread_ts"]
-        elif self.payload.get("channel") is not None and self.payload.get("thread_ts") is not None:
-            # message event
-            self.channel_id = self.payload["channel"]
-            self.thread_ts = self.payload["thread_ts"]
-        else:
-            # When moving this code to Bolt internals, no need to raise an exception for this pattern
-            raise ValueError(f"Cannot instantiate Assistant for this event pattern ({self.payload})")
-
-    @property
-    def set_title(self) -> SetTitle:
-        return SetTitle(self.client, self.channel_id, self.thread_ts)
-
-    @property
-    def say(self) -> Say:
-        def build_metadata() -> Optional[dict]:
-            thread_context = self.get_thread_context()
-            if thread_context is not None:
-                return {"event_type": "assistant_thread_context", "event_payload": thread_context}
-            return None
-
-        return Say(
-            self.client,
-            channel=self.channel_id,
-            thread_ts=self.thread_ts,
-            build_metadata=build_metadata,
-        )
-
-    @property
-    def get_thread_context(self) -> GetThreadContext:
-        return GetThreadContext(self.thread_context_store, self.channel_id, self.thread_ts, self.payload)
-
-    @property
-    def save_thread_context(self) -> SaveThreadContext:
-        return SaveThreadContext(self.thread_context_store, self.channel_id, self.thread_ts)
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var payload : dict
-
-

The type of the None singleton.

-
-
var thread_context_storeAssistantThreadContextStore
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-

Instance variables

-
-
prop get_thread_contextGetThreadContext
-
-
- -Expand source code - -
@property
-def get_thread_context(self) -> GetThreadContext:
-    return GetThreadContext(self.thread_context_store, self.channel_id, self.thread_ts, self.payload)
-
-
-
-
prop save_thread_contextSaveThreadContext
-
-
- -Expand source code - -
@property
-def save_thread_context(self) -> SaveThreadContext:
-    return SaveThreadContext(self.thread_context_store, self.channel_id, self.thread_ts)
-
-
-
-
prop saySay
-
-
- -Expand source code - -
@property
-def say(self) -> Say:
-    def build_metadata() -> Optional[dict]:
-        thread_context = self.get_thread_context()
-        if thread_context is not None:
-            return {"event_type": "assistant_thread_context", "event_payload": thread_context}
-        return None
-
-    return Say(
-        self.client,
-        channel=self.channel_id,
-        thread_ts=self.thread_ts,
-        build_metadata=build_metadata,
-    )
-
-
-
-
prop set_titleSetTitle
-
-
- -Expand source code - -
@property
-def set_title(self) -> SetTitle:
-    return SetTitle(self.client, self.channel_id, self.thread_ts)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/assistant/async_assistant_utilities.html b/docs/reference/context/assistant/async_assistant_utilities.html deleted file mode 100644 index 70f4d0d23..000000000 --- a/docs/reference/context/assistant/async_assistant_utilities.html +++ /dev/null @@ -1,235 +0,0 @@ - - - - - - -slack_bolt.context.assistant.async_assistant_utilities API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.assistant.async_assistant_utilities

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncAssistantUtilities -(*,
payload: dict,
context: AsyncBoltContext,
thread_context_store: AsyncAssistantThreadContextStore | None = None)
-
-
-
- -Expand source code - -
class AsyncAssistantUtilities:
-    payload: dict
-    client: AsyncWebClient
-    channel_id: str
-    thread_ts: str
-    thread_context_store: AsyncAssistantThreadContextStore
-
-    def __init__(
-        self,
-        *,
-        payload: dict,
-        context: AsyncBoltContext,
-        thread_context_store: Optional[AsyncAssistantThreadContextStore] = None,
-    ):
-        self.payload = payload
-        self.client = context.client
-        self.thread_context_store = thread_context_store or DefaultAsyncAssistantThreadContextStore(context)
-
-        if has_channel_id_and_thread_ts(self.payload):
-            # assistant_thread_started
-            thread = self.payload["assistant_thread"]
-            self.channel_id = thread["channel_id"]
-            self.thread_ts = thread["thread_ts"]
-        elif self.payload.get("channel") is not None and self.payload.get("thread_ts") is not None:
-            # message event
-            self.channel_id = self.payload["channel"]
-            self.thread_ts = self.payload["thread_ts"]
-        else:
-            # When moving this code to Bolt internals, no need to raise an exception for this pattern
-            raise ValueError(f"Cannot instantiate Assistant for this event pattern ({self.payload})")
-
-    @property
-    def set_title(self) -> AsyncSetTitle:
-        return AsyncSetTitle(self.client, self.channel_id, self.thread_ts)
-
-    @property
-    def say(self) -> AsyncSay:
-        return AsyncSay(
-            self.client,
-            channel=self.channel_id,
-            thread_ts=self.thread_ts,
-            build_metadata=self._build_message_metadata,
-        )
-
-    async def _build_message_metadata(self) -> dict:
-        return {
-            "event_type": "assistant_thread_context",
-            "event_payload": await self.get_thread_context(),
-        }
-
-    @property
-    def get_thread_context(self) -> AsyncGetThreadContext:
-        return AsyncGetThreadContext(self.thread_context_store, self.channel_id, self.thread_ts, self.payload)
-
-    @property
-    def save_thread_context(self) -> AsyncSaveThreadContext:
-        return AsyncSaveThreadContext(self.thread_context_store, self.channel_id, self.thread_ts)
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var payload : dict
-
-

The type of the None singleton.

-
-
var thread_context_storeAsyncAssistantThreadContextStore
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-

Instance variables

-
-
prop get_thread_contextAsyncGetThreadContext
-
-
- -Expand source code - -
@property
-def get_thread_context(self) -> AsyncGetThreadContext:
-    return AsyncGetThreadContext(self.thread_context_store, self.channel_id, self.thread_ts, self.payload)
-
-
-
-
prop save_thread_contextAsyncSaveThreadContext
-
-
- -Expand source code - -
@property
-def save_thread_context(self) -> AsyncSaveThreadContext:
-    return AsyncSaveThreadContext(self.thread_context_store, self.channel_id, self.thread_ts)
-
-
-
-
prop sayAsyncSay
-
-
- -Expand source code - -
@property
-def say(self) -> AsyncSay:
-    return AsyncSay(
-        self.client,
-        channel=self.channel_id,
-        thread_ts=self.thread_ts,
-        build_metadata=self._build_message_metadata,
-    )
-
-
-
-
prop set_titleAsyncSetTitle
-
-
- -Expand source code - -
@property
-def set_title(self) -> AsyncSetTitle:
-    return AsyncSetTitle(self.client, self.channel_id, self.thread_ts)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/assistant/index.html b/docs/reference/context/assistant/index.html deleted file mode 100644 index d442e26cf..000000000 --- a/docs/reference/context/assistant/index.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - -slack_bolt.context.assistant API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.assistant

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.assistant.assistant_utilities
-
-
-
-
slack_bolt.context.assistant.async_assistant_utilities
-
-
-
-
slack_bolt.context.assistant.internals
-
-
-
-
slack_bolt.context.assistant.thread_context
-
-
-
-
slack_bolt.context.assistant.thread_context_store
-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/assistant/internals.html b/docs/reference/context/assistant/internals.html deleted file mode 100644 index 242bd6f19..000000000 --- a/docs/reference/context/assistant/internals.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - -slack_bolt.context.assistant.internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.assistant.internals

-
-
-
-
-
-
-
-
-

Functions

-
-
-def has_channel_id_and_thread_ts(payload: dict) ‑> bool -
-
-
- -Expand source code - -
def has_channel_id_and_thread_ts(payload: dict) -> bool:
-    """Verifies if the given payload has both channel_id and thread_ts under assistant_thread property.
-    This data pattern is available for assistant_* events.
-    """
-    return (
-        payload.get("assistant_thread") is not None
-        and payload["assistant_thread"].get("channel_id") is not None
-        and payload["assistant_thread"].get("thread_ts") is not None
-    )
-
-

Verifies if the given payload has both channel_id and thread_ts under assistant_thread property. -This data pattern is available for assistant_* events.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/assistant/thread_context/index.html b/docs/reference/context/assistant/thread_context/index.html deleted file mode 100644 index f3767a1cf..000000000 --- a/docs/reference/context/assistant/thread_context/index.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - -slack_bolt.context.assistant.thread_context API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.assistant.thread_context

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AssistantThreadContext -(payload: dict) -
-
-
- -Expand source code - -
class AssistantThreadContext(dict):
-    enterprise_id: Optional[str]
-    team_id: Optional[str]
-    channel_id: str
-
-    def __init__(self, payload: dict):
-        dict.__init__(self, **payload)
-        self.enterprise_id = payload.get("enterprise_id")
-        self.team_id = payload.get("team_id")
-        self.channel_id = payload["channel_id"]
-
-

dict() -> new empty dictionary -dict(mapping) -> new dictionary initialized from a mapping object's -(key, value) pairs -dict(iterable) -> new dictionary initialized as if via: -d = {} -for k, v in iterable: -d[k] = v -dict(**kwargs) -> new dictionary initialized with the name=value pairs -in the keyword argument list. -For example: -dict(one=1, two=2)

-

Ancestors

-
    -
  • builtins.dict
  • -
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var enterprise_id : str | None
-
-

The type of the None singleton.

-
-
var team_id : str | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/assistant/thread_context_store/async_store.html b/docs/reference/context/assistant/thread_context_store/async_store.html deleted file mode 100644 index 64f4e53ed..000000000 --- a/docs/reference/context/assistant/thread_context_store/async_store.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - -slack_bolt.context.assistant.thread_context_store.async_store API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.assistant.thread_context_store.async_store

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncAssistantThreadContextStore -
-
-
- -Expand source code - -
class AsyncAssistantThreadContextStore:
-    async def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-        raise NotImplementedError()
-
-    async def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-async def find(self, *, channel_id: str, thread_ts: str) ‑> AssistantThreadContext | None -
-
-
- -Expand source code - -
async def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-    raise NotImplementedError()
-
-
-
-
-async def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) ‑> None -
-
-
- -Expand source code - -
async def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-    raise NotImplementedError()
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/assistant/thread_context_store/default_async_store.html b/docs/reference/context/assistant/thread_context_store/default_async_store.html deleted file mode 100644 index f6cd66060..000000000 --- a/docs/reference/context/assistant/thread_context_store/default_async_store.html +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - -slack_bolt.context.assistant.thread_context_store.default_async_store API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.assistant.thread_context_store.default_async_store

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class DefaultAsyncAssistantThreadContextStore -(context: AsyncBoltContext) -
-
-
- -Expand source code - -
class DefaultAsyncAssistantThreadContextStore(AsyncAssistantThreadContextStore):
-    client: AsyncWebClient
-    context: AsyncBoltContext
-
-    def __init__(self, context: AsyncBoltContext):
-        self.client = context.client
-        self.context = context
-
-    async def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-        parent_message = await self._retrieve_first_bot_reply(channel_id, thread_ts)
-        if parent_message is not None:
-            await self.client.chat_update(
-                channel=channel_id,
-                ts=parent_message["ts"],
-                text=parent_message["text"],
-                blocks=parent_message["blocks"],
-                metadata={
-                    "event_type": "assistant_thread_context",
-                    "event_payload": context,
-                },
-            )
-
-    async def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-        parent_message = await self._retrieve_first_bot_reply(channel_id, thread_ts)
-        if parent_message is not None and parent_message.get("metadata"):
-            if bool(parent_message["metadata"]["event_payload"]):
-                return AssistantThreadContext(parent_message["metadata"]["event_payload"])
-        return None
-
-    async def _retrieve_first_bot_reply(self, channel_id: str, thread_ts: str) -> Optional[dict]:
-        messages: List[dict] = (
-            await self.client.conversations_replies(
-                channel=channel_id,
-                ts=thread_ts,
-                oldest=thread_ts,
-                include_all_metadata=True,
-                limit=4,  # 2 should be usually enough but buffer for more robustness
-            )
-        ).get("messages", [])
-        for message in messages:
-            if message.get("subtype") is None and message.get("user") == self.context.bot_user_id:
-                return message
-        return None
-
-
-

Ancestors

- -

Class variables

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var contextAsyncBoltContext
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-async def find(self, *, channel_id: str, thread_ts: str) ‑> AssistantThreadContext | None -
-
-
- -Expand source code - -
async def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-    parent_message = await self._retrieve_first_bot_reply(channel_id, thread_ts)
-    if parent_message is not None and parent_message.get("metadata"):
-        if bool(parent_message["metadata"]["event_payload"]):
-            return AssistantThreadContext(parent_message["metadata"]["event_payload"])
-    return None
-
-
-
-
-async def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) ‑> None -
-
-
- -Expand source code - -
async def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-    parent_message = await self._retrieve_first_bot_reply(channel_id, thread_ts)
-    if parent_message is not None:
-        await self.client.chat_update(
-            channel=channel_id,
-            ts=parent_message["ts"],
-            text=parent_message["text"],
-            blocks=parent_message["blocks"],
-            metadata={
-                "event_type": "assistant_thread_context",
-                "event_payload": context,
-            },
-        )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/assistant/thread_context_store/default_store.html b/docs/reference/context/assistant/thread_context_store/default_store.html deleted file mode 100644 index 1594c5d38..000000000 --- a/docs/reference/context/assistant/thread_context_store/default_store.html +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - -slack_bolt.context.assistant.thread_context_store.default_store API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.assistant.thread_context_store.default_store

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class DefaultAssistantThreadContextStore -(context: BoltContext) -
-
-
- -Expand source code - -
class DefaultAssistantThreadContextStore(AssistantThreadContextStore):
-    client: WebClient
-    context: "BoltContext"
-
-    def __init__(self, context: BoltContext):
-        self.client = context.client
-        self.context = context
-
-    def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-        parent_message = self._retrieve_first_bot_reply(channel_id, thread_ts)
-        if parent_message is not None:
-            self.client.chat_update(
-                channel=channel_id,
-                ts=parent_message["ts"],
-                text=parent_message["text"],
-                blocks=parent_message["blocks"],
-                metadata={
-                    "event_type": "assistant_thread_context",
-                    "event_payload": context,
-                },
-            )
-
-    def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-        parent_message = self._retrieve_first_bot_reply(channel_id, thread_ts)
-        if parent_message is not None and parent_message.get("metadata"):
-            if bool(parent_message["metadata"]["event_payload"]):
-                return AssistantThreadContext(parent_message["metadata"]["event_payload"])
-        return None
-
-    def _retrieve_first_bot_reply(self, channel_id: str, thread_ts: str) -> Optional[dict]:
-        messages: List[dict] = self.client.conversations_replies(
-            channel=channel_id,
-            ts=thread_ts,
-            oldest=thread_ts,
-            include_all_metadata=True,
-            limit=4,  # 2 should be usually enough but buffer for more robustness
-        ).get("messages", [])
-        for message in messages:
-            if message.get("subtype") is None and message.get("user") == self.context.bot_user_id:
-                return message
-        return None
-
-
-

Ancestors

- -

Class variables

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var contextBoltContext
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def find(self, *, channel_id: str, thread_ts: str) ‑> AssistantThreadContext | None -
-
-
- -Expand source code - -
def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-    parent_message = self._retrieve_first_bot_reply(channel_id, thread_ts)
-    if parent_message is not None and parent_message.get("metadata"):
-        if bool(parent_message["metadata"]["event_payload"]):
-            return AssistantThreadContext(parent_message["metadata"]["event_payload"])
-    return None
-
-
-
-
-def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) ‑> None -
-
-
- -Expand source code - -
def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-    parent_message = self._retrieve_first_bot_reply(channel_id, thread_ts)
-    if parent_message is not None:
-        self.client.chat_update(
-            channel=channel_id,
-            ts=parent_message["ts"],
-            text=parent_message["text"],
-            blocks=parent_message["blocks"],
-            metadata={
-                "event_type": "assistant_thread_context",
-                "event_payload": context,
-            },
-        )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/assistant/thread_context_store/file/index.html b/docs/reference/context/assistant/thread_context_store/file/index.html deleted file mode 100644 index 4a5d944e1..000000000 --- a/docs/reference/context/assistant/thread_context_store/file/index.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - -slack_bolt.context.assistant.thread_context_store.file API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.assistant.thread_context_store.file

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class FileAssistantThreadContextStore -(base_dir: str = '/Users/wbergamin/.bolt-app-assistant-thread-contexts') -
-
-
- -Expand source code - -
class FileAssistantThreadContextStore(AssistantThreadContextStore):
-
-    def __init__(
-        self,
-        base_dir: str = str(Path.home()) + "/.bolt-app-assistant-thread-contexts",
-    ):
-        self.base_dir = base_dir
-        self._mkdir(self.base_dir)
-
-    def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-        path = f"{self.base_dir}/{channel_id}-{thread_ts}.json"
-        with open(path, "w") as f:
-            f.write(json.dumps(context))
-
-    def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-        path = f"{self.base_dir}/{channel_id}-{thread_ts}.json"
-        try:
-            with open(path) as f:
-                data = json.loads(f.read())
-                if data.get("channel_id") is not None:
-                    return AssistantThreadContext(data)
-        except FileNotFoundError:
-            pass
-        return None
-
-    @staticmethod
-    def _mkdir(path: Union[str, Path]):
-        if isinstance(path, str):
-            path = Path(path)
-        path.mkdir(parents=True, exist_ok=True)
-
-
-

Ancestors

- -

Methods

-
-
-def find(self, *, channel_id: str, thread_ts: str) ‑> AssistantThreadContext | None -
-
-
- -Expand source code - -
def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-    path = f"{self.base_dir}/{channel_id}-{thread_ts}.json"
-    try:
-        with open(path) as f:
-            data = json.loads(f.read())
-            if data.get("channel_id") is not None:
-                return AssistantThreadContext(data)
-    except FileNotFoundError:
-        pass
-    return None
-
-
-
-
-def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) ‑> None -
-
-
- -Expand source code - -
def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-    path = f"{self.base_dir}/{channel_id}-{thread_ts}.json"
-    with open(path, "w") as f:
-        f.write(json.dumps(context))
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/assistant/thread_context_store/index.html b/docs/reference/context/assistant/thread_context_store/index.html deleted file mode 100644 index 3083275d9..000000000 --- a/docs/reference/context/assistant/thread_context_store/index.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - -slack_bolt.context.assistant.thread_context_store API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.assistant.thread_context_store

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.assistant.thread_context_store.async_store
-
-
-
-
slack_bolt.context.assistant.thread_context_store.default_async_store
-
-
-
-
slack_bolt.context.assistant.thread_context_store.default_store
-
-
-
-
slack_bolt.context.assistant.thread_context_store.file
-
-
-
-
slack_bolt.context.assistant.thread_context_store.store
-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/assistant/thread_context_store/store.html b/docs/reference/context/assistant/thread_context_store/store.html deleted file mode 100644 index a0a177b09..000000000 --- a/docs/reference/context/assistant/thread_context_store/store.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - -slack_bolt.context.assistant.thread_context_store.store API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.assistant.thread_context_store.store

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AssistantThreadContextStore -
-
-
- -Expand source code - -
class AssistantThreadContextStore:
-    def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-        raise NotImplementedError()
-
-    def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-def find(self, *, channel_id: str, thread_ts: str) ‑> AssistantThreadContext | None -
-
-
- -Expand source code - -
def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-    raise NotImplementedError()
-
-
-
-
-def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) ‑> None -
-
-
- -Expand source code - -
def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-    raise NotImplementedError()
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/async_context.html b/docs/reference/context/async_context.html deleted file mode 100644 index 8fc6d36bf..000000000 --- a/docs/reference/context/async_context.html +++ /dev/null @@ -1,729 +0,0 @@ - - - - - - -slack_bolt.context.async_context API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.async_context

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncBoltContext -(*args, **kwargs) -
-
-
- -Expand source code - -
class AsyncBoltContext(BaseContext):
-    """Context object associated with a request from Slack."""
-
-    def to_copyable(self) -> "AsyncBoltContext":
-        new_dict = {}
-        for prop_name, prop_value in self.items():
-            if prop_name in self.copyable_standard_property_names:
-                # all the standard properties are copiable
-                new_dict[prop_name] = prop_value
-            elif prop_name in self.non_copyable_standard_property_names:
-                # Do nothing with this property (e.g., listener_runner)
-                continue
-            else:
-                try:
-                    copied_value = create_copy(prop_value)
-                    new_dict[prop_name] = copied_value
-                except TypeError as te:
-                    self.logger.debug(
-                        f"Skipped setting '{prop_name}' to a copied request for lazy listeners "
-                        f"as it's not possible to make a deep copy (error: {te})"
-                    )
-        return AsyncBoltContext(new_dict)
-
-    # The return type is intentionally string to avoid circular imports
-    @property
-    def listener_runner(self) -> "AsyncioListenerRunner":
-        """The properly configured listener_runner that is available for middleware/listeners."""
-        return self["listener_runner"]
-
-    @property
-    def client(self) -> AsyncWebClient:
-        """The `AsyncWebClient` instance available for this request.
-
-            @app.event("app_mention")
-            async def handle_events(context):
-                await context.client.chat_postMessage(
-                    channel=context.channel_id,
-                    text="Thanks!",
-                )
-
-            # You can access "client" this way too.
-            @app.event("app_mention")
-            async def handle_events(client, context):
-                await client.chat_postMessage(
-                    channel=context.channel_id,
-                    text="Thanks!",
-                )
-
-        Returns:
-            `AsyncWebClient` instance
-        """
-        if "client" not in self:
-            self["client"] = AsyncWebClient(token=None)
-        return self["client"]
-
-    @property
-    def ack(self) -> AsyncAck:
-        """`ack()` function for this request.
-
-            @app.action("button")
-            async def handle_button_clicks(context):
-                await context.ack()
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            async def handle_button_clicks(ack):
-                await ack()
-
-        Returns:
-            Callable `ack()` function
-        """
-        if "ack" not in self:
-            self["ack"] = AsyncAck()
-        return self["ack"]
-
-    @property
-    def say(self) -> AsyncSay:
-        """`say()` function for this request.
-
-            @app.action("button")
-            async def handle_button_clicks(context):
-                await context.ack()
-                await context.say("Hi!")
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            async def handle_button_clicks(ack, say):
-                await ack()
-                await say("Hi!")
-
-        Returns:
-            Callable `say()` function
-        """
-        if "say" not in self:
-            self["say"] = AsyncSay(client=self.client, channel=self.channel_id)
-        return self["say"]
-
-    @property
-    def respond(self) -> Optional[AsyncRespond]:
-        """`respond()` function for this request.
-
-            @app.action("button")
-            async def handle_button_clicks(context):
-                await context.ack()
-                await context.respond("Hi!")
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            async def handle_button_clicks(ack, respond):
-                await ack()
-                await respond("Hi!")
-
-        Returns:
-            Callable `respond()` function
-        """
-        if "respond" not in self:
-            self["respond"] = AsyncRespond(
-                response_url=self.response_url,
-                proxy=self.client.proxy,
-                ssl=self.client.ssl,
-            )
-        return self["respond"]
-
-    @property
-    def complete(self) -> AsyncComplete:
-        """`complete()` function for this request. Once a custom function's state is set to complete,
-        any outputs the function returns will be passed along to the next step of its housing workflow,
-        or complete the workflow if the function is the last step in a workflow. Additionally,
-        any interactivity handlers associated to a function invocation will no longer be invocable.
-
-            @app.function("reverse")
-            async def handle_button_clicks(ack, complete):
-                await ack()
-                await complete(outputs={"stringReverse":"olleh"})
-
-            @app.function("reverse")
-            async def handle_button_clicks(context):
-                await context.ack()
-                await context.complete(outputs={"stringReverse":"olleh"})
-
-        Returns:
-            Callable `complete()` function
-        """
-        if "complete" not in self:
-            self["complete"] = AsyncComplete(client=self.client, function_execution_id=self.function_execution_id)
-        return self["complete"]
-
-    @property
-    def fail(self) -> AsyncFail:
-        """`fail()` function for this request. Once a custom function's state is set to error,
-        its housing workflow will be interrupted and any provided error message will be passed
-        on to the end user through SlackBot. Additionally, any interactivity handlers associated
-        to a function invocation will no longer be invocable.
-
-            @app.function("reverse")
-            async def handle_button_clicks(ack, fail):
-                await ack()
-                await fail(error="something went wrong")
-
-            @app.function("reverse")
-            async def handle_button_clicks(context):
-                await context.ack()
-                await context.fail(error="something went wrong")
-
-        Returns:
-            Callable `fail()` function
-        """
-        if "fail" not in self:
-            self["fail"] = AsyncFail(client=self.client, function_execution_id=self.function_execution_id)
-        return self["fail"]
-
-    @property
-    def set_title(self) -> Optional[AsyncSetTitle]:
-        return self.get("set_title")
-
-    @property
-    def set_status(self) -> Optional[AsyncSetStatus]:
-        return self.get("set_status")
-
-    @property
-    def set_suggested_prompts(self) -> Optional[AsyncSetSuggestedPrompts]:
-        return self.get("set_suggested_prompts")
-
-    @property
-    def get_thread_context(self) -> Optional[AsyncGetThreadContext]:
-        return self.get("get_thread_context")
-
-    @property
-    def say_stream(self) -> Optional[AsyncSayStream]:
-        return self.get("say_stream")
-
-    @property
-    def save_thread_context(self) -> Optional[AsyncSaveThreadContext]:
-        return self.get("save_thread_context")
-
-

Context object associated with a request from Slack.

-

Ancestors

- -

Instance variables

-
-
prop ackAsyncAck
-
-
- -Expand source code - -
@property
-def ack(self) -> AsyncAck:
-    """`ack()` function for this request.
-
-        @app.action("button")
-        async def handle_button_clicks(context):
-            await context.ack()
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        async def handle_button_clicks(ack):
-            await ack()
-
-    Returns:
-        Callable `ack()` function
-    """
-    if "ack" not in self:
-        self["ack"] = AsyncAck()
-    return self["ack"]
-
-

ack() function for this request.

-
@app.action("button")
-async def handle_button_clicks(context):
-    await context.ack()
-
-# You can access "ack" this way too.
-@app.action("button")
-async def handle_button_clicks(ack):
-    await ack()
-
-

Returns

-

Callable ack() function

-
-
prop client : slack_sdk.web.async_client.AsyncWebClient
-
-
- -Expand source code - -
@property
-def client(self) -> AsyncWebClient:
-    """The `AsyncWebClient` instance available for this request.
-
-        @app.event("app_mention")
-        async def handle_events(context):
-            await context.client.chat_postMessage(
-                channel=context.channel_id,
-                text="Thanks!",
-            )
-
-        # You can access "client" this way too.
-        @app.event("app_mention")
-        async def handle_events(client, context):
-            await client.chat_postMessage(
-                channel=context.channel_id,
-                text="Thanks!",
-            )
-
-    Returns:
-        `AsyncWebClient` instance
-    """
-    if "client" not in self:
-        self["client"] = AsyncWebClient(token=None)
-    return self["client"]
-
-

The AsyncWebClient instance available for this request.

-
@app.event("app_mention")
-async def handle_events(context):
-    await context.client.chat_postMessage(
-        channel=context.channel_id,
-        text="Thanks!",
-    )
-
-# You can access "client" this way too.
-@app.event("app_mention")
-async def handle_events(client, context):
-    await client.chat_postMessage(
-        channel=context.channel_id,
-        text="Thanks!",
-    )
-
-

Returns

-

AsyncWebClient instance

-
-
prop completeAsyncComplete
-
-
- -Expand source code - -
@property
-def complete(self) -> AsyncComplete:
-    """`complete()` function for this request. Once a custom function's state is set to complete,
-    any outputs the function returns will be passed along to the next step of its housing workflow,
-    or complete the workflow if the function is the last step in a workflow. Additionally,
-    any interactivity handlers associated to a function invocation will no longer be invocable.
-
-        @app.function("reverse")
-        async def handle_button_clicks(ack, complete):
-            await ack()
-            await complete(outputs={"stringReverse":"olleh"})
-
-        @app.function("reverse")
-        async def handle_button_clicks(context):
-            await context.ack()
-            await context.complete(outputs={"stringReverse":"olleh"})
-
-    Returns:
-        Callable `complete()` function
-    """
-    if "complete" not in self:
-        self["complete"] = AsyncComplete(client=self.client, function_execution_id=self.function_execution_id)
-    return self["complete"]
-
-

complete() function for this request. Once a custom function's state is set to complete, -any outputs the function returns will be passed along to the next step of its housing workflow, -or complete the workflow if the function is the last step in a workflow. Additionally, -any interactivity handlers associated to a function invocation will no longer be invocable.

-
@app.function("reverse")
-async def handle_button_clicks(ack, complete):
-    await ack()
-    await complete(outputs={"stringReverse":"olleh"})
-
-@app.function("reverse")
-async def handle_button_clicks(context):
-    await context.ack()
-    await context.complete(outputs={"stringReverse":"olleh"})
-
-

Returns

-

Callable complete() function

-
-
prop failAsyncFail
-
-
- -Expand source code - -
@property
-def fail(self) -> AsyncFail:
-    """`fail()` function for this request. Once a custom function's state is set to error,
-    its housing workflow will be interrupted and any provided error message will be passed
-    on to the end user through SlackBot. Additionally, any interactivity handlers associated
-    to a function invocation will no longer be invocable.
-
-        @app.function("reverse")
-        async def handle_button_clicks(ack, fail):
-            await ack()
-            await fail(error="something went wrong")
-
-        @app.function("reverse")
-        async def handle_button_clicks(context):
-            await context.ack()
-            await context.fail(error="something went wrong")
-
-    Returns:
-        Callable `fail()` function
-    """
-    if "fail" not in self:
-        self["fail"] = AsyncFail(client=self.client, function_execution_id=self.function_execution_id)
-    return self["fail"]
-
-

fail() function for this request. Once a custom function's state is set to error, -its housing workflow will be interrupted and any provided error message will be passed -on to the end user through SlackBot. Additionally, any interactivity handlers associated -to a function invocation will no longer be invocable.

-
@app.function("reverse")
-async def handle_button_clicks(ack, fail):
-    await ack()
-    await fail(error="something went wrong")
-
-@app.function("reverse")
-async def handle_button_clicks(context):
-    await context.ack()
-    await context.fail(error="something went wrong")
-
-

Returns

-

Callable fail() function

-
-
prop get_thread_contextAsyncGetThreadContext | None
-
-
- -Expand source code - -
@property
-def get_thread_context(self) -> Optional[AsyncGetThreadContext]:
-    return self.get("get_thread_context")
-
-
-
-
prop listener_runner : AsyncioListenerRunner
-
-
- -Expand source code - -
@property
-def listener_runner(self) -> "AsyncioListenerRunner":
-    """The properly configured listener_runner that is available for middleware/listeners."""
-    return self["listener_runner"]
-
-

The properly configured listener_runner that is available for middleware/listeners.

-
-
prop respondAsyncRespond | None
-
-
- -Expand source code - -
@property
-def respond(self) -> Optional[AsyncRespond]:
-    """`respond()` function for this request.
-
-        @app.action("button")
-        async def handle_button_clicks(context):
-            await context.ack()
-            await context.respond("Hi!")
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        async def handle_button_clicks(ack, respond):
-            await ack()
-            await respond("Hi!")
-
-    Returns:
-        Callable `respond()` function
-    """
-    if "respond" not in self:
-        self["respond"] = AsyncRespond(
-            response_url=self.response_url,
-            proxy=self.client.proxy,
-            ssl=self.client.ssl,
-        )
-    return self["respond"]
-
-

respond() function for this request.

-
@app.action("button")
-async def handle_button_clicks(context):
-    await context.ack()
-    await context.respond("Hi!")
-
-# You can access "ack" this way too.
-@app.action("button")
-async def handle_button_clicks(ack, respond):
-    await ack()
-    await respond("Hi!")
-
-

Returns

-

Callable respond() function

-
-
prop save_thread_contextAsyncSaveThreadContext | None
-
-
- -Expand source code - -
@property
-def save_thread_context(self) -> Optional[AsyncSaveThreadContext]:
-    return self.get("save_thread_context")
-
-
-
-
prop sayAsyncSay
-
-
- -Expand source code - -
@property
-def say(self) -> AsyncSay:
-    """`say()` function for this request.
-
-        @app.action("button")
-        async def handle_button_clicks(context):
-            await context.ack()
-            await context.say("Hi!")
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        async def handle_button_clicks(ack, say):
-            await ack()
-            await say("Hi!")
-
-    Returns:
-        Callable `say()` function
-    """
-    if "say" not in self:
-        self["say"] = AsyncSay(client=self.client, channel=self.channel_id)
-    return self["say"]
-
-

say() function for this request.

-
@app.action("button")
-async def handle_button_clicks(context):
-    await context.ack()
-    await context.say("Hi!")
-
-# You can access "ack" this way too.
-@app.action("button")
-async def handle_button_clicks(ack, say):
-    await ack()
-    await say("Hi!")
-
-

Returns

-

Callable say() function

-
-
prop say_streamAsyncSayStream | None
-
-
- -Expand source code - -
@property
-def say_stream(self) -> Optional[AsyncSayStream]:
-    return self.get("say_stream")
-
-
-
-
prop set_statusAsyncSetStatus | None
-
-
- -Expand source code - -
@property
-def set_status(self) -> Optional[AsyncSetStatus]:
-    return self.get("set_status")
-
-
-
-
prop set_suggested_promptsAsyncSetSuggestedPrompts | None
-
-
- -Expand source code - -
@property
-def set_suggested_prompts(self) -> Optional[AsyncSetSuggestedPrompts]:
-    return self.get("set_suggested_prompts")
-
-
-
-
prop set_titleAsyncSetTitle | None
-
-
- -Expand source code - -
@property
-def set_title(self) -> Optional[AsyncSetTitle]:
-    return self.get("set_title")
-
-
-
-
-

Methods

-
-
-def to_copyable(self) ‑> AsyncBoltContext -
-
-
- -Expand source code - -
def to_copyable(self) -> "AsyncBoltContext":
-    new_dict = {}
-    for prop_name, prop_value in self.items():
-        if prop_name in self.copyable_standard_property_names:
-            # all the standard properties are copiable
-            new_dict[prop_name] = prop_value
-        elif prop_name in self.non_copyable_standard_property_names:
-            # Do nothing with this property (e.g., listener_runner)
-            continue
-        else:
-            try:
-                copied_value = create_copy(prop_value)
-                new_dict[prop_name] = copied_value
-            except TypeError as te:
-                self.logger.debug(
-                    f"Skipped setting '{prop_name}' to a copied request for lazy listeners "
-                    f"as it's not possible to make a deep copy (error: {te})"
-                )
-    return AsyncBoltContext(new_dict)
-
-
-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/context/base_context.html b/docs/reference/context/base_context.html deleted file mode 100644 index afe571163..000000000 --- a/docs/reference/context/base_context.html +++ /dev/null @@ -1,647 +0,0 @@ - - - - - - -slack_bolt.context.base_context API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.base_context

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class BaseContext -(*args, **kwargs) -
-
-
- -Expand source code - -
class BaseContext(dict):
-    """Context object associated with a request from Slack."""
-
-    copyable_standard_property_names = [
-        "logger",
-        "token",
-        "enterprise_id",
-        "is_enterprise_install",
-        "team_id",
-        "user_id",
-        "actor_enterprise_id",
-        "actor_team_id",
-        "actor_user_id",
-        "channel_id",
-        "thread_ts",
-        "response_url",
-        "matches",
-        "authorize_result",
-        "function_bot_access_token",
-        "bot_token",
-        "bot_id",
-        "bot_user_id",
-        "user_token",
-        "function_execution_id",
-        "inputs",
-        "client",
-        "ack",
-        "say",
-        "respond",
-        "complete",
-        "fail",
-        "set_status",
-        "set_title",
-        "set_suggested_prompts",
-        "say_stream",
-    ]
-    # Note that these items are not copyable, so when you add new items to this list,
-    # you must modify ThreadListenerRunner/AsyncioListenerRunner's _build_lazy_request method to pass the values.
-    # Other listener runners do not require the change because they invoke a lazy listener over the network,
-    # meaning that the context initialization would be done again.
-    non_copyable_standard_property_names = [
-        "listener_runner",
-        "get_thread_context",
-        "save_thread_context",
-    ]
-
-    standard_property_names = copyable_standard_property_names + non_copyable_standard_property_names
-
-    @property
-    def logger(self) -> Logger:
-        """The properly configured logger that is available for middleware/listeners."""
-        return self["logger"]
-
-    @property
-    def token(self) -> Optional[str]:
-        """The (bot/user) token resolved for this request."""
-        return self.get("token")
-
-    @property
-    def enterprise_id(self) -> Optional[str]:
-        """The Enterprise Grid Organization ID of this request."""
-        return self.get("enterprise_id")
-
-    @property
-    def is_enterprise_install(self) -> Optional[bool]:
-        """True if the request is associated with an Org-wide installation."""
-        return self.get("is_enterprise_install")
-
-    @property
-    def team_id(self) -> Optional[str]:
-        """The Workspace ID of this request."""
-        return self.get("team_id")
-
-    @property
-    def user_id(self) -> Optional[str]:
-        """The user ID associated ith this request."""
-        return self.get("user_id")
-
-    @property
-    def actor_enterprise_id(self) -> Optional[str]:
-        """The action's actor's Enterprise Grid organization ID.
-        Note that this property is especially useful for handling events in Slack Connect channels.
-        That being said, it's not guaranteed to have a valid ID for all events due to server-side inconsistency.
-        """
-        return self.get("actor_enterprise_id")
-
-    @property
-    def actor_team_id(self) -> Optional[str]:
-        """The action's actor's workspace ID.
-        Note that this property is especially useful for handling events in Slack Connect channels.
-        That being said, it's not guaranteed to have a valid ID for all events due to server-side inconsistency.
-        """
-        return self.get("actor_team_id")
-
-    @property
-    def actor_user_id(self) -> Optional[str]:
-        """The action's actor's user ID.
-        Note that this property is especially useful for handling events in Slack Connect channels.
-        That being said, it's not guaranteed to have a valid ID for all events due to server-side inconsistency.
-        """
-        return self.get("actor_user_id")
-
-    @property
-    def channel_id(self) -> Optional[str]:
-        """The conversation ID associated with this request."""
-        return self.get("channel_id")
-
-    @property
-    def thread_ts(self) -> Optional[str]:
-        """The conversation thread's ID associated with this request."""
-        return self.get("thread_ts")
-
-    @property
-    def response_url(self) -> Optional[str]:
-        """The `response_url` associated with this request."""
-        return self.get("response_url")
-
-    @property
-    def matches(self) -> Optional[Tuple]:
-        """Returns all the matched parts in message listener's regexp"""
-        return self.get("matches")
-
-    @property
-    def function_execution_id(self) -> Optional[str]:
-        """The `function_execution_id` associated with this request.
-        Only available for `function_executed` and interactivity events scoped to a custom step.
-        """
-        return self.get("function_execution_id")
-
-    @property
-    def inputs(self) -> Optional[Dict[str, Any]]:
-        """The `inputs` associated with this request.
-        Only available for `function_executed` and interactivity events scoped to a custom step.
-        """
-        return self.get("inputs")
-
-    # --------------------------------
-
-    @property
-    def authorize_result(self) -> Optional[AuthorizeResult]:
-        """The authorize result resolved for this request."""
-        return self.get("authorize_result")
-
-    @property
-    def function_bot_access_token(self) -> Optional[str]:
-        """The bot token resolved for this function request.
-        Only available for `function_executed` and interactivity events scoped to a custom step.
-        """
-        return self.get("function_bot_access_token")
-
-    @property
-    def bot_token(self) -> Optional[str]:
-        """The bot token resolved for this request."""
-        return self.get("bot_token")
-
-    @property
-    def bot_id(self) -> Optional[str]:
-        """The bot ID resolved for this request."""
-        return self.get("bot_id")
-
-    @property
-    def bot_user_id(self) -> Optional[str]:
-        """The bot user ID resolved for this request."""
-        return self.get("bot_user_id")
-
-    @property
-    def user_token(self) -> Optional[str]:
-        """The user token resolved for this request."""
-        return self.get("user_token")
-
-    def set_authorize_result(self, authorize_result: AuthorizeResult):
-        self["authorize_result"] = authorize_result
-        if authorize_result.bot_id is not None:
-            self["bot_id"] = authorize_result.bot_id
-        if authorize_result.bot_user_id is not None:
-            self["bot_user_id"] = authorize_result.bot_user_id
-        if authorize_result.bot_token is not None:
-            self["bot_token"] = authorize_result.bot_token
-        if authorize_result.user_id is not None:
-            self["user_id"] = authorize_result.user_id
-        if authorize_result.user_token is not None:
-            self["user_token"] = authorize_result.user_token
-
-

Context object associated with a request from Slack.

-

Ancestors

-
    -
  • builtins.dict
  • -
-

Subclasses

- -

Class variables

-
-
var copyable_standard_property_names
-
-

The type of the None singleton.

-
-
var non_copyable_standard_property_names
-
-

The type of the None singleton.

-
-
var standard_property_names
-
-

The type of the None singleton.

-
-
-

Instance variables

-
-
prop actor_enterprise_id : str | None
-
-
- -Expand source code - -
@property
-def actor_enterprise_id(self) -> Optional[str]:
-    """The action's actor's Enterprise Grid organization ID.
-    Note that this property is especially useful for handling events in Slack Connect channels.
-    That being said, it's not guaranteed to have a valid ID for all events due to server-side inconsistency.
-    """
-    return self.get("actor_enterprise_id")
-
-

The action's actor's Enterprise Grid organization ID. -Note that this property is especially useful for handling events in Slack Connect channels. -That being said, it's not guaranteed to have a valid ID for all events due to server-side inconsistency.

-
-
prop actor_team_id : str | None
-
-
- -Expand source code - -
@property
-def actor_team_id(self) -> Optional[str]:
-    """The action's actor's workspace ID.
-    Note that this property is especially useful for handling events in Slack Connect channels.
-    That being said, it's not guaranteed to have a valid ID for all events due to server-side inconsistency.
-    """
-    return self.get("actor_team_id")
-
-

The action's actor's workspace ID. -Note that this property is especially useful for handling events in Slack Connect channels. -That being said, it's not guaranteed to have a valid ID for all events due to server-side inconsistency.

-
-
prop actor_user_id : str | None
-
-
- -Expand source code - -
@property
-def actor_user_id(self) -> Optional[str]:
-    """The action's actor's user ID.
-    Note that this property is especially useful for handling events in Slack Connect channels.
-    That being said, it's not guaranteed to have a valid ID for all events due to server-side inconsistency.
-    """
-    return self.get("actor_user_id")
-
-

The action's actor's user ID. -Note that this property is especially useful for handling events in Slack Connect channels. -That being said, it's not guaranteed to have a valid ID for all events due to server-side inconsistency.

-
-
prop authorize_resultAuthorizeResult | None
-
-
- -Expand source code - -
@property
-def authorize_result(self) -> Optional[AuthorizeResult]:
-    """The authorize result resolved for this request."""
-    return self.get("authorize_result")
-
-

The authorize result resolved for this request.

-
-
prop bot_id : str | None
-
-
- -Expand source code - -
@property
-def bot_id(self) -> Optional[str]:
-    """The bot ID resolved for this request."""
-    return self.get("bot_id")
-
-

The bot ID resolved for this request.

-
-
prop bot_token : str | None
-
-
- -Expand source code - -
@property
-def bot_token(self) -> Optional[str]:
-    """The bot token resolved for this request."""
-    return self.get("bot_token")
-
-

The bot token resolved for this request.

-
-
prop bot_user_id : str | None
-
-
- -Expand source code - -
@property
-def bot_user_id(self) -> Optional[str]:
-    """The bot user ID resolved for this request."""
-    return self.get("bot_user_id")
-
-

The bot user ID resolved for this request.

-
-
prop channel_id : str | None
-
-
- -Expand source code - -
@property
-def channel_id(self) -> Optional[str]:
-    """The conversation ID associated with this request."""
-    return self.get("channel_id")
-
-

The conversation ID associated with this request.

-
-
prop enterprise_id : str | None
-
-
- -Expand source code - -
@property
-def enterprise_id(self) -> Optional[str]:
-    """The Enterprise Grid Organization ID of this request."""
-    return self.get("enterprise_id")
-
-

The Enterprise Grid Organization ID of this request.

-
-
prop function_bot_access_token : str | None
-
-
- -Expand source code - -
@property
-def function_bot_access_token(self) -> Optional[str]:
-    """The bot token resolved for this function request.
-    Only available for `function_executed` and interactivity events scoped to a custom step.
-    """
-    return self.get("function_bot_access_token")
-
-

The bot token resolved for this function request. -Only available for function_executed and interactivity events scoped to a custom step.

-
-
prop function_execution_id : str | None
-
-
- -Expand source code - -
@property
-def function_execution_id(self) -> Optional[str]:
-    """The `function_execution_id` associated with this request.
-    Only available for `function_executed` and interactivity events scoped to a custom step.
-    """
-    return self.get("function_execution_id")
-
-

The function_execution_id associated with this request. -Only available for function_executed and interactivity events scoped to a custom step.

-
-
prop inputs : Dict[str, Any] | None
-
-
- -Expand source code - -
@property
-def inputs(self) -> Optional[Dict[str, Any]]:
-    """The `inputs` associated with this request.
-    Only available for `function_executed` and interactivity events scoped to a custom step.
-    """
-    return self.get("inputs")
-
-

The inputs associated with this request. -Only available for function_executed and interactivity events scoped to a custom step.

-
-
prop is_enterprise_install : bool | None
-
-
- -Expand source code - -
@property
-def is_enterprise_install(self) -> Optional[bool]:
-    """True if the request is associated with an Org-wide installation."""
-    return self.get("is_enterprise_install")
-
-

True if the request is associated with an Org-wide installation.

-
-
prop logger : logging.Logger
-
-
- -Expand source code - -
@property
-def logger(self) -> Logger:
-    """The properly configured logger that is available for middleware/listeners."""
-    return self["logger"]
-
-

The properly configured logger that is available for middleware/listeners.

-
-
prop matches : Tuple | None
-
-
- -Expand source code - -
@property
-def matches(self) -> Optional[Tuple]:
-    """Returns all the matched parts in message listener's regexp"""
-    return self.get("matches")
-
-

Returns all the matched parts in message listener's regexp

-
-
prop response_url : str | None
-
-
- -Expand source code - -
@property
-def response_url(self) -> Optional[str]:
-    """The `response_url` associated with this request."""
-    return self.get("response_url")
-
-

The response_url associated with this request.

-
-
prop team_id : str | None
-
-
- -Expand source code - -
@property
-def team_id(self) -> Optional[str]:
-    """The Workspace ID of this request."""
-    return self.get("team_id")
-
-

The Workspace ID of this request.

-
-
prop thread_ts : str | None
-
-
- -Expand source code - -
@property
-def thread_ts(self) -> Optional[str]:
-    """The conversation thread's ID associated with this request."""
-    return self.get("thread_ts")
-
-

The conversation thread's ID associated with this request.

-
-
prop token : str | None
-
-
- -Expand source code - -
@property
-def token(self) -> Optional[str]:
-    """The (bot/user) token resolved for this request."""
-    return self.get("token")
-
-

The (bot/user) token resolved for this request.

-
-
prop user_id : str | None
-
-
- -Expand source code - -
@property
-def user_id(self) -> Optional[str]:
-    """The user ID associated ith this request."""
-    return self.get("user_id")
-
-

The user ID associated ith this request.

-
-
prop user_token : str | None
-
-
- -Expand source code - -
@property
-def user_token(self) -> Optional[str]:
-    """The user token resolved for this request."""
-    return self.get("user_token")
-
-

The user token resolved for this request.

-
-
-

Methods

-
-
-def set_authorize_result(self,
authorize_result: AuthorizeResult)
-
-
-
- -Expand source code - -
def set_authorize_result(self, authorize_result: AuthorizeResult):
-    self["authorize_result"] = authorize_result
-    if authorize_result.bot_id is not None:
-        self["bot_id"] = authorize_result.bot_id
-    if authorize_result.bot_user_id is not None:
-        self["bot_user_id"] = authorize_result.bot_user_id
-    if authorize_result.bot_token is not None:
-        self["bot_token"] = authorize_result.bot_token
-    if authorize_result.user_id is not None:
-        self["user_id"] = authorize_result.user_id
-    if authorize_result.user_token is not None:
-        self["user_token"] = authorize_result.user_token
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/complete/async_complete.html b/docs/reference/context/complete/async_complete.html deleted file mode 100644 index f0546a950..000000000 --- a/docs/reference/context/complete/async_complete.html +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - -slack_bolt.context.complete.async_complete API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.complete.async_complete

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncComplete -(client: slack_sdk.web.async_client.AsyncWebClient,
function_execution_id: str | None)
-
-
-
- -Expand source code - -
class AsyncComplete:
-    client: AsyncWebClient
-    function_execution_id: Optional[str]
-    _called: bool
-
-    def __init__(
-        self,
-        client: AsyncWebClient,
-        function_execution_id: Optional[str],
-    ):
-        self.client = client
-        self.function_execution_id = function_execution_id
-        self._called = False
-
-    async def __call__(self, outputs: Optional[Dict[str, Any]] = None) -> AsyncSlackResponse:
-        """Signal the successful completion of the custom function.
-
-        Kwargs:
-            outputs: Json serializable object containing the output values
-
-        Returns:
-            SlackResponse: The response object returned from slack
-
-        Raises:
-            ValueError: If this function cannot be used.
-        """
-        if self.function_execution_id is None:
-            raise ValueError("complete is unsupported here as there is no function_execution_id")
-
-        self._called = True
-        return await self.client.functions_completeSuccess(
-            function_execution_id=self.function_execution_id, outputs=outputs or {}
-        )
-
-    def has_been_called(self) -> bool:
-        """Check if this complete function has been called.
-
-        Returns:
-            bool: True if the complete function has been called, False otherwise.
-        """
-        return self._called
-
-
-

Class variables

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var function_execution_id : str | None
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def has_been_called(self) ‑> bool -
-
-
- -Expand source code - -
def has_been_called(self) -> bool:
-    """Check if this complete function has been called.
-
-    Returns:
-        bool: True if the complete function has been called, False otherwise.
-    """
-    return self._called
-
-

Check if this complete function has been called.

-

Returns

-
-
bool
-
True if the complete function has been called, False otherwise.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/complete/complete.html b/docs/reference/context/complete/complete.html deleted file mode 100644 index b8c1b083b..000000000 --- a/docs/reference/context/complete/complete.html +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - -slack_bolt.context.complete.complete API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.complete.complete

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Complete -(client: slack_sdk.web.client.WebClient, function_execution_id: str | None) -
-
-
- -Expand source code - -
class Complete:
-    client: WebClient
-    function_execution_id: Optional[str]
-    _called: bool
-
-    def __init__(
-        self,
-        client: WebClient,
-        function_execution_id: Optional[str],
-    ):
-        self.client = client
-        self.function_execution_id = function_execution_id
-        self._called = False
-
-    def __call__(self, outputs: Optional[Dict[str, Any]] = None) -> SlackResponse:
-        """Signal the successful completion of the custom function.
-
-        Kwargs:
-            outputs: Json serializable object containing the output values
-
-        Returns:
-            SlackResponse: The response object returned from slack
-
-        Raises:
-            ValueError: If this function cannot be used.
-        """
-        if self.function_execution_id is None:
-            raise ValueError("complete is unsupported here as there is no function_execution_id")
-
-        self._called = True
-        return self.client.functions_completeSuccess(function_execution_id=self.function_execution_id, outputs=outputs or {})
-
-    def has_been_called(self) -> bool:
-        """Check if this complete function has been called.
-
-        Returns:
-            bool: True if the complete function has been called, False otherwise.
-        """
-        return self._called
-
-
-

Class variables

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var function_execution_id : str | None
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def has_been_called(self) ‑> bool -
-
-
- -Expand source code - -
def has_been_called(self) -> bool:
-    """Check if this complete function has been called.
-
-    Returns:
-        bool: True if the complete function has been called, False otherwise.
-    """
-    return self._called
-
-

Check if this complete function has been called.

-

Returns

-
-
bool
-
True if the complete function has been called, False otherwise.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/complete/index.html b/docs/reference/context/complete/index.html deleted file mode 100644 index dddd26a84..000000000 --- a/docs/reference/context/complete/index.html +++ /dev/null @@ -1,186 +0,0 @@ - - - - - - -slack_bolt.context.complete API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.complete

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.complete.async_complete
-
-
-
-
slack_bolt.context.complete.complete
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Complete -(client: slack_sdk.web.client.WebClient, function_execution_id: str | None) -
-
-
- -Expand source code - -
class Complete:
-    client: WebClient
-    function_execution_id: Optional[str]
-    _called: bool
-
-    def __init__(
-        self,
-        client: WebClient,
-        function_execution_id: Optional[str],
-    ):
-        self.client = client
-        self.function_execution_id = function_execution_id
-        self._called = False
-
-    def __call__(self, outputs: Optional[Dict[str, Any]] = None) -> SlackResponse:
-        """Signal the successful completion of the custom function.
-
-        Kwargs:
-            outputs: Json serializable object containing the output values
-
-        Returns:
-            SlackResponse: The response object returned from slack
-
-        Raises:
-            ValueError: If this function cannot be used.
-        """
-        if self.function_execution_id is None:
-            raise ValueError("complete is unsupported here as there is no function_execution_id")
-
-        self._called = True
-        return self.client.functions_completeSuccess(function_execution_id=self.function_execution_id, outputs=outputs or {})
-
-    def has_been_called(self) -> bool:
-        """Check if this complete function has been called.
-
-        Returns:
-            bool: True if the complete function has been called, False otherwise.
-        """
-        return self._called
-
-
-

Class variables

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var function_execution_id : str | None
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def has_been_called(self) ‑> bool -
-
-
- -Expand source code - -
def has_been_called(self) -> bool:
-    """Check if this complete function has been called.
-
-    Returns:
-        bool: True if the complete function has been called, False otherwise.
-    """
-    return self._called
-
-

Check if this complete function has been called.

-

Returns

-
-
bool
-
True if the complete function has been called, False otherwise.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/context.html b/docs/reference/context/context.html deleted file mode 100644 index a7b531c20..000000000 --- a/docs/reference/context/context.html +++ /dev/null @@ -1,731 +0,0 @@ - - - - - - -slack_bolt.context.context API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.context

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class BoltContext -(*args, **kwargs) -
-
-
- -Expand source code - -
class BoltContext(BaseContext):
-    """Context object associated with a request from Slack."""
-
-    def to_copyable(self) -> "BoltContext":
-        new_dict = {}
-        for prop_name, prop_value in self.items():
-            if prop_name in self.copyable_standard_property_names:
-                # all the standard properties are copiable
-                new_dict[prop_name] = prop_value
-            elif prop_name in self.non_copyable_standard_property_names:
-                # Do nothing with this property (e.g., listener_runner)
-                continue
-            else:
-                try:
-                    copied_value = create_copy(prop_value)
-                    new_dict[prop_name] = copied_value
-                except TypeError as te:
-                    self.logger.warning(
-                        f"Skipped setting '{prop_name}' to a copied request for lazy listeners "
-                        "due to a deep-copy creation error. Consider passing the value not as part of context object "
-                        f"(error: {te})"
-                    )
-        return BoltContext(new_dict)
-
-    # The return type is intentionally string to avoid circular imports
-    @property
-    def listener_runner(self) -> "ThreadListenerRunner":
-        """The properly configured listener_runner that is available for middleware/listeners."""
-        return self["listener_runner"]
-
-    @property
-    def client(self) -> WebClient:
-        """The `WebClient` instance available for this request.
-
-            @app.event("app_mention")
-            def handle_events(context):
-                context.client.chat_postMessage(
-                    channel=context.channel_id,
-                    text="Thanks!",
-                )
-
-            # You can access "client" this way too.
-            @app.event("app_mention")
-            def handle_events(client, context):
-                client.chat_postMessage(
-                    channel=context.channel_id,
-                    text="Thanks!",
-                )
-
-        Returns:
-            `WebClient` instance
-        """
-        if "client" not in self:
-            self["client"] = WebClient(token=None)
-        return self["client"]
-
-    @property
-    def ack(self) -> Ack:
-        """`ack()` function for this request.
-
-            @app.action("button")
-            def handle_button_clicks(context):
-                context.ack()
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            def handle_button_clicks(ack):
-                ack()
-
-        Returns:
-            Callable `ack()` function
-        """
-        if "ack" not in self:
-            self["ack"] = Ack()
-        return self["ack"]
-
-    @property
-    def say(self) -> Say:
-        """`say()` function for this request.
-
-            @app.action("button")
-            def handle_button_clicks(context):
-                context.ack()
-                context.say("Hi!")
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            def handle_button_clicks(ack, say):
-                ack()
-                say("Hi!")
-
-        Returns:
-            Callable `say()` function
-        """
-        if "say" not in self:
-            self["say"] = Say(client=self.client, channel=self.channel_id)
-        return self["say"]
-
-    @property
-    def respond(self) -> Optional[Respond]:
-        """`respond()` function for this request.
-
-            @app.action("button")
-            def handle_button_clicks(context):
-                context.ack()
-                context.respond("Hi!")
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            def handle_button_clicks(ack, respond):
-                ack()
-                respond("Hi!")
-
-        Returns:
-            Callable `respond()` function
-        """
-        if "respond" not in self:
-            self["respond"] = Respond(
-                response_url=self.response_url,
-                proxy=self.client.proxy,
-                ssl=self.client.ssl,
-            )
-        return self["respond"]
-
-    @property
-    def complete(self) -> Complete:
-        """`complete()` function for this request. Once a custom function's state is set to complete,
-        any outputs the function returns will be passed along to the next step of its housing workflow,
-        or complete the workflow if the function is the last step in a workflow. Additionally,
-        any interactivity handlers associated to a function invocation will no longer be invocable.
-
-            @app.function("reverse")
-            def handle_button_clicks(ack, complete):
-                ack()
-                complete(outputs={"stringReverse":"olleh"})
-
-            @app.function("reverse")
-            def handle_button_clicks(context):
-                context.ack()
-                context.complete(outputs={"stringReverse":"olleh"})
-
-        Returns:
-            Callable `complete()` function
-        """
-        if "complete" not in self:
-            self["complete"] = Complete(client=self.client, function_execution_id=self.function_execution_id)
-        return self["complete"]
-
-    @property
-    def fail(self) -> Fail:
-        """`fail()` function for this request. Once a custom function's state is set to error,
-        its housing workflow will be interrupted and any provided error message will be passed
-        on to the end user through SlackBot. Additionally, any interactivity handlers associated
-        to a function invocation will no longer be invocable.
-
-            @app.function("reverse")
-            def handle_button_clicks(ack, fail):
-                ack()
-                fail(error="something went wrong")
-
-            @app.function("reverse")
-            def handle_button_clicks(context):
-                context.ack()
-                context.fail(error="something went wrong")
-
-        Returns:
-            Callable `fail()` function
-        """
-        if "fail" not in self:
-            self["fail"] = Fail(client=self.client, function_execution_id=self.function_execution_id)
-        return self["fail"]
-
-    @property
-    def set_title(self) -> Optional[SetTitle]:
-        return self.get("set_title")
-
-    @property
-    def set_status(self) -> Optional[SetStatus]:
-        return self.get("set_status")
-
-    @property
-    def set_suggested_prompts(self) -> Optional[SetSuggestedPrompts]:
-        return self.get("set_suggested_prompts")
-
-    @property
-    def get_thread_context(self) -> Optional[GetThreadContext]:
-        return self.get("get_thread_context")
-
-    @property
-    def say_stream(self) -> Optional[SayStream]:
-        return self.get("say_stream")
-
-    @property
-    def save_thread_context(self) -> Optional[SaveThreadContext]:
-        return self.get("save_thread_context")
-
-

Context object associated with a request from Slack.

-

Ancestors

- -

Instance variables

-
-
prop ackAck
-
-
- -Expand source code - -
@property
-def ack(self) -> Ack:
-    """`ack()` function for this request.
-
-        @app.action("button")
-        def handle_button_clicks(context):
-            context.ack()
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        def handle_button_clicks(ack):
-            ack()
-
-    Returns:
-        Callable `ack()` function
-    """
-    if "ack" not in self:
-        self["ack"] = Ack()
-    return self["ack"]
-
-

ack() function for this request.

-
@app.action("button")
-def handle_button_clicks(context):
-    context.ack()
-
-# You can access "ack" this way too.
-@app.action("button")
-def handle_button_clicks(ack):
-    ack()
-
-

Returns

-

Callable ack() function

-
-
prop client : slack_sdk.web.client.WebClient
-
-
- -Expand source code - -
@property
-def client(self) -> WebClient:
-    """The `WebClient` instance available for this request.
-
-        @app.event("app_mention")
-        def handle_events(context):
-            context.client.chat_postMessage(
-                channel=context.channel_id,
-                text="Thanks!",
-            )
-
-        # You can access "client" this way too.
-        @app.event("app_mention")
-        def handle_events(client, context):
-            client.chat_postMessage(
-                channel=context.channel_id,
-                text="Thanks!",
-            )
-
-    Returns:
-        `WebClient` instance
-    """
-    if "client" not in self:
-        self["client"] = WebClient(token=None)
-    return self["client"]
-
-

The WebClient instance available for this request.

-
@app.event("app_mention")
-def handle_events(context):
-    context.client.chat_postMessage(
-        channel=context.channel_id,
-        text="Thanks!",
-    )
-
-# You can access "client" this way too.
-@app.event("app_mention")
-def handle_events(client, context):
-    client.chat_postMessage(
-        channel=context.channel_id,
-        text="Thanks!",
-    )
-
-

Returns

-

WebClient instance

-
-
prop completeComplete
-
-
- -Expand source code - -
@property
-def complete(self) -> Complete:
-    """`complete()` function for this request. Once a custom function's state is set to complete,
-    any outputs the function returns will be passed along to the next step of its housing workflow,
-    or complete the workflow if the function is the last step in a workflow. Additionally,
-    any interactivity handlers associated to a function invocation will no longer be invocable.
-
-        @app.function("reverse")
-        def handle_button_clicks(ack, complete):
-            ack()
-            complete(outputs={"stringReverse":"olleh"})
-
-        @app.function("reverse")
-        def handle_button_clicks(context):
-            context.ack()
-            context.complete(outputs={"stringReverse":"olleh"})
-
-    Returns:
-        Callable `complete()` function
-    """
-    if "complete" not in self:
-        self["complete"] = Complete(client=self.client, function_execution_id=self.function_execution_id)
-    return self["complete"]
-
-

complete() function for this request. Once a custom function's state is set to complete, -any outputs the function returns will be passed along to the next step of its housing workflow, -or complete the workflow if the function is the last step in a workflow. Additionally, -any interactivity handlers associated to a function invocation will no longer be invocable.

-
@app.function("reverse")
-def handle_button_clicks(ack, complete):
-    ack()
-    complete(outputs={"stringReverse":"olleh"})
-
-@app.function("reverse")
-def handle_button_clicks(context):
-    context.ack()
-    context.complete(outputs={"stringReverse":"olleh"})
-
-

Returns

-

Callable complete() function

-
-
prop failFail
-
-
- -Expand source code - -
@property
-def fail(self) -> Fail:
-    """`fail()` function for this request. Once a custom function's state is set to error,
-    its housing workflow will be interrupted and any provided error message will be passed
-    on to the end user through SlackBot. Additionally, any interactivity handlers associated
-    to a function invocation will no longer be invocable.
-
-        @app.function("reverse")
-        def handle_button_clicks(ack, fail):
-            ack()
-            fail(error="something went wrong")
-
-        @app.function("reverse")
-        def handle_button_clicks(context):
-            context.ack()
-            context.fail(error="something went wrong")
-
-    Returns:
-        Callable `fail()` function
-    """
-    if "fail" not in self:
-        self["fail"] = Fail(client=self.client, function_execution_id=self.function_execution_id)
-    return self["fail"]
-
-

fail() function for this request. Once a custom function's state is set to error, -its housing workflow will be interrupted and any provided error message will be passed -on to the end user through SlackBot. Additionally, any interactivity handlers associated -to a function invocation will no longer be invocable.

-
@app.function("reverse")
-def handle_button_clicks(ack, fail):
-    ack()
-    fail(error="something went wrong")
-
-@app.function("reverse")
-def handle_button_clicks(context):
-    context.ack()
-    context.fail(error="something went wrong")
-
-

Returns

-

Callable fail() function

-
-
prop get_thread_contextGetThreadContext | None
-
-
- -Expand source code - -
@property
-def get_thread_context(self) -> Optional[GetThreadContext]:
-    return self.get("get_thread_context")
-
-
-
-
prop listener_runner : ThreadListenerRunner
-
-
- -Expand source code - -
@property
-def listener_runner(self) -> "ThreadListenerRunner":
-    """The properly configured listener_runner that is available for middleware/listeners."""
-    return self["listener_runner"]
-
-

The properly configured listener_runner that is available for middleware/listeners.

-
-
prop respondRespond | None
-
-
- -Expand source code - -
@property
-def respond(self) -> Optional[Respond]:
-    """`respond()` function for this request.
-
-        @app.action("button")
-        def handle_button_clicks(context):
-            context.ack()
-            context.respond("Hi!")
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        def handle_button_clicks(ack, respond):
-            ack()
-            respond("Hi!")
-
-    Returns:
-        Callable `respond()` function
-    """
-    if "respond" not in self:
-        self["respond"] = Respond(
-            response_url=self.response_url,
-            proxy=self.client.proxy,
-            ssl=self.client.ssl,
-        )
-    return self["respond"]
-
-

respond() function for this request.

-
@app.action("button")
-def handle_button_clicks(context):
-    context.ack()
-    context.respond("Hi!")
-
-# You can access "ack" this way too.
-@app.action("button")
-def handle_button_clicks(ack, respond):
-    ack()
-    respond("Hi!")
-
-

Returns

-

Callable respond() function

-
-
prop save_thread_contextSaveThreadContext | None
-
-
- -Expand source code - -
@property
-def save_thread_context(self) -> Optional[SaveThreadContext]:
-    return self.get("save_thread_context")
-
-
-
-
prop saySay
-
-
- -Expand source code - -
@property
-def say(self) -> Say:
-    """`say()` function for this request.
-
-        @app.action("button")
-        def handle_button_clicks(context):
-            context.ack()
-            context.say("Hi!")
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        def handle_button_clicks(ack, say):
-            ack()
-            say("Hi!")
-
-    Returns:
-        Callable `say()` function
-    """
-    if "say" not in self:
-        self["say"] = Say(client=self.client, channel=self.channel_id)
-    return self["say"]
-
-

say() function for this request.

-
@app.action("button")
-def handle_button_clicks(context):
-    context.ack()
-    context.say("Hi!")
-
-# You can access "ack" this way too.
-@app.action("button")
-def handle_button_clicks(ack, say):
-    ack()
-    say("Hi!")
-
-

Returns

-

Callable say() function

-
-
prop say_streamSayStream | None
-
-
- -Expand source code - -
@property
-def say_stream(self) -> Optional[SayStream]:
-    return self.get("say_stream")
-
-
-
-
prop set_statusSetStatus | None
-
-
- -Expand source code - -
@property
-def set_status(self) -> Optional[SetStatus]:
-    return self.get("set_status")
-
-
-
-
prop set_suggested_promptsSetSuggestedPrompts | None
-
-
- -Expand source code - -
@property
-def set_suggested_prompts(self) -> Optional[SetSuggestedPrompts]:
-    return self.get("set_suggested_prompts")
-
-
-
-
prop set_titleSetTitle | None
-
-
- -Expand source code - -
@property
-def set_title(self) -> Optional[SetTitle]:
-    return self.get("set_title")
-
-
-
-
-

Methods

-
-
-def to_copyable(self) ‑> BoltContext -
-
-
- -Expand source code - -
def to_copyable(self) -> "BoltContext":
-    new_dict = {}
-    for prop_name, prop_value in self.items():
-        if prop_name in self.copyable_standard_property_names:
-            # all the standard properties are copiable
-            new_dict[prop_name] = prop_value
-        elif prop_name in self.non_copyable_standard_property_names:
-            # Do nothing with this property (e.g., listener_runner)
-            continue
-        else:
-            try:
-                copied_value = create_copy(prop_value)
-                new_dict[prop_name] = copied_value
-            except TypeError as te:
-                self.logger.warning(
-                    f"Skipped setting '{prop_name}' to a copied request for lazy listeners "
-                    "due to a deep-copy creation error. Consider passing the value not as part of context object "
-                    f"(error: {te})"
-                )
-    return BoltContext(new_dict)
-
-
-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/context/fail/async_fail.html b/docs/reference/context/fail/async_fail.html deleted file mode 100644 index 80f19d18c..000000000 --- a/docs/reference/context/fail/async_fail.html +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - -slack_bolt.context.fail.async_fail API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.fail.async_fail

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncFail -(client: slack_sdk.web.async_client.AsyncWebClient,
function_execution_id: str | None)
-
-
-
- -Expand source code - -
class AsyncFail:
-    client: AsyncWebClient
-    function_execution_id: Optional[str]
-    _called: bool
-
-    def __init__(
-        self,
-        client: AsyncWebClient,
-        function_execution_id: Optional[str],
-    ):
-        self.client = client
-        self.function_execution_id = function_execution_id
-        self._called = False
-
-    async def __call__(self, error: str) -> AsyncSlackResponse:
-        """Signal that the custom function failed to complete.
-
-        Kwargs:
-            error: Error message to return to slack
-
-        Returns:
-            SlackResponse: The response object returned from slack
-
-        Raises:
-            ValueError: If this function cannot be used.
-        """
-        if self.function_execution_id is None:
-            raise ValueError("fail is unsupported here as there is no function_execution_id")
-
-        self._called = True
-        return await self.client.functions_completeError(function_execution_id=self.function_execution_id, error=error)
-
-    def has_been_called(self) -> bool:
-        """Check if this fail function has been called.
-
-        Returns:
-            bool: True if the fail function has been called, False otherwise.
-        """
-        return self._called
-
-
-

Class variables

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var function_execution_id : str | None
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def has_been_called(self) ‑> bool -
-
-
- -Expand source code - -
def has_been_called(self) -> bool:
-    """Check if this fail function has been called.
-
-    Returns:
-        bool: True if the fail function has been called, False otherwise.
-    """
-    return self._called
-
-

Check if this fail function has been called.

-

Returns

-
-
bool
-
True if the fail function has been called, False otherwise.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/fail/fail.html b/docs/reference/context/fail/fail.html deleted file mode 100644 index 51f4896a4..000000000 --- a/docs/reference/context/fail/fail.html +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - -slack_bolt.context.fail.fail API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.fail.fail

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Fail -(client: slack_sdk.web.client.WebClient, function_execution_id: str | None) -
-
-
- -Expand source code - -
class Fail:
-    client: WebClient
-    function_execution_id: Optional[str]
-    _called: bool
-
-    def __init__(
-        self,
-        client: WebClient,
-        function_execution_id: Optional[str],
-    ):
-        self.client = client
-        self.function_execution_id = function_execution_id
-        self._called = False
-
-    def __call__(self, error: str) -> SlackResponse:
-        """Signal that the custom function failed to complete.
-
-        Kwargs:
-            error: Error message to return to slack
-
-        Returns:
-            SlackResponse: The response object returned from slack
-
-        Raises:
-            ValueError: If this function cannot be used.
-        """
-        if self.function_execution_id is None:
-            raise ValueError("fail is unsupported here as there is no function_execution_id")
-
-        self._called = True
-        return self.client.functions_completeError(function_execution_id=self.function_execution_id, error=error)
-
-    def has_been_called(self) -> bool:
-        """Check if this fail function has been called.
-
-        Returns:
-            bool: True if the fail function has been called, False otherwise.
-        """
-        return self._called
-
-
-

Class variables

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var function_execution_id : str | None
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def has_been_called(self) ‑> bool -
-
-
- -Expand source code - -
def has_been_called(self) -> bool:
-    """Check if this fail function has been called.
-
-    Returns:
-        bool: True if the fail function has been called, False otherwise.
-    """
-    return self._called
-
-

Check if this fail function has been called.

-

Returns

-
-
bool
-
True if the fail function has been called, False otherwise.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/fail/index.html b/docs/reference/context/fail/index.html deleted file mode 100644 index 3b35dd6aa..000000000 --- a/docs/reference/context/fail/index.html +++ /dev/null @@ -1,186 +0,0 @@ - - - - - - -slack_bolt.context.fail API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.fail

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.fail.async_fail
-
-
-
-
slack_bolt.context.fail.fail
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Fail -(client: slack_sdk.web.client.WebClient, function_execution_id: str | None) -
-
-
- -Expand source code - -
class Fail:
-    client: WebClient
-    function_execution_id: Optional[str]
-    _called: bool
-
-    def __init__(
-        self,
-        client: WebClient,
-        function_execution_id: Optional[str],
-    ):
-        self.client = client
-        self.function_execution_id = function_execution_id
-        self._called = False
-
-    def __call__(self, error: str) -> SlackResponse:
-        """Signal that the custom function failed to complete.
-
-        Kwargs:
-            error: Error message to return to slack
-
-        Returns:
-            SlackResponse: The response object returned from slack
-
-        Raises:
-            ValueError: If this function cannot be used.
-        """
-        if self.function_execution_id is None:
-            raise ValueError("fail is unsupported here as there is no function_execution_id")
-
-        self._called = True
-        return self.client.functions_completeError(function_execution_id=self.function_execution_id, error=error)
-
-    def has_been_called(self) -> bool:
-        """Check if this fail function has been called.
-
-        Returns:
-            bool: True if the fail function has been called, False otherwise.
-        """
-        return self._called
-
-
-

Class variables

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var function_execution_id : str | None
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def has_been_called(self) ‑> bool -
-
-
- -Expand source code - -
def has_been_called(self) -> bool:
-    """Check if this fail function has been called.
-
-    Returns:
-        bool: True if the fail function has been called, False otherwise.
-    """
-    return self._called
-
-

Check if this fail function has been called.

-

Returns

-
-
bool
-
True if the fail function has been called, False otherwise.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/get_thread_context/async_get_thread_context.html b/docs/reference/context/get_thread_context/async_get_thread_context.html deleted file mode 100644 index 967581b50..000000000 --- a/docs/reference/context/get_thread_context/async_get_thread_context.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - -slack_bolt.context.get_thread_context.async_get_thread_context API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.get_thread_context.async_get_thread_context

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncGetThreadContext -(thread_context_store: AsyncAssistantThreadContextStore,
channel_id: str,
thread_ts: str,
payload: dict)
-
-
-
- -Expand source code - -
class AsyncGetThreadContext:
-    thread_context_store: AsyncAssistantThreadContextStore
-    payload: dict
-    channel_id: str
-    thread_ts: str
-
-    _thread_context: Optional[AssistantThreadContext]
-    thread_context_loaded: bool
-
-    def __init__(
-        self,
-        thread_context_store: AsyncAssistantThreadContextStore,
-        channel_id: str,
-        thread_ts: str,
-        payload: dict,
-    ):
-        self.thread_context_store = thread_context_store
-        self.payload = payload
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-        self._thread_context: Optional[AssistantThreadContext] = None
-        self.thread_context_loaded = False
-
-    async def __call__(self) -> Optional[AssistantThreadContext]:
-        if self.thread_context_loaded is True:
-            return self._thread_context
-
-        thread = self.payload.get("assistant_thread")
-        if isinstance(thread, dict) and thread.get("context", {}).get("channel_id") is not None:
-            # assistant_thread_started
-            self._thread_context = AssistantThreadContext(thread["context"])
-            # for this event, the context will never be changed
-            self.thread_context_loaded = True
-        elif self.payload.get("channel") is not None and self.payload.get("thread_ts") is not None:
-            # message event
-            self._thread_context = await self.thread_context_store.find(channel_id=self.channel_id, thread_ts=self.thread_ts)
-
-        return self._thread_context
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var payload : dict
-
-

The type of the None singleton.

-
-
var thread_context_loaded : bool
-
-

The type of the None singleton.

-
-
var thread_context_storeAsyncAssistantThreadContextStore
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/get_thread_context/get_thread_context.html b/docs/reference/context/get_thread_context/get_thread_context.html deleted file mode 100644 index cf2e17a86..000000000 --- a/docs/reference/context/get_thread_context/get_thread_context.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - -slack_bolt.context.get_thread_context.get_thread_context API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.get_thread_context.get_thread_context

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class GetThreadContext -(thread_context_store: AssistantThreadContextStore,
channel_id: str,
thread_ts: str,
payload: dict)
-
-
-
- -Expand source code - -
class GetThreadContext:
-    thread_context_store: AssistantThreadContextStore
-    payload: dict
-    channel_id: str
-    thread_ts: str
-
-    _thread_context: Optional[AssistantThreadContext]
-    thread_context_loaded: bool
-
-    def __init__(
-        self,
-        thread_context_store: AssistantThreadContextStore,
-        channel_id: str,
-        thread_ts: str,
-        payload: dict,
-    ):
-        self.thread_context_store = thread_context_store
-        self.payload = payload
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-        self._thread_context: Optional[AssistantThreadContext] = None
-        self.thread_context_loaded = False
-
-    def __call__(self) -> Optional[AssistantThreadContext]:
-        if self.thread_context_loaded is True:
-            return self._thread_context
-
-        thread = self.payload.get("assistant_thread")
-        if isinstance(thread, dict) and thread.get("context", {}).get("channel_id") is not None:
-            # assistant_thread_started
-            self._thread_context = AssistantThreadContext(thread["context"])
-            # for this event, the context will never be changed
-            self.thread_context_loaded = True
-        elif self.payload.get("channel") is not None and self.payload.get("thread_ts") is not None:
-            # message event
-            self._thread_context = self.thread_context_store.find(channel_id=self.channel_id, thread_ts=self.thread_ts)
-
-        return self._thread_context
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var payload : dict
-
-

The type of the None singleton.

-
-
var thread_context_loaded : bool
-
-

The type of the None singleton.

-
-
var thread_context_storeAssistantThreadContextStore
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/get_thread_context/index.html b/docs/reference/context/get_thread_context/index.html deleted file mode 100644 index 5f9e38e71..000000000 --- a/docs/reference/context/get_thread_context/index.html +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - -slack_bolt.context.get_thread_context API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.get_thread_context

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.get_thread_context.async_get_thread_context
-
-
-
-
slack_bolt.context.get_thread_context.get_thread_context
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class GetThreadContext -(thread_context_store: AssistantThreadContextStore,
channel_id: str,
thread_ts: str,
payload: dict)
-
-
-
- -Expand source code - -
class GetThreadContext:
-    thread_context_store: AssistantThreadContextStore
-    payload: dict
-    channel_id: str
-    thread_ts: str
-
-    _thread_context: Optional[AssistantThreadContext]
-    thread_context_loaded: bool
-
-    def __init__(
-        self,
-        thread_context_store: AssistantThreadContextStore,
-        channel_id: str,
-        thread_ts: str,
-        payload: dict,
-    ):
-        self.thread_context_store = thread_context_store
-        self.payload = payload
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-        self._thread_context: Optional[AssistantThreadContext] = None
-        self.thread_context_loaded = False
-
-    def __call__(self) -> Optional[AssistantThreadContext]:
-        if self.thread_context_loaded is True:
-            return self._thread_context
-
-        thread = self.payload.get("assistant_thread")
-        if isinstance(thread, dict) and thread.get("context", {}).get("channel_id") is not None:
-            # assistant_thread_started
-            self._thread_context = AssistantThreadContext(thread["context"])
-            # for this event, the context will never be changed
-            self.thread_context_loaded = True
-        elif self.payload.get("channel") is not None and self.payload.get("thread_ts") is not None:
-            # message event
-            self._thread_context = self.thread_context_store.find(channel_id=self.channel_id, thread_ts=self.thread_ts)
-
-        return self._thread_context
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var payload : dict
-
-

The type of the None singleton.

-
-
var thread_context_loaded : bool
-
-

The type of the None singleton.

-
-
var thread_context_storeAssistantThreadContextStore
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/index.html b/docs/reference/context/index.html deleted file mode 100644 index ebdfe8aa8..000000000 --- a/docs/reference/context/index.html +++ /dev/null @@ -1,818 +0,0 @@ - - - - - - -slack_bolt.context API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context

-
-
-

All listeners have access to a context dictionary, which can be used to enrich events with additional information. -Bolt automatically attaches information that is included in the incoming event, -like user_id, team_id, channel_id, and enterprise_id.

-

Refer to https://docs.slack.dev/tools/bolt-python/concepts/context for details.

-
-
-

Sub-modules

-
-
slack_bolt.context.ack
-
-
-
-
slack_bolt.context.assistant
-
-
-
-
slack_bolt.context.async_context
-
-
-
-
slack_bolt.context.base_context
-
-
-
-
slack_bolt.context.complete
-
-
-
-
slack_bolt.context.context
-
-
-
-
slack_bolt.context.fail
-
-
-
-
slack_bolt.context.get_thread_context
-
-
-
-
slack_bolt.context.respond
-
-
-
-
slack_bolt.context.save_thread_context
-
-
-
-
slack_bolt.context.say
-
-
-
-
slack_bolt.context.say_stream
-
-
-
-
slack_bolt.context.set_status
-
-
-
-
slack_bolt.context.set_suggested_prompts
-
-
-
-
slack_bolt.context.set_title
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class BoltContext -(*args, **kwargs) -
-
-
- -Expand source code - -
class BoltContext(BaseContext):
-    """Context object associated with a request from Slack."""
-
-    def to_copyable(self) -> "BoltContext":
-        new_dict = {}
-        for prop_name, prop_value in self.items():
-            if prop_name in self.copyable_standard_property_names:
-                # all the standard properties are copiable
-                new_dict[prop_name] = prop_value
-            elif prop_name in self.non_copyable_standard_property_names:
-                # Do nothing with this property (e.g., listener_runner)
-                continue
-            else:
-                try:
-                    copied_value = create_copy(prop_value)
-                    new_dict[prop_name] = copied_value
-                except TypeError as te:
-                    self.logger.warning(
-                        f"Skipped setting '{prop_name}' to a copied request for lazy listeners "
-                        "due to a deep-copy creation error. Consider passing the value not as part of context object "
-                        f"(error: {te})"
-                    )
-        return BoltContext(new_dict)
-
-    # The return type is intentionally string to avoid circular imports
-    @property
-    def listener_runner(self) -> "ThreadListenerRunner":
-        """The properly configured listener_runner that is available for middleware/listeners."""
-        return self["listener_runner"]
-
-    @property
-    def client(self) -> WebClient:
-        """The `WebClient` instance available for this request.
-
-            @app.event("app_mention")
-            def handle_events(context):
-                context.client.chat_postMessage(
-                    channel=context.channel_id,
-                    text="Thanks!",
-                )
-
-            # You can access "client" this way too.
-            @app.event("app_mention")
-            def handle_events(client, context):
-                client.chat_postMessage(
-                    channel=context.channel_id,
-                    text="Thanks!",
-                )
-
-        Returns:
-            `WebClient` instance
-        """
-        if "client" not in self:
-            self["client"] = WebClient(token=None)
-        return self["client"]
-
-    @property
-    def ack(self) -> Ack:
-        """`ack()` function for this request.
-
-            @app.action("button")
-            def handle_button_clicks(context):
-                context.ack()
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            def handle_button_clicks(ack):
-                ack()
-
-        Returns:
-            Callable `ack()` function
-        """
-        if "ack" not in self:
-            self["ack"] = Ack()
-        return self["ack"]
-
-    @property
-    def say(self) -> Say:
-        """`say()` function for this request.
-
-            @app.action("button")
-            def handle_button_clicks(context):
-                context.ack()
-                context.say("Hi!")
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            def handle_button_clicks(ack, say):
-                ack()
-                say("Hi!")
-
-        Returns:
-            Callable `say()` function
-        """
-        if "say" not in self:
-            self["say"] = Say(client=self.client, channel=self.channel_id)
-        return self["say"]
-
-    @property
-    def respond(self) -> Optional[Respond]:
-        """`respond()` function for this request.
-
-            @app.action("button")
-            def handle_button_clicks(context):
-                context.ack()
-                context.respond("Hi!")
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            def handle_button_clicks(ack, respond):
-                ack()
-                respond("Hi!")
-
-        Returns:
-            Callable `respond()` function
-        """
-        if "respond" not in self:
-            self["respond"] = Respond(
-                response_url=self.response_url,
-                proxy=self.client.proxy,
-                ssl=self.client.ssl,
-            )
-        return self["respond"]
-
-    @property
-    def complete(self) -> Complete:
-        """`complete()` function for this request. Once a custom function's state is set to complete,
-        any outputs the function returns will be passed along to the next step of its housing workflow,
-        or complete the workflow if the function is the last step in a workflow. Additionally,
-        any interactivity handlers associated to a function invocation will no longer be invocable.
-
-            @app.function("reverse")
-            def handle_button_clicks(ack, complete):
-                ack()
-                complete(outputs={"stringReverse":"olleh"})
-
-            @app.function("reverse")
-            def handle_button_clicks(context):
-                context.ack()
-                context.complete(outputs={"stringReverse":"olleh"})
-
-        Returns:
-            Callable `complete()` function
-        """
-        if "complete" not in self:
-            self["complete"] = Complete(client=self.client, function_execution_id=self.function_execution_id)
-        return self["complete"]
-
-    @property
-    def fail(self) -> Fail:
-        """`fail()` function for this request. Once a custom function's state is set to error,
-        its housing workflow will be interrupted and any provided error message will be passed
-        on to the end user through SlackBot. Additionally, any interactivity handlers associated
-        to a function invocation will no longer be invocable.
-
-            @app.function("reverse")
-            def handle_button_clicks(ack, fail):
-                ack()
-                fail(error="something went wrong")
-
-            @app.function("reverse")
-            def handle_button_clicks(context):
-                context.ack()
-                context.fail(error="something went wrong")
-
-        Returns:
-            Callable `fail()` function
-        """
-        if "fail" not in self:
-            self["fail"] = Fail(client=self.client, function_execution_id=self.function_execution_id)
-        return self["fail"]
-
-    @property
-    def set_title(self) -> Optional[SetTitle]:
-        return self.get("set_title")
-
-    @property
-    def set_status(self) -> Optional[SetStatus]:
-        return self.get("set_status")
-
-    @property
-    def set_suggested_prompts(self) -> Optional[SetSuggestedPrompts]:
-        return self.get("set_suggested_prompts")
-
-    @property
-    def get_thread_context(self) -> Optional[GetThreadContext]:
-        return self.get("get_thread_context")
-
-    @property
-    def say_stream(self) -> Optional[SayStream]:
-        return self.get("say_stream")
-
-    @property
-    def save_thread_context(self) -> Optional[SaveThreadContext]:
-        return self.get("save_thread_context")
-
-

Context object associated with a request from Slack.

-

Ancestors

- -

Instance variables

-
-
prop ackAck
-
-
- -Expand source code - -
@property
-def ack(self) -> Ack:
-    """`ack()` function for this request.
-
-        @app.action("button")
-        def handle_button_clicks(context):
-            context.ack()
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        def handle_button_clicks(ack):
-            ack()
-
-    Returns:
-        Callable `ack()` function
-    """
-    if "ack" not in self:
-        self["ack"] = Ack()
-    return self["ack"]
-
-

slack_bolt.context.ack function for this request.

-
@app.action("button")
-def handle_button_clicks(context):
-    context.ack()
-
-# You can access "ack" this way too.
-@app.action("button")
-def handle_button_clicks(ack):
-    ack()
-
-

Returns

-

Callable slack_bolt.context.ack function

-
-
prop client : slack_sdk.web.client.WebClient
-
-
- -Expand source code - -
@property
-def client(self) -> WebClient:
-    """The `WebClient` instance available for this request.
-
-        @app.event("app_mention")
-        def handle_events(context):
-            context.client.chat_postMessage(
-                channel=context.channel_id,
-                text="Thanks!",
-            )
-
-        # You can access "client" this way too.
-        @app.event("app_mention")
-        def handle_events(client, context):
-            client.chat_postMessage(
-                channel=context.channel_id,
-                text="Thanks!",
-            )
-
-    Returns:
-        `WebClient` instance
-    """
-    if "client" not in self:
-        self["client"] = WebClient(token=None)
-    return self["client"]
-
-

The WebClient instance available for this request.

-
@app.event("app_mention")
-def handle_events(context):
-    context.client.chat_postMessage(
-        channel=context.channel_id,
-        text="Thanks!",
-    )
-
-# You can access "client" this way too.
-@app.event("app_mention")
-def handle_events(client, context):
-    client.chat_postMessage(
-        channel=context.channel_id,
-        text="Thanks!",
-    )
-
-

Returns

-

WebClient instance

-
-
prop completeComplete
-
-
- -Expand source code - -
@property
-def complete(self) -> Complete:
-    """`complete()` function for this request. Once a custom function's state is set to complete,
-    any outputs the function returns will be passed along to the next step of its housing workflow,
-    or complete the workflow if the function is the last step in a workflow. Additionally,
-    any interactivity handlers associated to a function invocation will no longer be invocable.
-
-        @app.function("reverse")
-        def handle_button_clicks(ack, complete):
-            ack()
-            complete(outputs={"stringReverse":"olleh"})
-
-        @app.function("reverse")
-        def handle_button_clicks(context):
-            context.ack()
-            context.complete(outputs={"stringReverse":"olleh"})
-
-    Returns:
-        Callable `complete()` function
-    """
-    if "complete" not in self:
-        self["complete"] = Complete(client=self.client, function_execution_id=self.function_execution_id)
-    return self["complete"]
-
-

slack_bolt.context.complete function for this request. Once a custom function's state is set to complete, -any outputs the function returns will be passed along to the next step of its housing workflow, -or complete the workflow if the function is the last step in a workflow. Additionally, -any interactivity handlers associated to a function invocation will no longer be invocable.

-
@app.function("reverse")
-def handle_button_clicks(ack, complete):
-    ack()
-    complete(outputs={"stringReverse":"olleh"})
-
-@app.function("reverse")
-def handle_button_clicks(context):
-    context.ack()
-    context.complete(outputs={"stringReverse":"olleh"})
-
-

Returns

-

Callable slack_bolt.context.complete function

-
-
prop failFail
-
-
- -Expand source code - -
@property
-def fail(self) -> Fail:
-    """`fail()` function for this request. Once a custom function's state is set to error,
-    its housing workflow will be interrupted and any provided error message will be passed
-    on to the end user through SlackBot. Additionally, any interactivity handlers associated
-    to a function invocation will no longer be invocable.
-
-        @app.function("reverse")
-        def handle_button_clicks(ack, fail):
-            ack()
-            fail(error="something went wrong")
-
-        @app.function("reverse")
-        def handle_button_clicks(context):
-            context.ack()
-            context.fail(error="something went wrong")
-
-    Returns:
-        Callable `fail()` function
-    """
-    if "fail" not in self:
-        self["fail"] = Fail(client=self.client, function_execution_id=self.function_execution_id)
-    return self["fail"]
-
-

slack_bolt.context.fail function for this request. Once a custom function's state is set to error, -its housing workflow will be interrupted and any provided error message will be passed -on to the end user through SlackBot. Additionally, any interactivity handlers associated -to a function invocation will no longer be invocable.

-
@app.function("reverse")
-def handle_button_clicks(ack, fail):
-    ack()
-    fail(error="something went wrong")
-
-@app.function("reverse")
-def handle_button_clicks(context):
-    context.ack()
-    context.fail(error="something went wrong")
-
-

Returns

-

Callable slack_bolt.context.fail function

-
-
prop get_thread_contextGetThreadContext | None
-
-
- -Expand source code - -
@property
-def get_thread_context(self) -> Optional[GetThreadContext]:
-    return self.get("get_thread_context")
-
-
-
-
prop listener_runner : ThreadListenerRunner
-
-
- -Expand source code - -
@property
-def listener_runner(self) -> "ThreadListenerRunner":
-    """The properly configured listener_runner that is available for middleware/listeners."""
-    return self["listener_runner"]
-
-

The properly configured listener_runner that is available for middleware/listeners.

-
-
prop respondRespond | None
-
-
- -Expand source code - -
@property
-def respond(self) -> Optional[Respond]:
-    """`respond()` function for this request.
-
-        @app.action("button")
-        def handle_button_clicks(context):
-            context.ack()
-            context.respond("Hi!")
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        def handle_button_clicks(ack, respond):
-            ack()
-            respond("Hi!")
-
-    Returns:
-        Callable `respond()` function
-    """
-    if "respond" not in self:
-        self["respond"] = Respond(
-            response_url=self.response_url,
-            proxy=self.client.proxy,
-            ssl=self.client.ssl,
-        )
-    return self["respond"]
-
-

slack_bolt.context.respond function for this request.

-
@app.action("button")
-def handle_button_clicks(context):
-    context.ack()
-    context.respond("Hi!")
-
-# You can access "ack" this way too.
-@app.action("button")
-def handle_button_clicks(ack, respond):
-    ack()
-    respond("Hi!")
-
-

Returns

-

Callable slack_bolt.context.respond function

-
-
prop save_thread_contextSaveThreadContext | None
-
-
- -Expand source code - -
@property
-def save_thread_context(self) -> Optional[SaveThreadContext]:
-    return self.get("save_thread_context")
-
-
-
-
prop saySay
-
-
- -Expand source code - -
@property
-def say(self) -> Say:
-    """`say()` function for this request.
-
-        @app.action("button")
-        def handle_button_clicks(context):
-            context.ack()
-            context.say("Hi!")
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        def handle_button_clicks(ack, say):
-            ack()
-            say("Hi!")
-
-    Returns:
-        Callable `say()` function
-    """
-    if "say" not in self:
-        self["say"] = Say(client=self.client, channel=self.channel_id)
-    return self["say"]
-
-

slack_bolt.context.say function for this request.

-
@app.action("button")
-def handle_button_clicks(context):
-    context.ack()
-    context.say("Hi!")
-
-# You can access "ack" this way too.
-@app.action("button")
-def handle_button_clicks(ack, say):
-    ack()
-    say("Hi!")
-
-

Returns

-

Callable slack_bolt.context.say function

-
-
prop say_streamSayStream | None
-
-
- -Expand source code - -
@property
-def say_stream(self) -> Optional[SayStream]:
-    return self.get("say_stream")
-
-
-
-
prop set_statusSetStatus | None
-
-
- -Expand source code - -
@property
-def set_status(self) -> Optional[SetStatus]:
-    return self.get("set_status")
-
-
-
-
prop set_suggested_promptsSetSuggestedPrompts | None
-
-
- -Expand source code - -
@property
-def set_suggested_prompts(self) -> Optional[SetSuggestedPrompts]:
-    return self.get("set_suggested_prompts")
-
-
-
-
prop set_titleSetTitle | None
-
-
- -Expand source code - -
@property
-def set_title(self) -> Optional[SetTitle]:
-    return self.get("set_title")
-
-
-
-
-

Methods

-
-
-def to_copyable(self) ‑> BoltContext -
-
-
- -Expand source code - -
def to_copyable(self) -> "BoltContext":
-    new_dict = {}
-    for prop_name, prop_value in self.items():
-        if prop_name in self.copyable_standard_property_names:
-            # all the standard properties are copiable
-            new_dict[prop_name] = prop_value
-        elif prop_name in self.non_copyable_standard_property_names:
-            # Do nothing with this property (e.g., listener_runner)
-            continue
-        else:
-            try:
-                copied_value = create_copy(prop_value)
-                new_dict[prop_name] = copied_value
-            except TypeError as te:
-                self.logger.warning(
-                    f"Skipped setting '{prop_name}' to a copied request for lazy listeners "
-                    "due to a deep-copy creation error. Consider passing the value not as part of context object "
-                    f"(error: {te})"
-                )
-    return BoltContext(new_dict)
-
-
-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/context/respond/async_respond.html b/docs/reference/context/respond/async_respond.html deleted file mode 100644 index ed071afaf..000000000 --- a/docs/reference/context/respond/async_respond.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - -slack_bolt.context.respond.async_respond API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.respond.async_respond

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncRespond -(*,
response_url: str | None,
proxy: str | None = None,
ssl: ssl.SSLContext | None = None)
-
-
-
- -Expand source code - -
class AsyncRespond:
-    response_url: Optional[str]
-    proxy: Optional[str]
-    ssl: Optional[SSLContext]
-
-    def __init__(
-        self,
-        *,
-        response_url: Optional[str],
-        proxy: Optional[str] = None,
-        ssl: Optional[SSLContext] = None,
-    ):
-        self.response_url = response_url
-        self.proxy = proxy
-        self.ssl = ssl
-
-    async def __call__(
-        self,
-        text: Union[str, dict] = "",
-        blocks: Optional[Sequence[Union[dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[dict, Attachment]]] = None,
-        response_type: Optional[str] = None,
-        replace_original: Optional[bool] = None,
-        delete_original: Optional[bool] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        thread_ts: Optional[str] = None,
-        metadata: Optional[Dict[str, Any]] = None,
-    ) -> WebhookResponse:
-        if self.response_url is not None:
-            client = AsyncWebhookClient(
-                url=self.response_url,
-                proxy=self.proxy,
-                ssl=self.ssl,
-            )
-            text_or_whole_response: Union[str, dict] = text
-            if isinstance(text_or_whole_response, str):
-                message = _build_message(
-                    text=text,  # type: ignore[arg-type]
-                    blocks=blocks,
-                    attachments=attachments,
-                    response_type=response_type,
-                    replace_original=replace_original,
-                    delete_original=delete_original,
-                    unfurl_links=unfurl_links,
-                    unfurl_media=unfurl_media,
-                    thread_ts=thread_ts,
-                    metadata=metadata,
-                )
-                return await client.send_dict(message)
-            elif isinstance(text_or_whole_response, dict):
-                whole_response: dict = text_or_whole_response
-                message = _build_message(**whole_response)
-                return await client.send_dict(message)
-            else:
-                raise ValueError(f"The arg is unexpected type ({type(text)})")
-        else:
-            raise ValueError("respond is unsupported here as there is no response_url")
-
-
-

Class variables

-
-
var proxy : str | None
-
-

The type of the None singleton.

-
-
var response_url : str | None
-
-

The type of the None singleton.

-
-
var ssl : ssl.SSLContext | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/respond/index.html b/docs/reference/context/respond/index.html deleted file mode 100644 index 8c116c956..000000000 --- a/docs/reference/context/respond/index.html +++ /dev/null @@ -1,188 +0,0 @@ - - - - - - -slack_bolt.context.respond API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.respond

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.respond.async_respond
-
-
-
-
slack_bolt.context.respond.internals
-
-
-
-
slack_bolt.context.respond.respond
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Respond -(*,
response_url: str | None,
proxy: str | None = None,
ssl: ssl.SSLContext | None = None)
-
-
-
- -Expand source code - -
class Respond:
-    response_url: Optional[str]
-    proxy: Optional[str]
-    ssl: Optional[SSLContext]
-
-    def __init__(
-        self,
-        *,
-        response_url: Optional[str],
-        proxy: Optional[str] = None,
-        ssl: Optional[SSLContext] = None,
-    ):
-        self.response_url = response_url
-        self.proxy = proxy
-        self.ssl = ssl
-
-    def __call__(
-        self,
-        text: Union[str, dict] = "",
-        blocks: Optional[Sequence[Union[dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[dict, Attachment]]] = None,
-        response_type: Optional[str] = None,
-        replace_original: Optional[bool] = None,
-        delete_original: Optional[bool] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        thread_ts: Optional[str] = None,
-        metadata: Optional[Dict[str, Any]] = None,
-    ) -> WebhookResponse:
-        if self.response_url is not None:
-            client = WebhookClient(
-                url=self.response_url,
-                proxy=self.proxy,
-                ssl=self.ssl,
-            )
-            text_or_whole_response: Union[str, dict] = text
-            if isinstance(text_or_whole_response, str):
-                text = text_or_whole_response
-                message = _build_message(
-                    text=text,
-                    blocks=blocks,
-                    attachments=attachments,
-                    response_type=response_type,
-                    replace_original=replace_original,
-                    delete_original=delete_original,
-                    unfurl_links=unfurl_links,
-                    unfurl_media=unfurl_media,
-                    thread_ts=thread_ts,
-                    metadata=metadata,
-                )
-                return client.send_dict(message)
-            elif isinstance(text_or_whole_response, dict):
-                message = _build_message(**text_or_whole_response)
-                return client.send_dict(message)
-            else:
-                raise ValueError(f"The arg is unexpected type ({type(text_or_whole_response)})")
-        else:
-            raise ValueError("respond is unsupported here as there is no response_url")
-
-
-

Class variables

-
-
var proxy : str | None
-
-

The type of the None singleton.

-
-
var response_url : str | None
-
-

The type of the None singleton.

-
-
var ssl : ssl.SSLContext | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/respond/internals.html b/docs/reference/context/respond/internals.html deleted file mode 100644 index e61988ef6..000000000 --- a/docs/reference/context/respond/internals.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - -slack_bolt.context.respond.internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.respond.internals

-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/respond/respond.html b/docs/reference/context/respond/respond.html deleted file mode 100644 index af2271eb6..000000000 --- a/docs/reference/context/respond/respond.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - -slack_bolt.context.respond.respond API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.respond.respond

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Respond -(*,
response_url: str | None,
proxy: str | None = None,
ssl: ssl.SSLContext | None = None)
-
-
-
- -Expand source code - -
class Respond:
-    response_url: Optional[str]
-    proxy: Optional[str]
-    ssl: Optional[SSLContext]
-
-    def __init__(
-        self,
-        *,
-        response_url: Optional[str],
-        proxy: Optional[str] = None,
-        ssl: Optional[SSLContext] = None,
-    ):
-        self.response_url = response_url
-        self.proxy = proxy
-        self.ssl = ssl
-
-    def __call__(
-        self,
-        text: Union[str, dict] = "",
-        blocks: Optional[Sequence[Union[dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[dict, Attachment]]] = None,
-        response_type: Optional[str] = None,
-        replace_original: Optional[bool] = None,
-        delete_original: Optional[bool] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        thread_ts: Optional[str] = None,
-        metadata: Optional[Dict[str, Any]] = None,
-    ) -> WebhookResponse:
-        if self.response_url is not None:
-            client = WebhookClient(
-                url=self.response_url,
-                proxy=self.proxy,
-                ssl=self.ssl,
-            )
-            text_or_whole_response: Union[str, dict] = text
-            if isinstance(text_or_whole_response, str):
-                text = text_or_whole_response
-                message = _build_message(
-                    text=text,
-                    blocks=blocks,
-                    attachments=attachments,
-                    response_type=response_type,
-                    replace_original=replace_original,
-                    delete_original=delete_original,
-                    unfurl_links=unfurl_links,
-                    unfurl_media=unfurl_media,
-                    thread_ts=thread_ts,
-                    metadata=metadata,
-                )
-                return client.send_dict(message)
-            elif isinstance(text_or_whole_response, dict):
-                message = _build_message(**text_or_whole_response)
-                return client.send_dict(message)
-            else:
-                raise ValueError(f"The arg is unexpected type ({type(text_or_whole_response)})")
-        else:
-            raise ValueError("respond is unsupported here as there is no response_url")
-
-
-

Class variables

-
-
var proxy : str | None
-
-

The type of the None singleton.

-
-
var response_url : str | None
-
-

The type of the None singleton.

-
-
var ssl : ssl.SSLContext | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/save_thread_context/async_save_thread_context.html b/docs/reference/context/save_thread_context/async_save_thread_context.html deleted file mode 100644 index f57291c3c..000000000 --- a/docs/reference/context/save_thread_context/async_save_thread_context.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - -slack_bolt.context.save_thread_context.async_save_thread_context API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.save_thread_context.async_save_thread_context

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSaveThreadContext -(thread_context_store: AsyncAssistantThreadContextStore,
channel_id: str,
thread_ts: str)
-
-
-
- -Expand source code - -
class AsyncSaveThreadContext:
-    thread_context_store: AsyncAssistantThreadContextStore
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        thread_context_store: AsyncAssistantThreadContextStore,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.thread_context_store = thread_context_store
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    async def __call__(self, new_context: Dict[str, str]) -> None:
-        await self.thread_context_store.save(
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-            context=new_context,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var thread_context_storeAsyncAssistantThreadContextStore
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/save_thread_context/index.html b/docs/reference/context/save_thread_context/index.html deleted file mode 100644 index 01f63ecd8..000000000 --- a/docs/reference/context/save_thread_context/index.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - -slack_bolt.context.save_thread_context API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.save_thread_context

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.save_thread_context.async_save_thread_context
-
-
-
-
slack_bolt.context.save_thread_context.save_thread_context
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SaveThreadContext -(thread_context_store: AssistantThreadContextStore,
channel_id: str,
thread_ts: str)
-
-
-
- -Expand source code - -
class SaveThreadContext:
-    thread_context_store: AssistantThreadContextStore
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        thread_context_store: AssistantThreadContextStore,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.thread_context_store = thread_context_store
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    def __call__(self, new_context: Dict[str, str]) -> None:
-        self.thread_context_store.save(
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-            context=new_context,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var thread_context_storeAssistantThreadContextStore
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/save_thread_context/save_thread_context.html b/docs/reference/context/save_thread_context/save_thread_context.html deleted file mode 100644 index 328441034..000000000 --- a/docs/reference/context/save_thread_context/save_thread_context.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - -slack_bolt.context.save_thread_context.save_thread_context API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.save_thread_context.save_thread_context

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SaveThreadContext -(thread_context_store: AssistantThreadContextStore,
channel_id: str,
thread_ts: str)
-
-
-
- -Expand source code - -
class SaveThreadContext:
-    thread_context_store: AssistantThreadContextStore
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        thread_context_store: AssistantThreadContextStore,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.thread_context_store = thread_context_store
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    def __call__(self, new_context: Dict[str, str]) -> None:
-        self.thread_context_store.save(
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-            context=new_context,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var thread_context_storeAssistantThreadContextStore
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/say/async_say.html b/docs/reference/context/say/async_say.html deleted file mode 100644 index e170251fe..000000000 --- a/docs/reference/context/say/async_say.html +++ /dev/null @@ -1,191 +0,0 @@ - - - - - - -slack_bolt.context.say.async_say API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.say.async_say

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSay -(client: slack_sdk.web.async_client.AsyncWebClient | None,
channel: str | None,
thread_ts: str | None = None,
build_metadata: Callable[[], Awaitable[Dict | slack_sdk.models.metadata.Metadata]] | None = None)
-
-
-
- -Expand source code - -
class AsyncSay:
-    client: Optional[AsyncWebClient]
-    channel: Optional[str]
-    thread_ts: Optional[str]
-    build_metadata: Optional[Callable[[], Awaitable[Union[Dict, Metadata]]]]
-
-    def __init__(
-        self,
-        client: Optional[AsyncWebClient],
-        channel: Optional[str],
-        thread_ts: Optional[str] = None,
-        build_metadata: Optional[Callable[[], Awaitable[Union[Dict, Metadata]]]] = None,
-    ):
-        self.client = client
-        self.channel = channel
-        self.thread_ts = thread_ts
-        self.build_metadata = build_metadata
-
-    async def __call__(
-        self,
-        text: Union[str, dict] = "",
-        blocks: Optional[Sequence[Union[Dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[Dict, Attachment]]] = None,
-        channel: Optional[str] = None,
-        as_user: Optional[bool] = None,
-        thread_ts: Optional[str] = None,
-        reply_broadcast: Optional[bool] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        markdown_text: Optional[str] = None,
-        mrkdwn: Optional[bool] = None,
-        link_names: Optional[bool] = None,
-        parse: Optional[str] = None,  # none, full
-        metadata: Optional[Union[Dict, Metadata]] = None,
-        **kwargs,
-    ) -> AsyncSlackResponse:
-        if _can_say(self, channel):
-            if metadata is None and self.build_metadata is not None:
-                metadata = await self.build_metadata()
-            text_or_whole_response: Union[str, dict] = text
-            if isinstance(text_or_whole_response, str):
-                text = text_or_whole_response
-                return await self.client.chat_postMessage(  # type: ignore[union-attr]
-                    channel=channel or self.channel,  # type: ignore[arg-type]
-                    text=text,
-                    blocks=blocks,
-                    attachments=attachments,
-                    as_user=as_user,
-                    thread_ts=thread_ts or self.thread_ts,
-                    reply_broadcast=reply_broadcast,
-                    unfurl_links=unfurl_links,
-                    unfurl_media=unfurl_media,
-                    icon_emoji=icon_emoji,
-                    icon_url=icon_url,
-                    username=username,
-                    markdown_text=markdown_text,
-                    mrkdwn=mrkdwn,
-                    link_names=link_names,
-                    parse=parse,
-                    metadata=metadata,
-                    **kwargs,
-                )
-            elif isinstance(text_or_whole_response, dict):
-                message: dict = create_copy(text_or_whole_response)
-                if "channel" not in message:
-                    message["channel"] = channel or self.channel
-                if "thread_ts" not in message:
-                    message["thread_ts"] = thread_ts or self.thread_ts
-                if "metadata" not in message:
-                    message["metadata"] = metadata
-                return await self.client.chat_postMessage(**message)  # type: ignore[union-attr]
-            else:
-                raise ValueError(f"The arg is unexpected type ({type(text_or_whole_response)})")
-        else:
-            raise ValueError("say without channel_id here is unsupported")
-
-
-

Class variables

-
-
var build_metadata : Callable[[], Awaitable[Dict | slack_sdk.models.metadata.Metadata]] | None
-
-

The type of the None singleton.

-
-
var channel : str | None
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.async_client.AsyncWebClient | None
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/say/index.html b/docs/reference/context/say/index.html deleted file mode 100644 index e2ed0d03f..000000000 --- a/docs/reference/context/say/index.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - -slack_bolt.context.say API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.say

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.say.async_say
-
-
-
-
slack_bolt.context.say.internals
-
-
-
-
slack_bolt.context.say.say
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Say -(client: slack_sdk.web.client.WebClient | None,
channel: str | None,
thread_ts: str | None = None,
metadata: Dict | slack_sdk.models.metadata.Metadata | None = None,
build_metadata: Callable[[], Dict | slack_sdk.models.metadata.Metadata | None] | None = None)
-
-
-
- -Expand source code - -
class Say:
-    client: Optional[WebClient]
-    channel: Optional[str]
-    thread_ts: Optional[str]
-    metadata: Optional[Union[Dict, Metadata]]
-    build_metadata: Optional[Callable[[], Optional[Union[Dict, Metadata]]]]
-
-    def __init__(
-        self,
-        client: Optional[WebClient],
-        channel: Optional[str],
-        thread_ts: Optional[str] = None,
-        metadata: Optional[Union[Dict, Metadata]] = None,
-        build_metadata: Optional[Callable[[], Optional[Union[Dict, Metadata]]]] = None,
-    ):
-        self.client = client
-        self.channel = channel
-        self.thread_ts = thread_ts
-        self.metadata = metadata
-        self.build_metadata = build_metadata
-
-    def __call__(
-        self,
-        text: Union[str, dict] = "",
-        blocks: Optional[Sequence[Union[Dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[Dict, Attachment]]] = None,
-        channel: Optional[str] = None,
-        as_user: Optional[bool] = None,
-        thread_ts: Optional[str] = None,
-        reply_broadcast: Optional[bool] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        markdown_text: Optional[str] = None,
-        mrkdwn: Optional[bool] = None,
-        link_names: Optional[bool] = None,
-        parse: Optional[str] = None,  # none, full
-        metadata: Optional[Union[Dict, Metadata]] = None,
-        **kwargs,
-    ) -> SlackResponse:
-        if _can_say(self, channel):
-            text_or_whole_response: Union[str, dict] = text
-            if isinstance(text_or_whole_response, str):
-                text = text_or_whole_response
-                if metadata is None:
-                    metadata = self.build_metadata() if self.build_metadata is not None else self.metadata
-                return self.client.chat_postMessage(  # type: ignore[union-attr]
-                    channel=channel or self.channel,  # type: ignore[arg-type]
-                    text=text,
-                    blocks=blocks,
-                    attachments=attachments,
-                    as_user=as_user,
-                    thread_ts=thread_ts or self.thread_ts,
-                    reply_broadcast=reply_broadcast,
-                    unfurl_links=unfurl_links,
-                    unfurl_media=unfurl_media,
-                    icon_emoji=icon_emoji,
-                    icon_url=icon_url,
-                    username=username,
-                    markdown_text=markdown_text,
-                    mrkdwn=mrkdwn,
-                    link_names=link_names,
-                    parse=parse,
-                    metadata=metadata,
-                    **kwargs,
-                )
-            elif isinstance(text_or_whole_response, dict):
-                message: dict = create_copy(text_or_whole_response)
-                if "channel" not in message:
-                    message["channel"] = channel or self.channel
-                if "thread_ts" not in message:
-                    message["thread_ts"] = thread_ts or self.thread_ts
-                if "metadata" not in message:
-                    metadata = self.build_metadata() if self.build_metadata is not None else self.metadata
-                    message["metadata"] = metadata
-                return self.client.chat_postMessage(**message)  # type: ignore[union-attr]
-            else:
-                raise ValueError(f"The arg is unexpected type ({type(text_or_whole_response)})")
-        else:
-            raise ValueError("say without channel_id here is unsupported")
-
-
-

Class variables

-
-
var build_metadata : Callable[[], Dict | slack_sdk.models.metadata.Metadata | None] | None
-
-

The type of the None singleton.

-
-
var channel : str | None
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient | None
-
-

The type of the None singleton.

-
-
var metadata : Dict | slack_sdk.models.metadata.Metadata | None
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/say/internals.html b/docs/reference/context/say/internals.html deleted file mode 100644 index 861065203..000000000 --- a/docs/reference/context/say/internals.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - -slack_bolt.context.say.internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.say.internals

-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/say/say.html b/docs/reference/context/say/say.html deleted file mode 100644 index c66e2776f..000000000 --- a/docs/reference/context/say/say.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - -slack_bolt.context.say.say API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.say.say

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Say -(client: slack_sdk.web.client.WebClient | None,
channel: str | None,
thread_ts: str | None = None,
metadata: Dict | slack_sdk.models.metadata.Metadata | None = None,
build_metadata: Callable[[], Dict | slack_sdk.models.metadata.Metadata | None] | None = None)
-
-
-
- -Expand source code - -
class Say:
-    client: Optional[WebClient]
-    channel: Optional[str]
-    thread_ts: Optional[str]
-    metadata: Optional[Union[Dict, Metadata]]
-    build_metadata: Optional[Callable[[], Optional[Union[Dict, Metadata]]]]
-
-    def __init__(
-        self,
-        client: Optional[WebClient],
-        channel: Optional[str],
-        thread_ts: Optional[str] = None,
-        metadata: Optional[Union[Dict, Metadata]] = None,
-        build_metadata: Optional[Callable[[], Optional[Union[Dict, Metadata]]]] = None,
-    ):
-        self.client = client
-        self.channel = channel
-        self.thread_ts = thread_ts
-        self.metadata = metadata
-        self.build_metadata = build_metadata
-
-    def __call__(
-        self,
-        text: Union[str, dict] = "",
-        blocks: Optional[Sequence[Union[Dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[Dict, Attachment]]] = None,
-        channel: Optional[str] = None,
-        as_user: Optional[bool] = None,
-        thread_ts: Optional[str] = None,
-        reply_broadcast: Optional[bool] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        markdown_text: Optional[str] = None,
-        mrkdwn: Optional[bool] = None,
-        link_names: Optional[bool] = None,
-        parse: Optional[str] = None,  # none, full
-        metadata: Optional[Union[Dict, Metadata]] = None,
-        **kwargs,
-    ) -> SlackResponse:
-        if _can_say(self, channel):
-            text_or_whole_response: Union[str, dict] = text
-            if isinstance(text_or_whole_response, str):
-                text = text_or_whole_response
-                if metadata is None:
-                    metadata = self.build_metadata() if self.build_metadata is not None else self.metadata
-                return self.client.chat_postMessage(  # type: ignore[union-attr]
-                    channel=channel or self.channel,  # type: ignore[arg-type]
-                    text=text,
-                    blocks=blocks,
-                    attachments=attachments,
-                    as_user=as_user,
-                    thread_ts=thread_ts or self.thread_ts,
-                    reply_broadcast=reply_broadcast,
-                    unfurl_links=unfurl_links,
-                    unfurl_media=unfurl_media,
-                    icon_emoji=icon_emoji,
-                    icon_url=icon_url,
-                    username=username,
-                    markdown_text=markdown_text,
-                    mrkdwn=mrkdwn,
-                    link_names=link_names,
-                    parse=parse,
-                    metadata=metadata,
-                    **kwargs,
-                )
-            elif isinstance(text_or_whole_response, dict):
-                message: dict = create_copy(text_or_whole_response)
-                if "channel" not in message:
-                    message["channel"] = channel or self.channel
-                if "thread_ts" not in message:
-                    message["thread_ts"] = thread_ts or self.thread_ts
-                if "metadata" not in message:
-                    metadata = self.build_metadata() if self.build_metadata is not None else self.metadata
-                    message["metadata"] = metadata
-                return self.client.chat_postMessage(**message)  # type: ignore[union-attr]
-            else:
-                raise ValueError(f"The arg is unexpected type ({type(text_or_whole_response)})")
-        else:
-            raise ValueError("say without channel_id here is unsupported")
-
-
-

Class variables

-
-
var build_metadata : Callable[[], Dict | slack_sdk.models.metadata.Metadata | None] | None
-
-

The type of the None singleton.

-
-
var channel : str | None
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient | None
-
-

The type of the None singleton.

-
-
var metadata : Dict | slack_sdk.models.metadata.Metadata | None
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/say_stream/async_say_stream.html b/docs/reference/context/say_stream/async_say_stream.html deleted file mode 100644 index 3a1978299..000000000 --- a/docs/reference/context/say_stream/async_say_stream.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - -slack_bolt.context.say_stream.async_say_stream API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.say_stream.async_say_stream

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSayStream -(*,
client: slack_sdk.web.async_client.AsyncWebClient,
channel: str | None = None,
recipient_team_id: str | None = None,
recipient_user_id: str | None = None,
thread_ts: str | None = None)
-
-
-
- -Expand source code - -
class AsyncSayStream:
-    client: AsyncWebClient
-    channel: Optional[str]
-    recipient_team_id: Optional[str]
-    recipient_user_id: Optional[str]
-    thread_ts: Optional[str]
-
-    def __init__(
-        self,
-        *,
-        client: AsyncWebClient,
-        channel: Optional[str] = None,
-        recipient_team_id: Optional[str] = None,
-        recipient_user_id: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-    ):
-        self.client = client
-        self.channel = channel
-        self.recipient_team_id = recipient_team_id
-        self.recipient_user_id = recipient_user_id
-        self.thread_ts = thread_ts
-
-    async def __call__(
-        self,
-        *,
-        buffer_size: Optional[int] = None,
-        channel: Optional[str] = None,
-        recipient_team_id: Optional[str] = None,
-        recipient_user_id: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        **kwargs,
-    ) -> AsyncChatStream:
-        """Starts a new chat stream with context."""
-        channel = channel or self.channel
-        thread_ts = thread_ts or self.thread_ts
-        if channel is None:
-            raise ValueError("say_stream without channel here is unsupported")
-        if thread_ts is None:
-            raise ValueError("say_stream without thread_ts here is unsupported")
-
-        if buffer_size is not None:
-            return await self.client.chat_stream(
-                buffer_size=buffer_size,
-                channel=channel,
-                recipient_team_id=recipient_team_id or self.recipient_team_id,
-                recipient_user_id=recipient_user_id or self.recipient_user_id,
-                thread_ts=thread_ts,
-                icon_emoji=icon_emoji,
-                icon_url=icon_url,
-                username=username,
-                **kwargs,
-            )
-        return await self.client.chat_stream(
-            channel=channel,
-            recipient_team_id=recipient_team_id or self.recipient_team_id,
-            recipient_user_id=recipient_user_id or self.recipient_user_id,
-            thread_ts=thread_ts,
-            icon_emoji=icon_emoji,
-            icon_url=icon_url,
-            username=username,
-            **kwargs,
-        )
-
-
-

Class variables

-
-
var channel : str | None
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var recipient_team_id : str | None
-
-

The type of the None singleton.

-
-
var recipient_user_id : str | None
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/say_stream/index.html b/docs/reference/context/say_stream/index.html deleted file mode 100644 index 5ed62587b..000000000 --- a/docs/reference/context/say_stream/index.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - -slack_bolt.context.say_stream API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.say_stream

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.say_stream.async_say_stream
-
-
-
-
slack_bolt.context.say_stream.say_stream
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SayStream -(*,
client: slack_sdk.web.client.WebClient,
channel: str | None = None,
recipient_team_id: str | None = None,
recipient_user_id: str | None = None,
thread_ts: str | None = None)
-
-
-
- -Expand source code - -
class SayStream:
-    client: WebClient
-    channel: Optional[str]
-    recipient_team_id: Optional[str]
-    recipient_user_id: Optional[str]
-    thread_ts: Optional[str]
-
-    def __init__(
-        self,
-        *,
-        client: WebClient,
-        channel: Optional[str] = None,
-        recipient_team_id: Optional[str] = None,
-        recipient_user_id: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-    ):
-        self.client = client
-        self.channel = channel
-        self.recipient_team_id = recipient_team_id
-        self.recipient_user_id = recipient_user_id
-        self.thread_ts = thread_ts
-
-    def __call__(
-        self,
-        *,
-        buffer_size: Optional[int] = None,
-        channel: Optional[str] = None,
-        recipient_team_id: Optional[str] = None,
-        recipient_user_id: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        **kwargs,
-    ) -> ChatStream:
-        """Starts a new chat stream with context."""
-        channel = channel or self.channel
-        thread_ts = thread_ts or self.thread_ts
-        if channel is None:
-            raise ValueError("say_stream without channel here is unsupported")
-        if thread_ts is None:
-            raise ValueError("say_stream without thread_ts here is unsupported")
-
-        if buffer_size is not None:
-            return self.client.chat_stream(
-                buffer_size=buffer_size,
-                channel=channel,
-                recipient_team_id=recipient_team_id or self.recipient_team_id,
-                recipient_user_id=recipient_user_id or self.recipient_user_id,
-                thread_ts=thread_ts,
-                icon_emoji=icon_emoji,
-                icon_url=icon_url,
-                username=username,
-                **kwargs,
-            )
-        return self.client.chat_stream(
-            channel=channel,
-            recipient_team_id=recipient_team_id or self.recipient_team_id,
-            recipient_user_id=recipient_user_id or self.recipient_user_id,
-            thread_ts=thread_ts,
-            icon_emoji=icon_emoji,
-            icon_url=icon_url,
-            username=username,
-            **kwargs,
-        )
-
-
-

Class variables

-
-
var channel : str | None
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var recipient_team_id : str | None
-
-

The type of the None singleton.

-
-
var recipient_user_id : str | None
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/say_stream/say_stream.html b/docs/reference/context/say_stream/say_stream.html deleted file mode 100644 index e7bc33bff..000000000 --- a/docs/reference/context/say_stream/say_stream.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - -slack_bolt.context.say_stream.say_stream API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.say_stream.say_stream

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SayStream -(*,
client: slack_sdk.web.client.WebClient,
channel: str | None = None,
recipient_team_id: str | None = None,
recipient_user_id: str | None = None,
thread_ts: str | None = None)
-
-
-
- -Expand source code - -
class SayStream:
-    client: WebClient
-    channel: Optional[str]
-    recipient_team_id: Optional[str]
-    recipient_user_id: Optional[str]
-    thread_ts: Optional[str]
-
-    def __init__(
-        self,
-        *,
-        client: WebClient,
-        channel: Optional[str] = None,
-        recipient_team_id: Optional[str] = None,
-        recipient_user_id: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-    ):
-        self.client = client
-        self.channel = channel
-        self.recipient_team_id = recipient_team_id
-        self.recipient_user_id = recipient_user_id
-        self.thread_ts = thread_ts
-
-    def __call__(
-        self,
-        *,
-        buffer_size: Optional[int] = None,
-        channel: Optional[str] = None,
-        recipient_team_id: Optional[str] = None,
-        recipient_user_id: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        **kwargs,
-    ) -> ChatStream:
-        """Starts a new chat stream with context."""
-        channel = channel or self.channel
-        thread_ts = thread_ts or self.thread_ts
-        if channel is None:
-            raise ValueError("say_stream without channel here is unsupported")
-        if thread_ts is None:
-            raise ValueError("say_stream without thread_ts here is unsupported")
-
-        if buffer_size is not None:
-            return self.client.chat_stream(
-                buffer_size=buffer_size,
-                channel=channel,
-                recipient_team_id=recipient_team_id or self.recipient_team_id,
-                recipient_user_id=recipient_user_id or self.recipient_user_id,
-                thread_ts=thread_ts,
-                icon_emoji=icon_emoji,
-                icon_url=icon_url,
-                username=username,
-                **kwargs,
-            )
-        return self.client.chat_stream(
-            channel=channel,
-            recipient_team_id=recipient_team_id or self.recipient_team_id,
-            recipient_user_id=recipient_user_id or self.recipient_user_id,
-            thread_ts=thread_ts,
-            icon_emoji=icon_emoji,
-            icon_url=icon_url,
-            username=username,
-            **kwargs,
-        )
-
-
-

Class variables

-
-
var channel : str | None
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var recipient_team_id : str | None
-
-

The type of the None singleton.

-
-
var recipient_user_id : str | None
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/set_status/async_set_status.html b/docs/reference/context/set_status/async_set_status.html deleted file mode 100644 index 770583e4a..000000000 --- a/docs/reference/context/set_status/async_set_status.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - -slack_bolt.context.set_status.async_set_status API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.set_status.async_set_status

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSetStatus -(client: slack_sdk.web.async_client.AsyncWebClient,
channel_id: str,
thread_ts: str)
-
-
-
- -Expand source code - -
class AsyncSetStatus:
-    client: AsyncWebClient
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        client: AsyncWebClient,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    async def __call__(
-        self,
-        status: str,
-        loading_messages: Optional[List[str]] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        **kwargs,
-    ) -> AsyncSlackResponse:
-        return await self.client.assistant_threads_setStatus(
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-            status=status,
-            loading_messages=loading_messages,
-            icon_emoji=icon_emoji,
-            icon_url=icon_url,
-            username=username,
-            **kwargs,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/set_status/index.html b/docs/reference/context/set_status/index.html deleted file mode 100644 index 380e37f4f..000000000 --- a/docs/reference/context/set_status/index.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - -slack_bolt.context.set_status API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.set_status

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.set_status.async_set_status
-
-
-
-
slack_bolt.context.set_status.set_status
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SetStatus -(client: slack_sdk.web.client.WebClient, channel_id: str, thread_ts: str) -
-
-
- -Expand source code - -
class SetStatus:
-    client: WebClient
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        client: WebClient,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    def __call__(
-        self,
-        status: str,
-        loading_messages: Optional[List[str]] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        **kwargs,
-    ) -> SlackResponse:
-        return self.client.assistant_threads_setStatus(
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-            status=status,
-            loading_messages=loading_messages,
-            icon_emoji=icon_emoji,
-            icon_url=icon_url,
-            username=username,
-            **kwargs,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/set_status/set_status.html b/docs/reference/context/set_status/set_status.html deleted file mode 100644 index b0a0a9ee7..000000000 --- a/docs/reference/context/set_status/set_status.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - -slack_bolt.context.set_status.set_status API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.set_status.set_status

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SetStatus -(client: slack_sdk.web.client.WebClient, channel_id: str, thread_ts: str) -
-
-
- -Expand source code - -
class SetStatus:
-    client: WebClient
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        client: WebClient,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    def __call__(
-        self,
-        status: str,
-        loading_messages: Optional[List[str]] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        **kwargs,
-    ) -> SlackResponse:
-        return self.client.assistant_threads_setStatus(
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-            status=status,
-            loading_messages=loading_messages,
-            icon_emoji=icon_emoji,
-            icon_url=icon_url,
-            username=username,
-            **kwargs,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/set_suggested_prompts/async_set_suggested_prompts.html b/docs/reference/context/set_suggested_prompts/async_set_suggested_prompts.html deleted file mode 100644 index 1c7656456..000000000 --- a/docs/reference/context/set_suggested_prompts/async_set_suggested_prompts.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - -slack_bolt.context.set_suggested_prompts.async_set_suggested_prompts API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.set_suggested_prompts.async_set_suggested_prompts

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSetSuggestedPrompts -(client: slack_sdk.web.async_client.AsyncWebClient,
channel_id: str,
thread_ts: str | None = None)
-
-
-
- -Expand source code - -
class AsyncSetSuggestedPrompts:
-    client: AsyncWebClient
-    channel_id: str
-    thread_ts: Optional[str]
-
-    def __init__(
-        self,
-        client: AsyncWebClient,
-        channel_id: str,
-        thread_ts: Optional[str] = None,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    async def __call__(
-        self,
-        prompts: Sequence[Union[str, Dict[str, str]]],
-        title: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-    ) -> AsyncSlackResponse:
-        prompts_arg: List[Dict[str, str]] = []
-        for prompt in prompts:
-            if isinstance(prompt, str):
-                prompts_arg.append({"title": prompt, "message": prompt})
-            else:
-                prompts_arg.append(prompt)
-
-        return await self.client.assistant_threads_setSuggestedPrompts(
-            channel_id=self.channel_id,
-            thread_ts=thread_ts if thread_ts is not None else self.thread_ts,
-            prompts=prompts_arg,
-            title=title,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/set_suggested_prompts/index.html b/docs/reference/context/set_suggested_prompts/index.html deleted file mode 100644 index cf606ae2f..000000000 --- a/docs/reference/context/set_suggested_prompts/index.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - -slack_bolt.context.set_suggested_prompts API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.set_suggested_prompts

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.set_suggested_prompts.async_set_suggested_prompts
-
-
-
-
slack_bolt.context.set_suggested_prompts.set_suggested_prompts
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SetSuggestedPrompts -(client: slack_sdk.web.client.WebClient,
channel_id: str,
thread_ts: str | None = None)
-
-
-
- -Expand source code - -
class SetSuggestedPrompts:
-    client: WebClient
-    channel_id: str
-    thread_ts: Optional[str]
-
-    def __init__(
-        self,
-        client: WebClient,
-        channel_id: str,
-        thread_ts: Optional[str] = None,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    def __call__(
-        self,
-        prompts: Sequence[Union[str, Dict[str, str]]],
-        title: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-    ) -> SlackResponse:
-        prompts_arg: List[Dict[str, str]] = []
-        for prompt in prompts:
-            if isinstance(prompt, str):
-                prompts_arg.append({"title": prompt, "message": prompt})
-            else:
-                prompts_arg.append(prompt)
-
-        return self.client.assistant_threads_setSuggestedPrompts(
-            channel_id=self.channel_id,
-            thread_ts=thread_ts if thread_ts is not None else self.thread_ts,
-            prompts=prompts_arg,
-            title=title,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/set_suggested_prompts/set_suggested_prompts.html b/docs/reference/context/set_suggested_prompts/set_suggested_prompts.html deleted file mode 100644 index f034fc677..000000000 --- a/docs/reference/context/set_suggested_prompts/set_suggested_prompts.html +++ /dev/null @@ -1,142 +0,0 @@ - - - - - - -slack_bolt.context.set_suggested_prompts.set_suggested_prompts API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.set_suggested_prompts.set_suggested_prompts

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SetSuggestedPrompts -(client: slack_sdk.web.client.WebClient,
channel_id: str,
thread_ts: str | None = None)
-
-
-
- -Expand source code - -
class SetSuggestedPrompts:
-    client: WebClient
-    channel_id: str
-    thread_ts: Optional[str]
-
-    def __init__(
-        self,
-        client: WebClient,
-        channel_id: str,
-        thread_ts: Optional[str] = None,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    def __call__(
-        self,
-        prompts: Sequence[Union[str, Dict[str, str]]],
-        title: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-    ) -> SlackResponse:
-        prompts_arg: List[Dict[str, str]] = []
-        for prompt in prompts:
-            if isinstance(prompt, str):
-                prompts_arg.append({"title": prompt, "message": prompt})
-            else:
-                prompts_arg.append(prompt)
-
-        return self.client.assistant_threads_setSuggestedPrompts(
-            channel_id=self.channel_id,
-            thread_ts=thread_ts if thread_ts is not None else self.thread_ts,
-            prompts=prompts_arg,
-            title=title,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/set_title/async_set_title.html b/docs/reference/context/set_title/async_set_title.html deleted file mode 100644 index e7db1ca1c..000000000 --- a/docs/reference/context/set_title/async_set_title.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - -slack_bolt.context.set_title.async_set_title API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.set_title.async_set_title

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSetTitle -(client: slack_sdk.web.async_client.AsyncWebClient,
channel_id: str,
thread_ts: str)
-
-
-
- -Expand source code - -
class AsyncSetTitle:
-    client: AsyncWebClient
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        client: AsyncWebClient,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    async def __call__(self, title: str) -> AsyncSlackResponse:
-        return await self.client.assistant_threads_setTitle(
-            title=title,
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/set_title/index.html b/docs/reference/context/set_title/index.html deleted file mode 100644 index 7ae070fe8..000000000 --- a/docs/reference/context/set_title/index.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - -slack_bolt.context.set_title API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.set_title

-
-
-
-
-

Sub-modules

-
-
slack_bolt.context.set_title.async_set_title
-
-
-
-
slack_bolt.context.set_title.set_title
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SetTitle -(client: slack_sdk.web.client.WebClient, channel_id: str, thread_ts: str) -
-
-
- -Expand source code - -
class SetTitle:
-    client: WebClient
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        client: WebClient,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    def __call__(self, title: str) -> SlackResponse:
-        return self.client.assistant_threads_setTitle(
-            title=title,
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/context/set_title/set_title.html b/docs/reference/context/set_title/set_title.html deleted file mode 100644 index cd4d1e27e..000000000 --- a/docs/reference/context/set_title/set_title.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - -slack_bolt.context.set_title.set_title API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.context.set_title.set_title

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SetTitle -(client: slack_sdk.web.client.WebClient, channel_id: str, thread_ts: str) -
-
-
- -Expand source code - -
class SetTitle:
-    client: WebClient
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        client: WebClient,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    def __call__(self, title: str) -> SlackResponse:
-        return self.client.assistant_threads_setTitle(
-            title=title,
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/error/index.html b/docs/reference/error/index.html deleted file mode 100644 index 9a9998e63..000000000 --- a/docs/reference/error/index.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - -slack_bolt.error API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.error

-
-
-

Bolt specific error types.

-
-
-
-
-
-
-
-
-

Classes

-
-
-class BoltError -(*args, **kwargs) -
-
-
- -Expand source code - -
class BoltError(Exception):
-    """General class in a Bolt app"""
-
-

General class in a Bolt app

-

Ancestors

-
    -
  • builtins.Exception
  • -
  • builtins.BaseException
  • -
-

Subclasses

- -
-
-class BoltUnhandledRequestError -(*,
request: BoltRequest | AsyncBoltRequest,
current_response: BoltResponse | None,
last_global_middleware_name: str | None = None)
-
-
-
- -Expand source code - -
class BoltUnhandledRequestError(BoltError):
-    request: "BoltRequest"  # type: ignore[name-defined]
-    body: dict
-    current_response: Optional["BoltResponse"]  # type: ignore[name-defined]
-    last_global_middleware_name: Optional[str]
-
-    def __init__(
-        self,
-        *,
-        request: Union["BoltRequest", "AsyncBoltRequest"],  # type: ignore[name-defined]
-        current_response: Optional["BoltResponse"],  # type: ignore[name-defined]
-        last_global_middleware_name: Optional[str] = None,
-    ):
-        self.request = request
-        self.body = request.body if request is not None else {}
-        self.current_response = current_response
-        self.last_global_middleware_name = last_global_middleware_name
-
-    def __str__(self) -> str:
-        return "unhandled request error"
-
-

General class in a Bolt app

-

Ancestors

-
    -
  • BoltError
  • -
  • builtins.Exception
  • -
  • builtins.BaseException
  • -
-

Class variables

-
-
var body : dict
-
-

The type of the None singleton.

-
-
var current_response : BoltResponse | None
-
-

The type of the None singleton.

-
-
var last_global_middleware_name : str | None
-
-

The type of the None singleton.

-
-
var request : BoltRequest
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/index.html b/docs/reference/index.html deleted file mode 100644 index ac1666851..000000000 --- a/docs/reference/index.html +++ /dev/null @@ -1,6449 +0,0 @@ - - - - - - -slack_bolt API documentation - - - - - - - - - - - -
-
-
-

Package slack_bolt

-
-
-

A Python framework to build Slack apps in a flash with the latest platform features.Read the getting started guide and look at our code examples to learn how to build apps using Bolt.

- -
-
-

Sub-modules

-
-
slack_bolt.adapter
-
-

Adapter modules for running Bolt apps along with Web frameworks or Socket Mode.

-
-
slack_bolt.app
-
-

Application interface in Bolt …

-
-
slack_bolt.async_app
-
-

Module for creating asyncio based apps …

-
-
slack_bolt.authorization
-
-

Authorization is the process of determining which Slack credentials should be available -while processing an incoming Slack event …

-
-
slack_bolt.context
-
-

All listeners have access to a context dictionary, which can be used to enrich events with additional information. -Bolt automatically attaches …

-
-
slack_bolt.error
-
-

Bolt specific error types.

-
-
slack_bolt.kwargs_injection
-
-

For middleware/listener arguments, Bolt does flexible data injection in accordance with their names …

-
-
slack_bolt.lazy_listener
-
-

Lazy listener runner is a beta feature for the apps running on Function-as-a-Service platforms …

-
-
slack_bolt.listener
-
-

Listeners process an incoming request from Slack if the request's type or data structure matches -the predefined conditions of the listener. Typically, …

-
-
slack_bolt.listener_matcher
-
-

A listener matcher is a simplified version of listener middleware. -A listener matcher function returns bool value instead of next() method …

-
-
slack_bolt.logger
-
-

Bolt for Python relies on the standard logging module.

-
-
slack_bolt.middleware
-
-

A middleware processes request data and calls next() method -if the execution chain should continue running the following middleware …

-
-
slack_bolt.oauth
-
-

Slack OAuth flow support for building an app that is installable in any workspaces …

-
-
slack_bolt.request
-
-

Incoming request from Slack through either HTTP request or Socket Mode connection …

-
-
slack_bolt.response
-
-

This interface represents Bolt's synchronous response to Slack …

-
-
slack_bolt.util
-
-

Internal utilities for the Bolt framework.

-
-
slack_bolt.version
-
-

Check the latest version at https://pypi.org/project/slack-bolt/

-
-
slack_bolt.workflows
-
-

Steps from apps enables developers to build their own steps …

-
-
-
-
-
-
-
-
-

Classes

-
-
-class Ack -
-
-
- -Expand source code - -
class Ack:
-    response: Optional[BoltResponse]
-
-    def __init__(self):
-        self.response: Optional[BoltResponse] = None
-
-    def __call__(
-        self,
-        text: Union[str, dict] = "",  # text: str or whole_response: dict
-        blocks: Optional[Sequence[Union[dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[dict, Attachment]]] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        response_type: Optional[str] = None,  # in_channel / ephemeral
-        # block_suggestion / dialog_suggestion
-        options: Optional[Sequence[Union[dict, Option]]] = None,
-        option_groups: Optional[Sequence[Union[dict, OptionGroup]]] = None,
-        # view_submission
-        response_action: Optional[str] = None,  # errors / update / push / clear
-        errors: Optional[Dict[str, str]] = None,
-        view: Optional[Union[dict, View]] = None,
-    ) -> BoltResponse:
-        return _set_response(
-            self,
-            text_or_whole_response=text,
-            blocks=blocks,
-            attachments=attachments,
-            unfurl_links=unfurl_links,
-            unfurl_media=unfurl_media,
-            response_type=response_type,
-            options=options,
-            option_groups=option_groups,
-            response_action=response_action,
-            errors=errors,
-            view=view,
-        )
-
-
-

Class variables

-
-
var responseBoltResponse | None
-
-

The type of the None singleton.

-
-
-
-
-class App -(*,
logger: logging.Logger | None = None,
name: str | None = None,
process_before_response: bool = False,
raise_error_for_unhandled_request: bool = False,
signing_secret: str | None = None,
token: str | None = None,
token_verification_enabled: bool = True,
client: slack_sdk.web.client.WebClient | None = None,
before_authorize: Middleware | Callable[..., Any] | None = None,
authorize: Callable[..., AuthorizeResult] | None = None,
user_facing_authorize_error_message: str | None = None,
installation_store: slack_sdk.oauth.installation_store.installation_store.InstallationStore | None = None,
installation_store_bot_only: bool | None = None,
request_verification_enabled: bool = True,
ignoring_self_events_enabled: bool = True,
ignoring_self_assistant_message_events_enabled: bool = True,
ssl_check_enabled: bool = True,
url_verification_enabled: bool = True,
attaching_function_token_enabled: bool = True,
oauth_settings: OAuthSettings | None = None,
oauth_flow: OAuthFlow | None = None,
verification_token: str | None = None,
listener_executor: concurrent.futures._base.Executor | None = None,
assistant_thread_context_store: AssistantThreadContextStore | None = None,
attaching_conversation_kwargs_enabled: bool = True)
-
-
-
- -Expand source code - -
class App:
-    def __init__(
-        self,
-        *,
-        logger: Optional[logging.Logger] = None,
-        # Used in logger
-        name: Optional[str] = None,
-        # Set True when you run this app on a FaaS platform
-        process_before_response: bool = False,
-        # Set True if you want to handle an unhandled request as an exception
-        raise_error_for_unhandled_request: bool = False,
-        # Basic Information > Credentials > Signing Secret
-        signing_secret: Optional[str] = None,
-        # for single-workspace apps
-        token: Optional[str] = None,
-        token_verification_enabled: bool = True,
-        client: Optional[WebClient] = None,
-        # for multi-workspace apps
-        before_authorize: Optional[Union[Middleware, Callable[..., Any]]] = None,
-        authorize: Optional[Callable[..., AuthorizeResult]] = None,
-        user_facing_authorize_error_message: Optional[str] = None,
-        installation_store: Optional[InstallationStore] = None,
-        # for either only bot scope usage or v1.0.x compatibility
-        installation_store_bot_only: Optional[bool] = None,
-        # for customizing the built-in middleware
-        request_verification_enabled: bool = True,
-        ignoring_self_events_enabled: bool = True,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-        ssl_check_enabled: bool = True,
-        url_verification_enabled: bool = True,
-        attaching_function_token_enabled: bool = True,
-        # for the OAuth flow
-        oauth_settings: Optional[OAuthSettings] = None,
-        oauth_flow: Optional[OAuthFlow] = None,
-        # No need to set (the value is used only in response to ssl_check requests)
-        verification_token: Optional[str] = None,
-        # Set this one only when you want to customize the executor
-        listener_executor: Optional[Executor] = None,
-        # for AI Agents & Assistants
-        assistant_thread_context_store: Optional[AssistantThreadContextStore] = None,
-        attaching_conversation_kwargs_enabled: bool = True,
-    ):
-        """Bolt App that provides functionalities to register middleware/listeners.
-
-            import os
-            from slack_bolt import App
-
-            # Initializes your app with your bot token and signing secret
-            app = App(
-                token=os.environ.get("SLACK_BOT_TOKEN"),
-                signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
-            )
-
-            # Listens to incoming messages that contain "hello"
-            @app.message("hello")
-            def message_hello(message, say):
-                # say() sends a message to the channel where the event was triggered
-                say(f"Hey there <@{message['user']}>!")
-
-            # Start your app
-            if __name__ == "__main__":
-                app.start(port=int(os.environ.get("PORT", 3000)))
-
-        Refer to https://docs.slack.dev/tools/bolt-python/creating-an-app for details.
-
-        If you would like to build an OAuth app for enabling the app to run with multiple workspaces,
-        refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app.
-
-        Args:
-            logger: The custom logger that can be used in this app.
-            name: The application name that will be used in logging. If absent, the source file name will be used.
-            process_before_response: True if this app runs on Function as a Service. (Default: False)
-            raise_error_for_unhandled_request: True if you want to raise exceptions for unhandled requests
-                and use @app.error listeners instead of
-                the built-in handler, which pints warning logs and returns 404 to Slack (Default: False)
-            signing_secret: The Signing Secret value used for verifying requests from Slack.
-            token: The bot/user access token required only for single-workspace app.
-            token_verification_enabled: Verifies the validity of the given token if True.
-            client: The singleton `slack_sdk.WebClient` instance for this app.
-            before_authorize: A global middleware that can be executed right before authorize function
-            authorize: The function to authorize an incoming request from Slack
-                by checking if there is a team/user in the installation data.
-            user_facing_authorize_error_message: The user-facing error message to display
-                when the app is installed but the installation is not managed by this app's installation store
-            installation_store: The module offering save/find operations of installation data
-            installation_store_bot_only: Use `InstallationStore#find_bot()` if True (Default: False)
-            request_verification_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `RequestVerification` is a built-in middleware that verifies the signature in HTTP Mode requests.
-                Make sure if it's safe enough when you turn a built-in middleware off.
-                We strongly recommend using RequestVerification for better security.
-                If you have a proxy that verifies request signature in front of the Bolt app,
-                it's totally fine to disable RequestVerification to avoid duplication of work.
-                Don't turn it off just for easiness of development.
-            ignoring_self_events_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `IgnoringSelfEvents` is a built-in middleware that enables Bolt apps to easily skip the events
-                generated by this app's bot user (this is useful for avoiding code error causing an infinite loop).
-            ignoring_self_assistant_message_events_enabled: False if you would like to disable the built-in middleware.
-                `IgnoringSelfEvents` for this app's bot user message events within an assistant thread
-                This is useful for avoiding code error causing an infinite loop; Default: True
-            url_verification_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `UrlVerification` is a built-in middleware that handles url_verification requests
-                that verify the endpoint for Events API in HTTP Mode requests.
-            attaching_function_token_enabled: False if you would like to disable the built-in middleware (Default: True).
-                `AttachingFunctionToken` is a built-in middleware that injects the just-in-time workflow-execution tokens
-                when your app receives `function_executed` or interactivity events scoped to a custom step.
-            ssl_check_enabled: bool = False if you would like to disable the built-in middleware (Default: True).
-                `SslCheck` is a built-in middleware that handles ssl_check requests from Slack.
-            oauth_settings: The settings related to Slack app installation flow (OAuth flow)
-            oauth_flow: Instantiated `slack_bolt.oauth.OAuthFlow`. This is always prioritized over oauth_settings.
-            verification_token: Deprecated verification mechanism. This can be used only for ssl_check requests.
-            listener_executor: Custom executor to run background tasks. If absent, the default `ThreadPoolExecutor` will
-                be used.
-            assistant_thread_context_store: Custom AssistantThreadContext store (Default: the built-in implementation,
-                which uses a parent message's metadata to store the latest context)
-        """
-        if signing_secret is None:
-            signing_secret = os.environ.get("SLACK_SIGNING_SECRET", "")
-        token = token or os.environ.get("SLACK_BOT_TOKEN")
-
-        self._name: str = name or inspect.stack()[1].filename.split(os.path.sep)[-1]
-        self._signing_secret: str = signing_secret
-
-        self._verification_token: Optional[str] = verification_token or os.environ.get("SLACK_VERIFICATION_TOKEN", None)
-        # If a logger is explicitly passed when initializing, the logger works as the base logger.
-        # The base logger's logging settings will be propagated to all the loggers created by bolt-python.
-        self._base_logger = logger
-        # The framework logger is supposed to be used for the internal logging.
-        # Also, it's accessible via `app.logger` as the app's singleton logger.
-        self._framework_logger = logger or get_bolt_logger(App)
-        self._raise_error_for_unhandled_request = raise_error_for_unhandled_request
-
-        self._token: Optional[str] = token
-
-        if client is not None:
-            if not isinstance(client, WebClient):
-                raise BoltError(error_client_invalid_type())
-            self._client = client
-            self._token = client.token
-            if token is not None:
-                self._framework_logger.warning(warning_client_prioritized_and_token_skipped())
-        else:
-            self._client = create_web_client(
-                # NOTE: the token here can be None
-                token=token,
-                logger=self._framework_logger,
-            )
-
-        # --------------------------------------
-        # Authorize & OAuthFlow initialization
-        # --------------------------------------
-
-        self._before_authorize: Optional[Middleware] = None
-        if before_authorize is not None:
-            if callable(before_authorize):
-                self._before_authorize = CustomMiddleware(
-                    app_name=self._name,
-                    func=before_authorize,
-                    base_logger=self._framework_logger,
-                )
-            elif isinstance(before_authorize, Middleware):
-                self._before_authorize = before_authorize
-
-        self._authorize: Optional[Authorize] = None
-        if authorize is not None:
-            if isinstance(authorize, Authorize):
-                # As long as an advanced developer understands what they're doing,
-                # bolt-python should not prevent customizing authorize middleware
-                self._authorize = authorize
-            else:
-                if oauth_settings is not None or oauth_flow is not None:
-                    # If the given authorize is a simple function,
-                    # it does not work along with installation_store.
-                    raise BoltError(error_authorize_conflicts())
-                self._authorize = CallableAuthorize(logger=self._framework_logger, func=authorize)
-
-        self._installation_store: Optional[InstallationStore] = installation_store
-        if self._installation_store is not None and self._authorize is None:
-            settings = oauth_flow.settings if oauth_flow is not None else oauth_settings
-            self._authorize = InstallationStoreAuthorize(
-                installation_store=self._installation_store,
-                client_id=settings.client_id if settings is not None else None,
-                client_secret=settings.client_secret if settings is not None else None,
-                logger=self._framework_logger,
-                bot_only=installation_store_bot_only or False,
-                client=self._client,  # for proxy use cases etc.
-                user_token_resolution=(settings.user_token_resolution if settings is not None else "authed_user"),
-            )
-
-        self._oauth_flow: Optional[OAuthFlow] = None
-
-        if (
-            oauth_settings is None
-            and os.environ.get("SLACK_CLIENT_ID") is not None
-            and os.environ.get("SLACK_CLIENT_SECRET") is not None
-        ):
-            # initialize with the default settings
-            oauth_settings = OAuthSettings()
-
-            if oauth_flow is None and installation_store is None:
-                # show info-level log for avoiding confusions
-                self._framework_logger.info(info_default_oauth_settings_loaded())
-
-        if oauth_flow is not None:
-            self._oauth_flow = oauth_flow
-            installation_store = select_consistent_installation_store(
-                client_id=self._oauth_flow.client_id,
-                app_store=self._installation_store,
-                oauth_flow_store=self._oauth_flow.settings.installation_store,
-                logger=self._framework_logger,
-            )
-            self._installation_store = installation_store
-            if installation_store is not None:
-                self._oauth_flow.settings.installation_store = installation_store
-
-            if self._oauth_flow._client is None:
-                self._oauth_flow._client = self._client
-            if self._authorize is None:
-                self._authorize = self._oauth_flow.settings.authorize
-        elif oauth_settings is not None:
-            installation_store = select_consistent_installation_store(
-                client_id=oauth_settings.client_id,
-                app_store=self._installation_store,
-                oauth_flow_store=oauth_settings.installation_store,
-                logger=self._framework_logger,
-            )
-            self._installation_store = installation_store
-            if installation_store is not None:
-                oauth_settings.installation_store = installation_store
-            self._oauth_flow = OAuthFlow(client=self.client, logger=self.logger, settings=oauth_settings)
-            if self._authorize is None:
-                self._authorize = self._oauth_flow.settings.authorize
-            self._authorize.token_rotation_expiration_minutes = oauth_settings.token_rotation_expiration_minutes  # type: ignore[attr-defined] # noqa: E501
-
-        if (self._installation_store is not None or self._authorize is not None) and self._token is not None:
-            self._token = None
-            self._framework_logger.warning(warning_token_skipped())
-
-        # after setting bot_only here, __init__ cannot replace authorize function
-        if installation_store_bot_only is not None and self._oauth_flow is not None:
-            app_bot_only = installation_store_bot_only or False
-            oauth_flow_bot_only = self._oauth_flow.settings.installation_store_bot_only
-            if app_bot_only != oauth_flow_bot_only:
-                self.logger.warning(warning_bot_only_conflicts())
-                self._oauth_flow.settings.installation_store_bot_only = app_bot_only
-                self._authorize.bot_only = app_bot_only  # type: ignore[union-attr]
-
-        self._tokens_revocation_listeners: Optional[TokenRevocationListeners] = None
-        if self._installation_store is not None:
-            self._tokens_revocation_listeners = TokenRevocationListeners(self._installation_store)
-
-        # --------------------------------------
-        # Middleware Initialization
-        # --------------------------------------
-
-        self._middleware_list: List[Middleware] = []
-        self._listeners: List[Listener] = []
-
-        if listener_executor is None:
-            listener_executor = ThreadPoolExecutor(max_workers=5)
-
-        self._assistant_thread_context_store = assistant_thread_context_store
-        self._attaching_conversation_kwargs_enabled = attaching_conversation_kwargs_enabled
-
-        self._process_before_response = process_before_response
-        self._listener_runner = ThreadListenerRunner(
-            logger=self._framework_logger,
-            process_before_response=process_before_response,
-            listener_error_handler=DefaultListenerErrorHandler(logger=self._framework_logger),
-            listener_start_handler=DefaultListenerStartHandler(logger=self._framework_logger),
-            listener_completion_handler=DefaultListenerCompletionHandler(logger=self._framework_logger),
-            listener_executor=listener_executor,
-            lazy_listener_runner=ThreadLazyListenerRunner(
-                logger=self._framework_logger,
-                executor=listener_executor,
-            ),
-        )
-        self._middleware_error_handler: MiddlewareErrorHandler = DefaultMiddlewareErrorHandler(
-            logger=self._framework_logger,
-        )
-
-        self._init_middleware_list_done = False
-        self._init_middleware_list(
-            token_verification_enabled=token_verification_enabled,
-            request_verification_enabled=request_verification_enabled,
-            ignoring_self_events_enabled=ignoring_self_events_enabled,
-            ignoring_self_assistant_message_events_enabled=ignoring_self_assistant_message_events_enabled,
-            ssl_check_enabled=ssl_check_enabled,
-            url_verification_enabled=url_verification_enabled,
-            attaching_function_token_enabled=attaching_function_token_enabled,
-            user_facing_authorize_error_message=user_facing_authorize_error_message,
-        )
-
-    def _init_middleware_list(
-        self,
-        token_verification_enabled: bool = True,
-        request_verification_enabled: bool = True,
-        ignoring_self_events_enabled: bool = True,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-        ssl_check_enabled: bool = True,
-        url_verification_enabled: bool = True,
-        attaching_function_token_enabled: bool = True,
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        if self._init_middleware_list_done:
-            return
-        if ssl_check_enabled is True:
-            self._middleware_list.append(
-                SslCheck(
-                    verification_token=self._verification_token,
-                    base_logger=self._base_logger,
-                )
-            )
-        if request_verification_enabled is True:
-            self._middleware_list.append(RequestVerification(self._signing_secret, base_logger=self._base_logger))
-
-        if self._before_authorize is not None:
-            self._middleware_list.append(self._before_authorize)
-
-        # As authorize is required for making a Bolt app function, we don't offer the flag to disable this
-        if self._oauth_flow is None:
-            if self._token is not None:
-                try:
-                    auth_test_result = None
-                    if token_verification_enabled:
-                        # This API call is for eagerly validating the token
-                        auth_test_result = self._client.auth_test(token=self._token)
-                    self._middleware_list.append(
-                        SingleTeamAuthorization(
-                            auth_test_result=auth_test_result,
-                            base_logger=self._base_logger,
-                            user_facing_authorize_error_message=user_facing_authorize_error_message,
-                        )
-                    )
-                except SlackApiError as err:
-                    raise BoltError(error_auth_test_failure(err.response))
-            elif self._authorize is not None:
-                self._middleware_list.append(
-                    MultiTeamsAuthorization(
-                        authorize=self._authorize,
-                        base_logger=self._base_logger,
-                        user_facing_authorize_error_message=user_facing_authorize_error_message,
-                    )
-                )
-            else:
-                raise BoltError(error_token_required())
-        elif self._authorize is not None:
-            self._middleware_list.append(
-                MultiTeamsAuthorization(
-                    authorize=self._authorize,
-                    base_logger=self._base_logger,
-                    user_token_resolution=self._oauth_flow.settings.user_token_resolution,
-                    user_facing_authorize_error_message=user_facing_authorize_error_message,
-                )
-            )
-        else:
-            raise BoltError(error_oauth_flow_or_authorize_required())
-
-        if ignoring_self_events_enabled is True:
-            self._middleware_list.append(
-                IgnoringSelfEvents(
-                    base_logger=self._base_logger,
-                    ignoring_self_assistant_message_events_enabled=ignoring_self_assistant_message_events_enabled,
-                )
-            )
-        if url_verification_enabled is True:
-            self._middleware_list.append(UrlVerification(base_logger=self._base_logger))
-        if attaching_function_token_enabled is True:
-            self._middleware_list.append(AttachingFunctionToken())
-        self._init_middleware_list_done = True
-
-    # -------------------------
-    # accessors
-
-    @property
-    def name(self) -> str:
-        """The name of this app (default: the filename)"""
-        return self._name
-
-    @property
-    def oauth_flow(self) -> Optional[OAuthFlow]:
-        """Configured `OAuthFlow` object if exists."""
-        return self._oauth_flow
-
-    @property
-    def logger(self) -> logging.Logger:
-        """The logger this app uses."""
-        return self._framework_logger
-
-    @property
-    def client(self) -> WebClient:
-        """The singleton `slack_sdk.WebClient` instance in this app."""
-        return self._client
-
-    @property
-    def installation_store(self) -> Optional[InstallationStore]:
-        """The `slack_sdk.oauth.InstallationStore` that can be used in the `authorize` middleware."""
-        return self._installation_store
-
-    @property
-    def listener_runner(self) -> ThreadListenerRunner:
-        """The thread executor for asynchronously running listeners."""
-        return self._listener_runner
-
-    @property
-    def process_before_response(self) -> bool:
-        return self._process_before_response or False
-
-    # -------------------------
-    # standalone server
-
-    def start(
-        self,
-        port: int = 3000,
-        path: str = "/slack/events",
-        http_server_logger_enabled: bool = True,
-    ) -> None:
-        """Starts a web server for local development.
-
-            # With the default settings, `http://localhost:3000/slack/events`
-            # is available for handling incoming requests from Slack
-            app.start()
-
-        This method internally starts a Web server process built with the `http.server` module.
-        For production, consider using a production-ready WSGI server such as Gunicorn.
-
-        Args:
-            port: The port to listen on (Default: 3000)
-            path: The path to handle request from Slack (Default: `/slack/events`)
-            http_server_logger_enabled: The flag to enable http.server logging if True (Default: True)
-        """
-        self._development_server = SlackAppDevelopmentServer(
-            port=port,
-            path=path,
-            app=self,
-            oauth_flow=self.oauth_flow,
-            http_server_logger_enabled=http_server_logger_enabled,
-        )
-        self._development_server.start()
-
-    # -------------------------
-    # main dispatcher
-
-    def dispatch(self, req: BoltRequest) -> BoltResponse:
-        """Applies all middleware and dispatches an incoming request from Slack to the right code path.
-
-        Args:
-            req: An incoming request from Slack
-
-        Returns:
-            The response generated by this Bolt app
-        """
-        starting_time = time.time()
-        self._init_context(req)
-
-        resp: Optional[BoltResponse] = BoltResponse(status=200, body="")
-        middleware_state = {"next_called": False}
-
-        def middleware_next():
-            middleware_state["next_called"] = True
-
-        try:
-            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)  # type: ignore[arg-type]
-                if not middleware_state["next_called"]:
-                    if resp is None:
-                        # next() method was not called without providing the response to return to Slack
-                        # This should not be an intentional handling in usual use cases.
-                        resp = BoltResponse(status=404, body={"error": "no next() calls in middleware"})
-                        if self._raise_error_for_unhandled_request is True:
-                            try:
-                                raise BoltUnhandledRequestError(
-                                    request=req,
-                                    current_response=resp,
-                                    last_global_middleware_name=middleware.name,
-                                )
-                            except BoltUnhandledRequestError as e:
-                                self._listener_runner.listener_error_handler.handle(
-                                    error=e,
-                                    request=req,
-                                    response=resp,
-                                )
-                            return resp
-                        self._framework_logger.warning(warning_unhandled_by_global_middleware(middleware.name, req))
-                        return resp
-                    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):  # type: ignore[arg-type]
-                    # run all the middleware attached to this listener first
-                    middleware_resp, next_was_not_called = listener.run_middleware(
-                        req=req, resp=resp  # type: ignore[arg-type]
-                    )
-                    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,  # type: ignore[arg-type]
-                        listener_name=listener_name,
-                        listener=listener,
-                    )
-                    if listener_response is not None:
-                        return listener_response
-
-            if resp is None:
-                resp = BoltResponse(status=404, body={"error": "unhandled request"})
-            if self._raise_error_for_unhandled_request is True:
-                try:
-                    raise BoltUnhandledRequestError(
-                        request=req,
-                        current_response=resp,
-                    )
-                except BoltUnhandledRequestError as e:
-                    self._listener_runner.listener_error_handler.handle(
-                        error=e,
-                        request=req,
-                        response=resp,
-                    )
-                return resp
-            return self._handle_unmatched_requests(req, resp)
-        except Exception as error:
-            resp = BoltResponse(status=500, body="")
-            self._middleware_error_handler.handle(
-                error=error,
-                request=req,
-                response=resp,
-            )
-            return resp
-
-    def _handle_unmatched_requests(self, req: BoltRequest, resp: BoltResponse) -> BoltResponse:
-        self._framework_logger.warning(warning_unhandled_request(req))
-        return resp
-
-    # -------------------------
-    # middleware
-
-    def use(self, *args) -> Optional[Callable]:
-        """Registers a new global middleware to this app. This method can be used as either a decorator or a method.
-
-        Refer to `App#middleware()` method's docstring for details."""
-        return self.middleware(*args)
-
-    def middleware(self, *args) -> Optional[Callable]:
-        """Registers a new middleware to this app.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.middleware
-            def middleware_func(logger, body, next):
-                logger.info(f"request body: {body}")
-                next()
-
-            # Pass a function to this method
-            app.middleware(middleware_func)
-
-        Refer to https://docs.slack.dev/tools/bolt-python/concepts/global-middleware for details.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            *args: A function that works as a global middleware.
-        """
-        if len(args) > 0:
-            middleware_or_callable = args[0]
-            if isinstance(middleware_or_callable, Middleware):
-                middleware: Middleware = middleware_or_callable
-                self._middleware_list.append(middleware)
-                if isinstance(middleware, Assistant) and middleware.thread_context_store is not None:
-                    self._assistant_thread_context_store = middleware.thread_context_store
-            elif callable(middleware_or_callable):
-                self._middleware_list.append(
-                    CustomMiddleware(
-                        app_name=self.name,
-                        func=middleware_or_callable,
-                        base_logger=self._base_logger,
-                    )
-                )
-                return middleware_or_callable
-            else:
-                raise BoltError(f"Unexpected type for a middleware ({type(middleware_or_callable)})")
-        return None
-
-    # -------------------------
-    # AI Agents & Assistants
-
-    def assistant(self, assistant: Assistant) -> Optional[Callable]:
-        return self.middleware(assistant)
-
-    # -------------------------
-    # Workflows: Steps from apps
-
-    def step(
-        self,
-        callback_id: Union[str, Pattern, WorkflowStep, WorkflowStepBuilder],
-        edit: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-        save: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-        execute: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Registers a new step from app listener.
-
-        Unlike others, this method doesn't behave as a decorator.
-        If you want to register a step from app by a decorator, use `WorkflowStepBuilder`'s methods.
-
-            # Create a new WorkflowStep instance
-            from slack_bolt.workflows.step import WorkflowStep
-            ws = WorkflowStep(
-                callback_id="add_task",
-                edit=edit,
-                save=save,
-                execute=execute,
-            )
-            # Pass Step to set up listeners
-            app.step(ws)
-
-        Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        For further information about WorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            callback_id: The Callback ID for this step from app
-            edit: The function for displaying a modal in the Workflow Builder
-            save: The function for handling configuration in the Workflow Builder
-            execute: The function for handling the step execution
-        """
-        warnings.warn(
-            (
-                "Steps from apps for legacy workflows are now deprecated. "
-                "Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/"
-            ),
-            category=DeprecationWarning,
-        )
-        step = callback_id
-        if isinstance(callback_id, (str, Pattern)):
-            step = WorkflowStep(
-                callback_id=callback_id,
-                edit=edit,  # type: ignore[arg-type]
-                save=save,  # type: ignore[arg-type]
-                execute=execute,  # type: ignore[arg-type]
-                base_logger=self._base_logger,
-            )
-        elif isinstance(step, WorkflowStepBuilder):
-            step = step.build(base_logger=self._base_logger)
-        elif not isinstance(step, WorkflowStep):
-            raise BoltError(f"Invalid step object ({type(step)})")
-
-        self.use(WorkflowStepMiddleware(step))
-
-    # -------------------------
-    # global error handler
-
-    def error(self, func: Callable[..., Optional[BoltResponse]]) -> Callable[..., Optional[BoltResponse]]:
-        """Updates the global error handler. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.error
-            def custom_error_handler(error, body, logger):
-                logger.exception(f"Error: {error}")
-                logger.info(f"Request body: {body}")
-
-            # Pass a function to this method
-            app.error(custom_error_handler)
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            func: The function that is supposed to be executed
-                when getting an unhandled error in Bolt app.
-        """
-        self._listener_runner.listener_error_handler = CustomListenerErrorHandler(
-            logger=self._framework_logger,
-            func=func,
-        )
-        self._middleware_error_handler = CustomMiddlewareErrorHandler(
-            logger=self._framework_logger,
-            func=func,
-        )
-        return func
-
-    # -------------------------
-    # events
-
-    def event(
-        self,
-        event: Union[
-            str,
-            Pattern,
-            Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]],
-        ],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new event listener. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.event("team_join")
-            def ask_for_introduction(event, say):
-                welcome_channel_id = "C12345"
-                user_id = event["user"]
-                text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-                say(text=text, channel=welcome_channel_id)
-
-            # Pass a function to this method
-            app.event("team_join")(ask_for_introduction)
-
-        Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            event: The conditions that match a request payload.
-                If you pass a dict for this, you can have type, subtype in the constraint.
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.event(event, base_logger=self._base_logger)
-            if self._attaching_conversation_kwargs_enabled:
-                middleware.insert(0, AttachingConversationKwargs(self._assistant_thread_context_store))
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-        return __call__
-
-    def message(
-        self,
-        keyword: Union[str, Pattern] = "",
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new message event listener. This method can be used as either a decorator or a method.
-        Check the `App#event` method's docstring for details.
-
-            # Use this method as a decorator
-            @app.message(":wave:")
-            def say_hello(message, say):
-                user = message['user']
-                say(f"Hi there, <@{user}>!")
-
-            # Pass a function to this method
-            app.message(":wave:")(say_hello)
-
-        Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            keyword: The keyword to match
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-        matchers = list(matchers) if matchers else []
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            constraints = {
-                "type": "message",
-                "subtype": (
-                    # In most cases, new message events come with no subtype.
-                    None,
-                    # As of Jan 2021, most bot messages no longer have the subtype bot_message.
-                    # By contrast, messages posted using classic app's bot token still have the subtype.
-                    "bot_message",
-                    # If an end-user posts a message with "Also send to #channel" checked,
-                    # the message event comes with this subtype.
-                    "thread_broadcast",
-                    # If an end-user posts a message with attached files,
-                    # the message event comes with this subtype.
-                    "file_share",
-                ),
-            }
-            primary_matcher = builtin_matchers.message_event(
-                keyword=keyword, constraints=constraints, base_logger=self._base_logger
-            )
-            if self._attaching_conversation_kwargs_enabled:
-                middleware.insert(0, AttachingConversationKwargs(self._assistant_thread_context_store))
-            middleware.insert(0, MessageListenerMatches(keyword))
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-        return __call__
-
-    def function(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-        auto_acknowledge: bool = True,
-        ack_timeout: int = 3,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new Function listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.function("reverse")
-            def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail):
-                try:
-                    ack()
-                    string_to_reverse = inputs["stringToReverse"]
-                    complete(outputs={"reverseString": string_to_reverse[::-1]})
-                except Exception as e:
-                    fail(f"Cannot reverse string (error: {e})")
-                    raise e
-
-            # Pass a function to this method
-            app.function("reverse")(reverse_string)
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            callback_id: The callback id to identify the function
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        if auto_acknowledge is True:
-            if ack_timeout != 3:
-                self._framework_logger.warning(warning_ack_timeout_has_no_effect(callback_id, ack_timeout))
-
-        matchers = list(matchers) if matchers else []
-        middleware = list(middleware) if middleware else []
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.function_executed(callback_id=callback_id, base_logger=self._base_logger)
-            return self._register_listener(functions, primary_matcher, matchers, middleware, auto_acknowledge, ack_timeout)
-
-        return __call__
-
-    # -------------------------
-    # slash commands
-
-    def command(
-        self,
-        command: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new slash command listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.command("/echo")
-            def repeat_text(ack, say, command):
-                # Acknowledge command request
-                ack()
-                say(f"{command['text']}")
-
-            # Pass a function to this method
-            app.command("/echo")(repeat_text)
-
-        Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            command: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.command(command, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # shortcut
-
-    def shortcut(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new shortcut listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.shortcut("open_modal")
-            def open_modal(ack, body, client):
-                # Acknowledge the command request
-                ack()
-                # Call views_open with the built-in client
-                client.views_open(
-                    # Pass a valid trigger_id within 3 seconds of receiving it
-                    trigger_id=body["trigger_id"],
-                    # View payload
-                    view={ ... }
-                )
-
-            # Pass a function to this method
-            app.shortcut("open_modal")(open_modal)
-
-        Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload.
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.shortcut(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def global_shortcut(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new global shortcut listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.global_shortcut(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def message_shortcut(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new message shortcut listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.message_shortcut(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # action
-
-    def action(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new action listener. This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.action("approve_button")
-            def update_message(ack):
-                ack()
-
-            # Pass a function to this method
-            app.action("approve_button")(update_message)
-
-        * Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`.
-        * Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`.
-        * Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.action(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def block_action(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `block_actions` action listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.block_action(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def attachment_action(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `interactive_message` action listener.
-        Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.attachment_action(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_submission(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `dialog_submission` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_submission(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_cancellation(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `dialog_cancellation` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_cancellation(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # view
-
-    def view(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `view_submission`/`view_closed` event listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.view("view_1")
-            def handle_submission(ack, body, client, view):
-                # Assume there's an input block with `block_c` as the block_id and `dreamy_input`
-                hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-                user = body["user"]["id"]
-                # Validate the inputs
-                errors = {}
-                if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-                    errors["block_c"] = "The value must be longer than 5 characters"
-                if len(errors) > 0:
-                    ack(response_action="errors", errors=errors)
-                    return
-                # Acknowledge the view_submission event and close the modal
-                ack()
-                # Do whatever you want with the input data - here we're saving it to a DB
-
-            # Pass a function to this method
-            app.view("view_1")(handle_submission)
-
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            constraints: The conditions that match a request payload
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def view_submission(
-        self,
-        constraints: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `view_submission` listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for
-        details.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view_submission(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def view_closed(
-        self,
-        constraints: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `view_closed` listener.
-        Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.view_closed(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # options
-
-    def options(
-        self,
-        constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new options listener.
-        This method can be used as either a decorator or a method.
-
-            # Use this method as a decorator
-            @app.options("menu_selection")
-            def show_menu_options(ack):
-                options = [
-                    {
-                        "text": {"type": "plain_text", "text": "Option 1"},
-                        "value": "1-1",
-                    },
-                    {
-                        "text": {"type": "plain_text", "text": "Option 2"},
-                        "value": "1-2",
-                    },
-                ]
-                ack(options=options)
-
-            # Pass a function to this method
-            app.options("menu_selection")(show_menu_options)
-
-        Refer to the following documents for details:
-
-        * https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select
-        * https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select
-
-        To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-        Args:
-            matchers: A list of listener matcher functions.
-                Only when all the matchers return True, the listener function can be invoked.
-            middleware: A list of lister middleware functions.
-                Only when all the middleware call `next()` method, the listener function can be invoked.
-        """
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.options(constraints, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def block_suggestion(
-        self,
-        action_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `block_suggestion` listener."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.block_suggestion(action_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    def dialog_suggestion(
-        self,
-        callback_id: Union[str, Pattern],
-        matchers: Optional[Sequence[Callable[..., bool]]] = None,
-        middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-        """Registers a new `dialog_suggestion` listener.
-        Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-        def __call__(*args, **kwargs):
-            functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-            primary_matcher = builtin_matchers.dialog_suggestion(callback_id, base_logger=self._base_logger)
-            return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-        return __call__
-
-    # -------------------------
-    # built-in listener functions
-
-    def default_tokens_revoked_event_listener(
-        self,
-    ) -> Callable[..., Optional[BoltResponse]]:
-        if self._tokens_revocation_listeners is None:
-            raise BoltError(error_installation_store_required_for_builtin_listeners())
-        return self._tokens_revocation_listeners.handle_tokens_revoked_events
-
-    def default_app_uninstalled_event_listener(
-        self,
-    ) -> Callable[..., Optional[BoltResponse]]:
-        if self._tokens_revocation_listeners is None:
-            raise BoltError(error_installation_store_required_for_builtin_listeners())
-        return self._tokens_revocation_listeners.handle_app_uninstalled_events
-
-    def enable_token_revocation_listeners(self) -> None:
-        self.event("tokens_revoked")(self.default_tokens_revoked_event_listener())
-        self.event("app_uninstalled")(self.default_app_uninstalled_event_listener())
-
-    # -------------------------
-
-    def _init_context(self, req: BoltRequest):
-        req.context["logger"] = get_bolt_app_logger(app_name=self.name, base_logger=self._base_logger)
-        req.context["token"] = self._token
-        # Prior to version 1.15, when the token is static, self._client was passed to `req.context`.
-        # The intention was to avoid creating a new instance per request
-        # in the interest of runtime performance/memory footprint optimization.
-        # However, developers may want to replace the token held by req.context.client in some situations.
-        # In this case, this behavior can result in thread-unsafe data modification on `self._client`.
-        # (`self._client` a.k.a. `app.client` is a singleton object per an App instance)
-        # Thus, we've changed the behavior to create a new instance per request regardless of token argument
-        # in the App initialization starting v1.15.
-        # The overhead brought by this change is slight so that we believe that it is ignorable in any cases.
-        client_per_request: WebClient = WebClient(
-            token=self._token,  # this can be None, and it can be set later on
-            base_url=self._client.base_url,
-            timeout=self._client.timeout,
-            ssl=self._client.ssl,
-            proxy=self._client.proxy,
-            headers=self._client.headers,
-            team_id=req.context.team_id,
-            logger=self._client.logger,
-            retry_handlers=self._client.retry_handlers.copy() if self._client.retry_handlers is not None else None,
-        )
-        req.context["client"] = client_per_request
-
-        # Most apps do not need this "listener_runner" instance.
-        # It is intended for apps that start lazy listeners from their custom global middleware.
-        req.context["listener_runner"] = self.listener_runner
-
-    @staticmethod
-    def _to_listener_functions(
-        kwargs: dict,
-    ) -> Optional[Sequence[Callable[..., Optional[BoltResponse]]]]:
-        if kwargs:
-            functions = [kwargs["ack"]]
-            for sub in kwargs["lazy"]:
-                functions.append(sub)
-            return functions
-        return None
-
-    def _register_listener(
-        self,
-        functions: Sequence[Callable[..., Optional[BoltResponse]]],
-        primary_matcher: ListenerMatcher,
-        matchers: Optional[Sequence[Callable[..., bool]]],
-        middleware: Optional[Sequence[Union[Callable, Middleware]]],
-        auto_acknowledgement: bool = False,
-        ack_timeout: int = 3,
-    ) -> Optional[Callable[..., Optional[BoltResponse]]]:
-        value_to_return = None
-        if not isinstance(functions, list):
-            functions = list(functions)
-        if len(functions) == 1:
-            # In the case where the function is registered using decorator,
-            # the registration should return the original function.
-            value_to_return = functions[0]
-
-        listener_matchers: List[ListenerMatcher] = [
-            CustomListenerMatcher(app_name=self.name, func=f, base_logger=self._base_logger) for f in (matchers or [])
-        ]
-        listener_matchers.insert(0, primary_matcher)
-        listener_middleware = []
-        for m in middleware or []:
-            if isinstance(m, Middleware):
-                listener_middleware.append(m)
-            elif callable(m):
-                listener_middleware.append(CustomMiddleware(app_name=self.name, func=m, base_logger=self._base_logger))
-            else:
-                raise ValueError(error_unexpected_listener_middleware(type(m)))
-
-        self._listeners.append(
-            CustomListener(
-                app_name=self.name,
-                ack_function=functions.pop(0),
-                lazy_functions=functions,  # type: ignore[arg-type]
-                matchers=listener_matchers,
-                middleware=listener_middleware,
-                auto_acknowledgement=auto_acknowledgement,
-                ack_timeout=ack_timeout,
-                base_logger=self._base_logger,
-            )
-        )
-        return value_to_return
-
-

Bolt App that provides functionalities to register middleware/listeners.

-
import os
-from slack_bolt import App
-
-# Initializes your app with your bot token and signing secret
-app = App(
-    token=os.environ.get("SLACK_BOT_TOKEN"),
-    signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
-)
-
-# Listens to incoming messages that contain "hello"
-@app.message("hello")
-def message_hello(message, say):
-    # say() sends a message to the channel where the event was triggered
-    say(f"Hey there <@{message['user']}>!")
-
-# Start your app
-if __name__ == "__main__":
-    app.start(port=int(os.environ.get("PORT", 3000)))
-
-

Refer to https://docs.slack.dev/tools/bolt-python/creating-an-app for details.

-

If you would like to build an OAuth app for enabling the app to run with multiple workspaces, -refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth to learn how to configure the app.

-

Args

-
-
logger
-
The custom logger that can be used in this app.
-
name
-
The application name that will be used in logging. If absent, the source file name will be used.
-
process_before_response
-
True if this app runs on Function as a Service. (Default: False)
-
raise_error_for_unhandled_request
-
True if you want to raise exceptions for unhandled requests -and use @app.error listeners instead of -the built-in handler, which pints warning logs and returns 404 to Slack (Default: False)
-
signing_secret
-
The Signing Secret value used for verifying requests from Slack.
-
token
-
The bot/user access token required only for single-workspace app.
-
token_verification_enabled
-
Verifies the validity of the given token if True.
-
client
-
The singleton slack_sdk.WebClient instance for this app.
-
before_authorize
-
A global middleware that can be executed right before authorize function
-
authorize
-
The function to authorize an incoming request from Slack -by checking if there is a team/user in the installation data.
-
user_facing_authorize_error_message
-
The user-facing error message to display -when the app is installed but the installation is not managed by this app's installation store
-
installation_store
-
The module offering save/find operations of installation data
-
installation_store_bot_only
-
Use InstallationStore#find_bot() if True (Default: False)
-
request_verification_enabled
-
False if you would like to disable the built-in middleware (Default: True). -RequestVerification is a built-in middleware that verifies the signature in HTTP Mode requests. -Make sure if it's safe enough when you turn a built-in middleware off. -We strongly recommend using RequestVerification for better security. -If you have a proxy that verifies request signature in front of the Bolt app, -it's totally fine to disable RequestVerification to avoid duplication of work. -Don't turn it off just for easiness of development.
-
ignoring_self_events_enabled
-
False if you would like to disable the built-in middleware (Default: True). -IgnoringSelfEvents is a built-in middleware that enables Bolt apps to easily skip the events -generated by this app's bot user (this is useful for avoiding code error causing an infinite loop).
-
ignoring_self_assistant_message_events_enabled
-
False if you would like to disable the built-in middleware. -IgnoringSelfEvents for this app's bot user message events within an assistant thread -This is useful for avoiding code error causing an infinite loop; Default: True
-
url_verification_enabled
-
False if you would like to disable the built-in middleware (Default: True). -UrlVerification is a built-in middleware that handles url_verification requests -that verify the endpoint for Events API in HTTP Mode requests.
-
attaching_function_token_enabled
-
False if you would like to disable the built-in middleware (Default: True). -AttachingFunctionToken is a built-in middleware that injects the just-in-time workflow-execution tokens -when your app receives function_executed or interactivity events scoped to a custom step.
-
ssl_check_enabled
-
bool = False if you would like to disable the built-in middleware (Default: True). -SslCheck is a built-in middleware that handles ssl_check requests from Slack.
-
oauth_settings
-
The settings related to Slack app installation flow (OAuth flow)
-
oauth_flow
-
Instantiated OAuthFlow. This is always prioritized over oauth_settings.
-
verification_token
-
Deprecated verification mechanism. This can be used only for ssl_check requests.
-
listener_executor
-
Custom executor to run background tasks. If absent, the default ThreadPoolExecutor will -be used.
-
assistant_thread_context_store
-
Custom AssistantThreadContext store (Default: the built-in implementation, -which uses a parent message's metadata to store the latest context)
-
-

Instance variables

-
-
prop client : slack_sdk.web.client.WebClient
-
-
- -Expand source code - -
@property
-def client(self) -> WebClient:
-    """The singleton `slack_sdk.WebClient` instance in this app."""
-    return self._client
-
-

The singleton slack_sdk.WebClient instance in this app.

-
-
prop installation_store : slack_sdk.oauth.installation_store.installation_store.InstallationStore | None
-
-
- -Expand source code - -
@property
-def installation_store(self) -> Optional[InstallationStore]:
-    """The `slack_sdk.oauth.InstallationStore` that can be used in the `authorize` middleware."""
-    return self._installation_store
-
-

The slack_sdk.oauth.InstallationStore that can be used in the authorize middleware.

-
-
prop listener_runnerThreadListenerRunner
-
-
- -Expand source code - -
@property
-def listener_runner(self) -> ThreadListenerRunner:
-    """The thread executor for asynchronously running listeners."""
-    return self._listener_runner
-
-

The thread executor for asynchronously running listeners.

-
-
prop logger : logging.Logger
-
-
- -Expand source code - -
@property
-def logger(self) -> logging.Logger:
-    """The logger this app uses."""
-    return self._framework_logger
-
-

The logger this app uses.

-
-
prop name : str
-
-
- -Expand source code - -
@property
-def name(self) -> str:
-    """The name of this app (default: the filename)"""
-    return self._name
-
-

The name of this app (default: the filename)

-
-
prop oauth_flowOAuthFlow | None
-
-
- -Expand source code - -
@property
-def oauth_flow(self) -> Optional[OAuthFlow]:
-    """Configured `OAuthFlow` object if exists."""
-    return self._oauth_flow
-
-

Configured OAuthFlow object if exists.

-
-
prop process_before_response : bool
-
-
- -Expand source code - -
@property
-def process_before_response(self) -> bool:
-    return self._process_before_response or False
-
-
-
-
-

Methods

-
-
-def action(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def action(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new action listener. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.action("approve_button")
-        def update_message(ack):
-            ack()
-
-        # Pass a function to this method
-        app.action("approve_button")(update_message)
-
-    * Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`.
-    * Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`.
-    * Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for actions in dialogs.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.action(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new action listener. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.action("approve_button")
-def update_message(ack):
-    ack()
-
-# Pass a function to this method
-app.action("approve_button")(update_message)
-
- -

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def assistant(self,
assistant: Assistant) ‑> Callable | None
-
-
-
- -Expand source code - -
def assistant(self, assistant: Assistant) -> Optional[Callable]:
-    return self.middleware(assistant)
-
-
-
-
-def attachment_action(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def attachment_action(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `interactive_message` action listener.
-    Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.attachment_action(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new interactive_message action listener. -Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for details.

-
-
-def block_action(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def block_action(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `block_actions` action listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.block_action(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new block_actions action listener. -Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for details.

-
-
-def block_suggestion(self,
action_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def block_suggestion(
-    self,
-    action_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `block_suggestion` listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.block_suggestion(action_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new block_suggestion listener.

-
-
-def command(self,
command: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def command(
-    self,
-    command: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new slash command listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.command("/echo")
-        def repeat_text(ack, say, command):
-            # Acknowledge command request
-            ack()
-            say(f"{command['text']}")
-
-        # Pass a function to this method
-        app.command("/echo")(repeat_text)
-
-    Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        command: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.command(command, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new slash command listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.command("/echo")
-def repeat_text(ack, say, command):
-    # Acknowledge command request
-    ack()
-    say(f"{command['text']}")
-
-# Pass a function to this method
-app.command("/echo")(repeat_text)
-
-

Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
command
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def default_app_uninstalled_event_listener(self) ‑> Callable[..., BoltResponse | None] -
-
-
- -Expand source code - -
def default_app_uninstalled_event_listener(
-    self,
-) -> Callable[..., Optional[BoltResponse]]:
-    if self._tokens_revocation_listeners is None:
-        raise BoltError(error_installation_store_required_for_builtin_listeners())
-    return self._tokens_revocation_listeners.handle_app_uninstalled_events
-
-
-
-
-def default_tokens_revoked_event_listener(self) ‑> Callable[..., BoltResponse | None] -
-
-
- -Expand source code - -
def default_tokens_revoked_event_listener(
-    self,
-) -> Callable[..., Optional[BoltResponse]]:
-    if self._tokens_revocation_listeners is None:
-        raise BoltError(error_installation_store_required_for_builtin_listeners())
-    return self._tokens_revocation_listeners.handle_tokens_revoked_events
-
-
-
-
-def dialog_cancellation(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def dialog_cancellation(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `dialog_cancellation` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_cancellation(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_cancellation listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dialog_submission(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def dialog_submission(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `dialog_submission` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_submission(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_submission listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dialog_suggestion(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def dialog_suggestion(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `dialog_suggestion` listener.
-    Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.dialog_suggestion(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new dialog_suggestion listener. -Refer to https://docs.slack.dev/legacy/legacy-dialogs/ for details.

-
-
-def dispatch(self,
req: BoltRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def dispatch(self, req: BoltRequest) -> BoltResponse:
-    """Applies all middleware and dispatches an incoming request from Slack to the right code path.
-
-    Args:
-        req: An incoming request from Slack
-
-    Returns:
-        The response generated by this Bolt app
-    """
-    starting_time = time.time()
-    self._init_context(req)
-
-    resp: Optional[BoltResponse] = BoltResponse(status=200, body="")
-    middleware_state = {"next_called": False}
-
-    def middleware_next():
-        middleware_state["next_called"] = True
-
-    try:
-        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)  # type: ignore[arg-type]
-            if not middleware_state["next_called"]:
-                if resp is None:
-                    # next() method was not called without providing the response to return to Slack
-                    # This should not be an intentional handling in usual use cases.
-                    resp = BoltResponse(status=404, body={"error": "no next() calls in middleware"})
-                    if self._raise_error_for_unhandled_request is True:
-                        try:
-                            raise BoltUnhandledRequestError(
-                                request=req,
-                                current_response=resp,
-                                last_global_middleware_name=middleware.name,
-                            )
-                        except BoltUnhandledRequestError as e:
-                            self._listener_runner.listener_error_handler.handle(
-                                error=e,
-                                request=req,
-                                response=resp,
-                            )
-                        return resp
-                    self._framework_logger.warning(warning_unhandled_by_global_middleware(middleware.name, req))
-                    return resp
-                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):  # type: ignore[arg-type]
-                # run all the middleware attached to this listener first
-                middleware_resp, next_was_not_called = listener.run_middleware(
-                    req=req, resp=resp  # type: ignore[arg-type]
-                )
-                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,  # type: ignore[arg-type]
-                    listener_name=listener_name,
-                    listener=listener,
-                )
-                if listener_response is not None:
-                    return listener_response
-
-        if resp is None:
-            resp = BoltResponse(status=404, body={"error": "unhandled request"})
-        if self._raise_error_for_unhandled_request is True:
-            try:
-                raise BoltUnhandledRequestError(
-                    request=req,
-                    current_response=resp,
-                )
-            except BoltUnhandledRequestError as e:
-                self._listener_runner.listener_error_handler.handle(
-                    error=e,
-                    request=req,
-                    response=resp,
-                )
-            return resp
-        return self._handle_unmatched_requests(req, resp)
-    except Exception as error:
-        resp = BoltResponse(status=500, body="")
-        self._middleware_error_handler.handle(
-            error=error,
-            request=req,
-            response=resp,
-        )
-        return resp
-
-

Applies all middleware and dispatches an incoming request from Slack to the right code path.

-

Args

-
-
req
-
An incoming request from Slack
-
-

Returns

-

The response generated by this Bolt app

-
-
-def enable_token_revocation_listeners(self) ‑> None -
-
-
- -Expand source code - -
def enable_token_revocation_listeners(self) -> None:
-    self.event("tokens_revoked")(self.default_tokens_revoked_event_listener())
-    self.event("app_uninstalled")(self.default_app_uninstalled_event_listener())
-
-
-
-
-def error(self,
func: Callable[..., BoltResponse | None]) ‑> Callable[..., BoltResponse | None]
-
-
-
- -Expand source code - -
def error(self, func: Callable[..., Optional[BoltResponse]]) -> Callable[..., Optional[BoltResponse]]:
-    """Updates the global error handler. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.error
-        def custom_error_handler(error, body, logger):
-            logger.exception(f"Error: {error}")
-            logger.info(f"Request body: {body}")
-
-        # Pass a function to this method
-        app.error(custom_error_handler)
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        func: The function that is supposed to be executed
-            when getting an unhandled error in Bolt app.
-    """
-    self._listener_runner.listener_error_handler = CustomListenerErrorHandler(
-        logger=self._framework_logger,
-        func=func,
-    )
-    self._middleware_error_handler = CustomMiddlewareErrorHandler(
-        logger=self._framework_logger,
-        func=func,
-    )
-    return func
-
-

Updates the global error handler. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.error
-def custom_error_handler(error, body, logger):
-    logger.exception(f"Error: {error}")
-    logger.info(f"Request body: {body}")
-
-# Pass a function to this method
-app.error(custom_error_handler)
-
-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
func
-
The function that is supposed to be executed -when getting an unhandled error in Bolt app.
-
-
-
-def event(self,
event: str | Pattern | Dict[str, str | Sequence[str | Pattern | None] | None],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def event(
-    self,
-    event: Union[
-        str,
-        Pattern,
-        Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]],
-    ],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new event listener. This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.event("team_join")
-        def ask_for_introduction(event, say):
-            welcome_channel_id = "C12345"
-            user_id = event["user"]
-            text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-            say(text=text, channel=welcome_channel_id)
-
-        # Pass a function to this method
-        app.event("team_join")(ask_for_introduction)
-
-    Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        event: The conditions that match a request payload.
-            If you pass a dict for this, you can have type, subtype in the constraint.
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.event(event, base_logger=self._base_logger)
-        if self._attaching_conversation_kwargs_enabled:
-            middleware.insert(0, AttachingConversationKwargs(self._assistant_thread_context_store))
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-    return __call__
-
-

Registers a new event listener. This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.event("team_join")
-def ask_for_introduction(event, say):
-    welcome_channel_id = "C12345"
-    user_id = event["user"]
-    text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel."
-    say(text=text, channel=welcome_channel_id)
-
-# Pass a function to this method
-app.event("team_join")(ask_for_introduction)
-
-

Refer to https://docs.slack.dev/apis/events-api/ for details of Events API.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
event
-
The conditions that match a request payload. -If you pass a dict for this, you can have type, subtype in the constraint.
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def function(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None,
auto_acknowledge: bool = True,
ack_timeout: int = 3) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def function(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-    auto_acknowledge: bool = True,
-    ack_timeout: int = 3,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new Function listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.function("reverse")
-        def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail):
-            try:
-                ack()
-                string_to_reverse = inputs["stringToReverse"]
-                complete(outputs={"reverseString": string_to_reverse[::-1]})
-            except Exception as e:
-                fail(f"Cannot reverse string (error: {e})")
-                raise e
-
-        # Pass a function to this method
-        app.function("reverse")(reverse_string)
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        callback_id: The callback id to identify the function
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    if auto_acknowledge is True:
-        if ack_timeout != 3:
-            self._framework_logger.warning(warning_ack_timeout_has_no_effect(callback_id, ack_timeout))
-
-    matchers = list(matchers) if matchers else []
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.function_executed(callback_id=callback_id, base_logger=self._base_logger)
-        return self._register_listener(functions, primary_matcher, matchers, middleware, auto_acknowledge, ack_timeout)
-
-    return __call__
-
-

Registers a new Function listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.function("reverse")
-def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail):
-    try:
-        ack()
-        string_to_reverse = inputs["stringToReverse"]
-        complete(outputs={"reverseString": string_to_reverse[::-1]})
-    except Exception as e:
-        fail(f"Cannot reverse string (error: {e})")
-        raise e
-
-# Pass a function to this method
-app.function("reverse")(reverse_string)
-
-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
callback_id
-
The callback id to identify the function
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def global_shortcut(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def global_shortcut(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new global shortcut listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.global_shortcut(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new global shortcut listener.

-
-
-def message(self,
keyword: str | Pattern = '',
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def message(
-    self,
-    keyword: Union[str, Pattern] = "",
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new message event listener. This method can be used as either a decorator or a method.
-    Check the `App#event` method's docstring for details.
-
-        # Use this method as a decorator
-        @app.message(":wave:")
-        def say_hello(message, say):
-            user = message['user']
-            say(f"Hi there, <@{user}>!")
-
-        # Pass a function to this method
-        app.message(":wave:")(say_hello)
-
-    Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        keyword: The keyword to match
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-    matchers = list(matchers) if matchers else []
-    middleware = list(middleware) if middleware else []
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        constraints = {
-            "type": "message",
-            "subtype": (
-                # In most cases, new message events come with no subtype.
-                None,
-                # As of Jan 2021, most bot messages no longer have the subtype bot_message.
-                # By contrast, messages posted using classic app's bot token still have the subtype.
-                "bot_message",
-                # If an end-user posts a message with "Also send to #channel" checked,
-                # the message event comes with this subtype.
-                "thread_broadcast",
-                # If an end-user posts a message with attached files,
-                # the message event comes with this subtype.
-                "file_share",
-            ),
-        }
-        primary_matcher = builtin_matchers.message_event(
-            keyword=keyword, constraints=constraints, base_logger=self._base_logger
-        )
-        if self._attaching_conversation_kwargs_enabled:
-            middleware.insert(0, AttachingConversationKwargs(self._assistant_thread_context_store))
-        middleware.insert(0, MessageListenerMatches(keyword))
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware, True)
-
-    return __call__
-
-

Registers a new message event listener. This method can be used as either a decorator or a method. -Check the App#event method's docstring for details.

-
# Use this method as a decorator
-@app.message(":wave:")
-def say_hello(message, say):
-    user = message['user']
-    say(f"Hi there, <@{user}>!")
-
-# Pass a function to this method
-app.message(":wave:")(say_hello)
-
-

Refer to https://docs.slack.dev/reference/events/message/ for details of message events.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
keyword
-
The keyword to match
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def message_shortcut(self,
callback_id: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def message_shortcut(
-    self,
-    callback_id: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new message shortcut listener."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.message_shortcut(callback_id, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new message shortcut listener.

-
-
-def middleware(self, *args) ‑> Callable | None -
-
-
- -Expand source code - -
def middleware(self, *args) -> Optional[Callable]:
-    """Registers a new middleware to this app.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.middleware
-        def middleware_func(logger, body, next):
-            logger.info(f"request body: {body}")
-            next()
-
-        # Pass a function to this method
-        app.middleware(middleware_func)
-
-    Refer to https://docs.slack.dev/tools/bolt-python/concepts/global-middleware for details.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        *args: A function that works as a global middleware.
-    """
-    if len(args) > 0:
-        middleware_or_callable = args[0]
-        if isinstance(middleware_or_callable, Middleware):
-            middleware: Middleware = middleware_or_callable
-            self._middleware_list.append(middleware)
-            if isinstance(middleware, Assistant) and middleware.thread_context_store is not None:
-                self._assistant_thread_context_store = middleware.thread_context_store
-        elif callable(middleware_or_callable):
-            self._middleware_list.append(
-                CustomMiddleware(
-                    app_name=self.name,
-                    func=middleware_or_callable,
-                    base_logger=self._base_logger,
-                )
-            )
-            return middleware_or_callable
-        else:
-            raise BoltError(f"Unexpected type for a middleware ({type(middleware_or_callable)})")
-    return None
-
-

Registers a new middleware to this app. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.middleware
-def middleware_func(logger, body, next):
-    logger.info(f"request body: {body}")
-    next()
-
-# Pass a function to this method
-app.middleware(middleware_func)
-
-

Refer to https://docs.slack.dev/tools/bolt-python/concepts/global-middleware for details.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
*args
-
A function that works as a global middleware.
-
-
-
-def options(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def options(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new options listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.options("menu_selection")
-        def show_menu_options(ack):
-            options = [
-                {
-                    "text": {"type": "plain_text", "text": "Option 1"},
-                    "value": "1-1",
-                },
-                {
-                    "text": {"type": "plain_text", "text": "Option 2"},
-                    "value": "1-2",
-                },
-            ]
-            ack(options=options)
-
-        # Pass a function to this method
-        app.options("menu_selection")(show_menu_options)
-
-    Refer to the following documents for details:
-
-    * https://docs.slack.dev/reference/block-kit/block-elements/select-menu-element#external_select
-    * https://docs.slack.dev/reference/block-kit/block-elements/multi-select-menu-element#external_multi_select
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.options(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new options listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.options("menu_selection")
-def show_menu_options(ack):
-    options = [
-        {
-            "text": {"type": "plain_text", "text": "Option 1"},
-            "value": "1-1",
-        },
-        {
-            "text": {"type": "plain_text", "text": "Option 2"},
-            "value": "1-2",
-        },
-    ]
-    ack(options=options)
-
-# Pass a function to this method
-app.options("menu_selection")(show_menu_options)
-
-

Refer to the following documents for details:

- -

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def shortcut(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def shortcut(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new shortcut listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.shortcut("open_modal")
-        def open_modal(ack, body, client):
-            # Acknowledge the command request
-            ack()
-            # Call views_open with the built-in client
-            client.views_open(
-                # Pass a valid trigger_id within 3 seconds of receiving it
-                trigger_id=body["trigger_id"],
-                # View payload
-                view={ ... }
-            )
-
-        # Pass a function to this method
-        app.shortcut("open_modal")(open_modal)
-
-    Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload.
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.shortcut(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new shortcut listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.shortcut("open_modal")
-def open_modal(ack, body, client):
-    # Acknowledge the command request
-    ack()
-    # Call views_open with the built-in client
-    client.views_open(
-        # Pass a valid trigger_id within 3 seconds of receiving it
-        trigger_id=body["trigger_id"],
-        # View payload
-        view={ ... }
-    )
-
-# Pass a function to this method
-app.shortcut("open_modal")(open_modal)
-
-

Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload.
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def start(self,
port: int = 3000,
path: str = '/slack/events',
http_server_logger_enabled: bool = True) ‑> None
-
-
-
- -Expand source code - -
def start(
-    self,
-    port: int = 3000,
-    path: str = "/slack/events",
-    http_server_logger_enabled: bool = True,
-) -> None:
-    """Starts a web server for local development.
-
-        # With the default settings, `http://localhost:3000/slack/events`
-        # is available for handling incoming requests from Slack
-        app.start()
-
-    This method internally starts a Web server process built with the `http.server` module.
-    For production, consider using a production-ready WSGI server such as Gunicorn.
-
-    Args:
-        port: The port to listen on (Default: 3000)
-        path: The path to handle request from Slack (Default: `/slack/events`)
-        http_server_logger_enabled: The flag to enable http.server logging if True (Default: True)
-    """
-    self._development_server = SlackAppDevelopmentServer(
-        port=port,
-        path=path,
-        app=self,
-        oauth_flow=self.oauth_flow,
-        http_server_logger_enabled=http_server_logger_enabled,
-    )
-    self._development_server.start()
-
-

Starts a web server for local development.

-
# With the default settings, `http://localhost:3000/slack/events`
-# is available for handling incoming requests from Slack
-app.start()
-
-

This method internally starts a Web server process built with the http.server module. -For production, consider using a production-ready WSGI server such as Gunicorn.

-

Args

-
-
port
-
The port to listen on (Default: 3000)
-
path
-
The path to handle request from Slack (Default: /slack/events)
-
http_server_logger_enabled
-
The flag to enable http.server logging if True (Default: True)
-
-
-
-def step(self,
callback_id: str | Pattern | WorkflowStep | WorkflowStepBuilder,
edit: Callable[..., BoltResponse | None] | Listener | Sequence[Callable] | None = None,
save: Callable[..., BoltResponse | None] | Listener | Sequence[Callable] | None = None,
execute: Callable[..., BoltResponse | None] | Listener | Sequence[Callable] | None = None)
-
-
-
- -Expand source code - -
def step(
-    self,
-    callback_id: Union[str, Pattern, WorkflowStep, WorkflowStepBuilder],
-    edit: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-    save: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-    execute: Optional[Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]]] = None,
-):
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Registers a new step from app listener.
-
-    Unlike others, this method doesn't behave as a decorator.
-    If you want to register a step from app by a decorator, use `WorkflowStepBuilder`'s methods.
-
-        # Create a new WorkflowStep instance
-        from slack_bolt.workflows.step import WorkflowStep
-        ws = WorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        # Pass Step to set up listeners
-        app.step(ws)
-
-    Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    For further information about WorkflowStep specific function arguments
-    such as `configure`, `update`, `complete`, and `fail`,
-    refer to `slack_bolt.workflows.step.utilities` API documents.
-
-    Args:
-        callback_id: The Callback ID for this step from app
-        edit: The function for displaying a modal in the Workflow Builder
-        save: The function for handling configuration in the Workflow Builder
-        execute: The function for handling the step execution
-    """
-    warnings.warn(
-        (
-            "Steps from apps for legacy workflows are now deprecated. "
-            "Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/"
-        ),
-        category=DeprecationWarning,
-    )
-    step = callback_id
-    if isinstance(callback_id, (str, Pattern)):
-        step = WorkflowStep(
-            callback_id=callback_id,
-            edit=edit,  # type: ignore[arg-type]
-            save=save,  # type: ignore[arg-type]
-            execute=execute,  # type: ignore[arg-type]
-            base_logger=self._base_logger,
-        )
-    elif isinstance(step, WorkflowStepBuilder):
-        step = step.build(base_logger=self._base_logger)
-    elif not isinstance(step, WorkflowStep):
-        raise BoltError(f"Invalid step object ({type(step)})")
-
-    self.use(WorkflowStepMiddleware(step))
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Registers a new step from app listener.

-

Unlike others, this method doesn't behave as a decorator. -If you want to register a step from app by a decorator, use WorkflowStepBuilder's methods.

-
# Create a new WorkflowStep instance
-from slack_bolt.workflows.step import WorkflowStep
-ws = WorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-# Pass Step to set up listeners
-app.step(ws)
-
-

Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

For further information about WorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
callback_id
-
The Callback ID for this step from app
-
edit
-
The function for displaying a modal in the Workflow Builder
-
save
-
The function for handling configuration in the Workflow Builder
-
execute
-
The function for handling the step execution
-
-
-
-def use(self, *args) ‑> Callable | None -
-
-
- -Expand source code - -
def use(self, *args) -> Optional[Callable]:
-    """Registers a new global middleware to this app. This method can be used as either a decorator or a method.
-
-    Refer to `App#middleware()` method's docstring for details."""
-    return self.middleware(*args)
-
-

Registers a new global middleware to this app. This method can be used as either a decorator or a method.

-

Refer to App#middleware() method's docstring for details.

-
-
-def view(self,
constraints: str | Pattern | Dict[str, str | Pattern],
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def view(
-    self,
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `view_submission`/`view_closed` event listener.
-    This method can be used as either a decorator or a method.
-
-        # Use this method as a decorator
-        @app.view("view_1")
-        def handle_submission(ack, body, client, view):
-            # Assume there's an input block with `block_c` as the block_id and `dreamy_input`
-            hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-            user = body["user"]["id"]
-            # Validate the inputs
-            errors = {}
-            if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-                errors["block_c"] = "The value must be longer than 5 characters"
-            if len(errors) > 0:
-                ack(response_action="errors", errors=errors)
-                return
-            # Acknowledge the view_submission event and close the modal
-            ack()
-            # Do whatever you want with the input data - here we're saving it to a DB
-
-        # Pass a function to this method
-        app.view("view_1")(handle_submission)
-
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.
-
-    To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document.
-
-    Args:
-        constraints: The conditions that match a request payload
-        matchers: A list of listener matcher functions.
-            Only when all the matchers return True, the listener function can be invoked.
-        middleware: A list of lister middleware functions.
-            Only when all the middleware call `next()` method, the listener function can be invoked.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new view_submission/view_closed event listener. -This method can be used as either a decorator or a method.

-
# Use this method as a decorator
-@app.view("view_1")
-def handle_submission(ack, body, client, view):
-    # Assume there's an input block with <code>block\_c</code> as the block_id and <code>dreamy\_input</code>
-    hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"]
-    user = body["user"]["id"]
-    # Validate the inputs
-    errors = {}
-    if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5:
-        errors["block_c"] = "The value must be longer than 5 characters"
-    if len(errors) > 0:
-        ack(response_action="errors", errors=errors)
-        return
-    # Acknowledge the view_submission event and close the modal
-    ack()
-    # Do whatever you want with the input data - here we're saving it to a DB
-
-# Pass a function to this method
-app.view("view_1")(handle_submission)
-
-

Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads.

-

To learn available arguments for middleware/listeners, see slack_bolt.kwargs_injection.args's API document.

-

Args

-
-
constraints
-
The conditions that match a request payload
-
matchers
-
A list of listener matcher functions. -Only when all the matchers return True, the listener function can be invoked.
-
middleware
-
A list of lister middleware functions. -Only when all the middleware call next() method, the listener function can be invoked.
-
-
-
-def view_closed(self,
constraints: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def view_closed(
-    self,
-    constraints: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `view_closed` listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_closed for details."""
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view_closed(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
- -
-
-def view_submission(self,
constraints: str | Pattern,
matchers: Sequence[Callable[..., bool]] | None = None,
middleware: Sequence[Callable | Middleware] | None = None) ‑> Callable[..., Callable[..., BoltResponse | None] | None]
-
-
-
- -Expand source code - -
def view_submission(
-    self,
-    constraints: Union[str, Pattern],
-    matchers: Optional[Sequence[Callable[..., bool]]] = None,
-    middleware: Optional[Sequence[Union[Callable, Middleware]]] = None,
-) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]:
-    """Registers a new `view_submission` listener.
-    Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for
-    details.
-    """
-
-    def __call__(*args, **kwargs):
-        functions = self._to_listener_functions(kwargs) if kwargs else list(args)
-        primary_matcher = builtin_matchers.view_submission(constraints, base_logger=self._base_logger)
-        return self._register_listener(list(functions), primary_matcher, matchers, middleware)
-
-    return __call__
-
-

Registers a new view_submission listener. -Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload/#view_submission for -details.

-
-
-
-
-class Args -(*,
logger: logging.Logger,
client: slack_sdk.web.client.WebClient,
req: BoltRequest,
resp: BoltResponse,
context: BoltContext,
body: Dict[str, Any],
payload: Dict[str, Any],
options: Dict[str, Any] | None = None,
shortcut: Dict[str, Any] | None = None,
action: Dict[str, Any] | None = None,
view: Dict[str, Any] | None = None,
command: Dict[str, Any] | None = None,
event: Dict[str, Any] | None = None,
message: Dict[str, Any] | None = None,
ack: Ack,
say: Say,
respond: Respond,
complete: Complete,
fail: Fail,
set_status: SetStatus | None = None,
set_title: SetTitle | None = None,
set_suggested_prompts: SetSuggestedPrompts | None = None,
get_thread_context: GetThreadContext | None = None,
save_thread_context: SaveThreadContext | None = None,
say_stream: SayStream | None = None,
next: Callable[[], None],
**kwargs)
-
-
-
- -Expand source code - -
class Args:
-    """All the arguments in this class are available in any middleware / listeners.
-    You can inject the named variables in the argument list in arbitrary order.
-
-        @app.action("link_button")
-        def handle_buttons(ack, respond, logger, context, body, client):
-            logger.info(f"request body: {body}")
-            ack()
-            if context.channel_id is not None:
-                respond("Hi!")
-            client.views_open(
-                trigger_id=body["trigger_id"],
-                view={ ... }
-            )
-
-    Alternatively, you can include a parameter named `args` and it will be injected with an instance of this class.
-
-        @app.action("link_button")
-        def handle_buttons(args):
-            args.logger.info(f"request body: {args.body}")
-            args.ack()
-            if args.context.channel_id is not None:
-                args.respond("Hi!")
-            args.client.views_open(
-                trigger_id=args.body["trigger_id"],
-                view={ ... }
-            )
-
-    """
-
-    client: WebClient
-    """`slack_sdk.web.WebClient` instance with a valid token"""
-    logger: Logger
-    """Logger instance"""
-    req: BoltRequest
-    """Incoming request from Slack"""
-    resp: BoltResponse
-    """Response representation"""
-    request: BoltRequest
-    """Incoming request from Slack"""
-    response: BoltResponse
-    """Response representation"""
-    context: BoltContext
-    """Context data associated with the incoming request"""
-    body: Dict[str, Any]
-    """Parsed request body data"""
-    # payload
-    payload: Dict[str, Any]
-    """The unwrapped core data in the request body"""
-    options: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.options` listener"""
-    shortcut: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.shortcut` listener"""
-    action: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.action` listener"""
-    view: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.view` listener"""
-    command: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.command` listener"""
-    event: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.event` listener"""
-    message: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.message` listener"""
-    # utilities
-    ack: Ack
-    """`ack()` utility function, which returns acknowledgement to the Slack servers"""
-    say: Say
-    """`say()` utility function, which calls `chat.postMessage` API with the associated channel ID"""
-    respond: Respond
-    """`respond()` utility function, which utilizes the associated `response_url`"""
-    complete: Complete
-    """`complete()` utility function, signals a successful completion of the custom function"""
-    fail: Fail
-    """`fail()` utility function, signal that the custom function failed to complete"""
-    set_status: Optional[SetStatus]
-    """`set_status()` utility function for AI Agents & Assistants"""
-    set_title: Optional[SetTitle]
-    """`set_title()` utility function for AI Agents & Assistants"""
-    set_suggested_prompts: Optional[SetSuggestedPrompts]
-    """`set_suggested_prompts()` utility function for AI Agents & Assistants"""
-    get_thread_context: Optional[GetThreadContext]
-    """`get_thread_context()` utility function for AI Agents & Assistants"""
-    save_thread_context: Optional[SaveThreadContext]
-    """`save_thread_context()` utility function for AI Agents & Assistants"""
-    say_stream: Optional[SayStream]
-    """`say_stream()` utility function for conversations, AI Agents & Assistants"""
-    # middleware
-    next: Callable[[], None]
-    """`next()` utility function, which tells the middleware chain that it can continue with the next one"""
-    next_: Callable[[], None]
-    """An alias of `next()` for avoiding the Python built-in method overrides in middleware functions"""
-
-    def __init__(
-        self,
-        *,
-        logger: logging.Logger,
-        client: WebClient,
-        req: BoltRequest,
-        resp: BoltResponse,
-        context: BoltContext,
-        body: Dict[str, Any],
-        payload: Dict[str, Any],
-        options: Optional[Dict[str, Any]] = None,
-        shortcut: Optional[Dict[str, Any]] = None,
-        action: Optional[Dict[str, Any]] = None,
-        view: Optional[Dict[str, Any]] = None,
-        command: Optional[Dict[str, Any]] = None,
-        event: Optional[Dict[str, Any]] = None,
-        message: Optional[Dict[str, Any]] = None,
-        ack: Ack,
-        say: Say,
-        respond: Respond,
-        complete: Complete,
-        fail: Fail,
-        set_status: Optional[SetStatus] = None,
-        set_title: Optional[SetTitle] = None,
-        set_suggested_prompts: Optional[SetSuggestedPrompts] = None,
-        get_thread_context: Optional[GetThreadContext] = None,
-        save_thread_context: Optional[SaveThreadContext] = None,
-        say_stream: Optional[SayStream] = None,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], None],
-        **kwargs,  # noqa
-    ):
-        self.logger: logging.Logger = logger
-        self.client: WebClient = client
-        self.request = self.req = req
-        self.response = self.resp = resp
-        self.context: BoltContext = context
-
-        self.body: Dict[str, Any] = body
-        self.payload: Dict[str, Any] = payload
-        self.options: Optional[Dict[str, Any]] = options
-        self.shortcut: Optional[Dict[str, Any]] = shortcut
-        self.action: Optional[Dict[str, Any]] = action
-        self.view: Optional[Dict[str, Any]] = view
-        self.command: Optional[Dict[str, Any]] = command
-        self.event: Optional[Dict[str, Any]] = event
-        self.message: Optional[Dict[str, Any]] = message
-
-        self.ack: Ack = ack
-        self.say: Say = say
-        self.respond: Respond = respond
-        self.complete: Complete = complete
-        self.fail: Fail = fail
-
-        self.set_status = set_status
-        self.set_title = set_title
-        self.set_suggested_prompts = set_suggested_prompts
-        self.get_thread_context = get_thread_context
-        self.save_thread_context = save_thread_context
-        self.say_stream = say_stream
-
-        self.next: Callable[[], None] = next
-        self.next_: Callable[[], None] = next
-
-

All the arguments in this class are available in any middleware / listeners. -You can inject the named variables in the argument list in arbitrary order.

-
@app.action("link_button")
-def handle_buttons(ack, respond, logger, context, body, client):
-    logger.info(f"request body: {body}")
-    ack()
-    if context.channel_id is not None:
-        respond("Hi!")
-    client.views_open(
-        trigger_id=body["trigger_id"],
-        view={ ... }
-    )
-
-

Alternatively, you can include a parameter named args and it will be injected with an instance of this class.

-
@app.action("link_button")
-def handle_buttons(args):
-    args.logger.info(f"request body: {args.body}")
-    args.ack()
-    if args.context.channel_id is not None:
-        args.respond("Hi!")
-    args.client.views_open(
-        trigger_id=args.body["trigger_id"],
-        view={ ... }
-    )
-
-

Class variables

-
-
var ackAck
-
-

ack() utility function, which returns acknowledgement to the Slack servers

-
-
var action : Dict[str, Any] | None
-
-

An alias for payload in an @app.action listener

-
-
var body : Dict[str, Any]
-
-

Parsed request body data

-
-
var client : slack_sdk.web.client.WebClient
-
-

slack_sdk.web.WebClient instance with a valid token

-
-
var command : Dict[str, Any] | None
-
-

An alias for payload in an @app.command listener

-
-
var completeComplete
-
-

complete() utility function, signals a successful completion of the custom function

-
-
var contextBoltContext
-
-

Context data associated with the incoming request

-
-
var event : Dict[str, Any] | None
-
-

An alias for payload in an @app.event listener

-
-
var failFail
-
-

fail() utility function, signal that the custom function failed to complete

-
-
var get_thread_contextGetThreadContext | None
-
-

get_thread_context() utility function for AI Agents & Assistants

-
-
var logger : logging.Logger
-
-

Logger instance

-
-
var message : Dict[str, Any] | None
-
-

An alias for payload in an @app.message listener

-
-
var next : Callable[[], None]
-
-

next() utility function, which tells the middleware chain that it can continue with the next one

-
-
var next_ : Callable[[], None]
-
-

An alias of next() for avoiding the Python built-in method overrides in middleware functions

-
-
var options : Dict[str, Any] | None
-
-

An alias for payload in an @app.options listener

-
-
var payload : Dict[str, Any]
-
-

The unwrapped core data in the request body

-
-
var reqBoltRequest
-
-

Incoming request from Slack

-
-
var requestBoltRequest
-
-

Incoming request from Slack

-
-
var respBoltResponse
-
-

Response representation

-
-
var respondRespond
-
-

respond() utility function, which utilizes the associated response_url

-
-
var responseBoltResponse
-
-

Response representation

-
-
var save_thread_contextSaveThreadContext | None
-
-

save_thread_context() utility function for AI Agents & Assistants

-
-
var saySay
-
-

say() utility function, which calls chat.postMessage API with the associated channel ID

-
-
var say_streamSayStream | None
-
-

say_stream() utility function for conversations, AI Agents & Assistants

-
-
var set_statusSetStatus | None
-
-

set_status() utility function for AI Agents & Assistants

-
-
var set_suggested_promptsSetSuggestedPrompts | None
-
-

set_suggested_prompts() utility function for AI Agents & Assistants

-
-
var set_titleSetTitle | None
-
-

set_title() utility function for AI Agents & Assistants

-
-
var shortcut : Dict[str, Any] | None
-
-

An alias for payload in an @app.shortcut listener

-
-
var view : Dict[str, Any] | None
-
-

An alias for payload in an @app.view listener

-
-
-
-
-class Assistant -(*,
app_name: str = 'assistant',
thread_context_store: AssistantThreadContextStore | None = None,
logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class Assistant(Middleware):
-    _thread_started_listeners: Optional[List[Listener]]
-    _thread_context_changed_listeners: Optional[List[Listener]]
-    _user_message_listeners: Optional[List[Listener]]
-    _bot_message_listeners: Optional[List[Listener]]
-
-    thread_context_store: Optional[AssistantThreadContextStore]
-    base_logger: Optional[logging.Logger]
-
-    def __init__(
-        self,
-        *,
-        app_name: str = "assistant",
-        thread_context_store: Optional[AssistantThreadContextStore] = None,
-        logger: Optional[logging.Logger] = None,
-    ):
-        self.app_name = app_name
-        self.thread_context_store = thread_context_store
-        self.base_logger = logger
-
-        self._thread_started_listeners = None
-        self._thread_context_changed_listeners = None
-        self._user_message_listeners = None
-        self._bot_message_listeners = None
-
-    def thread_started(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._thread_started_listeners is None:
-            self._thread_started_listeners = []
-        all_matchers = self._merge_matchers(is_assistant_thread_started_event, matchers)
-        if is_used_without_argument(args):
-            func = args[0]
-            self._thread_started_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._thread_started_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def user_message(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._user_message_listeners is None:
-            self._user_message_listeners = []
-        all_matchers = self._merge_matchers(is_user_message_event_in_assistant_thread, matchers)
-        if is_used_without_argument(args):
-            func = args[0]
-            self._user_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._user_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def bot_message(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._bot_message_listeners is None:
-            self._bot_message_listeners = []
-        all_matchers = self._merge_matchers(is_bot_message_event_in_assistant_thread, matchers)
-        if is_used_without_argument(args):
-            func = args[0]
-            self._bot_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._bot_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def thread_context_changed(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._thread_context_changed_listeners is None:
-            self._thread_context_changed_listeners = []
-        all_matchers = self._merge_matchers(is_assistant_thread_context_changed_event, matchers)
-        if is_used_without_argument(args):
-            func = args[0]
-            self._thread_context_changed_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._thread_context_changed_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def _merge_matchers(
-        self,
-        primary_matcher: Callable[..., bool],
-        custom_matchers: Optional[Union[Callable[..., bool], ListenerMatcher]],
-    ):
-        return [CustomListenerMatcher(app_name=self.app_name, func=primary_matcher)] + (
-            custom_matchers or []
-        )  # type: ignore[operator]
-
-    @staticmethod
-    def default_thread_context_changed(save_thread_context: SaveThreadContext, payload: dict):
-        save_thread_context(payload["assistant_thread"]["context"])
-
-    def process(  # type: ignore[return]
-        self, *, req: BoltRequest, resp: BoltResponse, next: Callable[[], BoltResponse]
-    ) -> Optional[BoltResponse]:
-        if self._thread_context_changed_listeners is None:
-            self.thread_context_changed(self.default_thread_context_changed)
-
-        listener_runner: ThreadListenerRunner = req.context.listener_runner
-        for listeners in [
-            self._thread_started_listeners,
-            self._thread_context_changed_listeners,
-            self._user_message_listeners,
-            self._bot_message_listeners,
-        ]:
-            if listeners is not None:
-                for listener in listeners:
-                    if listener.matches(req=req, resp=resp):
-                        middleware_resp, next_was_not_called = listener.run_middleware(req=req, resp=resp)
-                        if next_was_not_called:
-                            if middleware_resp is not None:
-                                return middleware_resp
-                            # The listener middleware didn't call next().
-                            # Skip this listener and try the next one.
-                            continue
-                        if middleware_resp is not None:
-                            resp = middleware_resp
-                        return listener_runner.run(
-                            request=req,
-                            response=resp,
-                            listener_name="assistant_listener",
-                            listener=listener,
-                        )
-        if is_other_message_sub_event_in_assistant_thread(req.body):
-            # message_changed, message_deleted, etc.
-            return req.context.ack()
-
-        next()
-
-    def build_listener(
-        self,
-        listener_or_functions: Union[Listener, Callable, List[Callable]],
-        matchers: Optional[List[Union[ListenerMatcher, Callable[..., bool]]]] = None,
-        middleware: Optional[List[Middleware]] = None,
-        base_logger: Optional[Logger] = None,
-    ) -> Listener:
-        if isinstance(listener_or_functions, Callable):  # type: ignore[arg-type]
-            listener_or_functions = [listener_or_functions]  # type: ignore[list-item]
-
-        if isinstance(listener_or_functions, Listener):
-            return listener_or_functions
-        elif isinstance(listener_or_functions, list):
-            middleware = middleware if middleware else []
-            middleware.insert(0, AttachingConversationKwargs(self.thread_context_store))
-            functions = listener_or_functions
-            ack_function = functions.pop(0)
-
-            matchers = matchers if matchers else []
-            listener_matchers: List[ListenerMatcher] = []
-            for matcher in matchers:
-                if isinstance(matcher, ListenerMatcher):
-                    listener_matchers.append(matcher)
-                elif isinstance(matcher, Callable):  # type: ignore[arg-type]
-                    listener_matchers.append(
-                        build_listener_matcher(
-                            func=matcher,
-                            asyncio=False,
-                            base_logger=base_logger,
-                        )
-                    )
-            return CustomListener(
-                app_name=self.app_name,
-                matchers=listener_matchers,
-                middleware=middleware,
-                ack_function=ack_function,
-                lazy_functions=functions,
-                auto_acknowledgement=True,
-                base_logger=base_logger or self.base_logger,
-            )
-        else:
-            raise BoltError(f"Invalid listener: {type(listener_or_functions)} detected")
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var base_logger : logging.Logger | None
-
-

The type of the None singleton.

-
-
var thread_context_storeAssistantThreadContextStore | None
-
-

The type of the None singleton.

-
-
-

Static methods

-
-
-def default_thread_context_changed(save_thread_context: SaveThreadContext,
payload: dict)
-
-
-
- -Expand source code - -
@staticmethod
-def default_thread_context_changed(save_thread_context: SaveThreadContext, payload: dict):
-    save_thread_context(payload["assistant_thread"]["context"])
-
-
-
-
-

Methods

-
-
-def bot_message(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def bot_message(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._bot_message_listeners is None:
-        self._bot_message_listeners = []
-    all_matchers = self._merge_matchers(is_bot_message_event_in_assistant_thread, matchers)
-    if is_used_without_argument(args):
-        func = args[0]
-        self._bot_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._bot_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def build_listener(self,
listener_or_functions: Listener | Callable | List[Callable],
matchers: List[ListenerMatcher | Callable[..., bool]] | None = None,
middleware: List[Middleware] | None = None,
base_logger: logging.Logger | None = None) ‑> Listener
-
-
-
- -Expand source code - -
def build_listener(
-    self,
-    listener_or_functions: Union[Listener, Callable, List[Callable]],
-    matchers: Optional[List[Union[ListenerMatcher, Callable[..., bool]]]] = None,
-    middleware: Optional[List[Middleware]] = None,
-    base_logger: Optional[Logger] = None,
-) -> Listener:
-    if isinstance(listener_or_functions, Callable):  # type: ignore[arg-type]
-        listener_or_functions = [listener_or_functions]  # type: ignore[list-item]
-
-    if isinstance(listener_or_functions, Listener):
-        return listener_or_functions
-    elif isinstance(listener_or_functions, list):
-        middleware = middleware if middleware else []
-        middleware.insert(0, AttachingConversationKwargs(self.thread_context_store))
-        functions = listener_or_functions
-        ack_function = functions.pop(0)
-
-        matchers = matchers if matchers else []
-        listener_matchers: List[ListenerMatcher] = []
-        for matcher in matchers:
-            if isinstance(matcher, ListenerMatcher):
-                listener_matchers.append(matcher)
-            elif isinstance(matcher, Callable):  # type: ignore[arg-type]
-                listener_matchers.append(
-                    build_listener_matcher(
-                        func=matcher,
-                        asyncio=False,
-                        base_logger=base_logger,
-                    )
-                )
-        return CustomListener(
-            app_name=self.app_name,
-            matchers=listener_matchers,
-            middleware=middleware,
-            ack_function=ack_function,
-            lazy_functions=functions,
-            auto_acknowledgement=True,
-            base_logger=base_logger or self.base_logger,
-        )
-    else:
-        raise BoltError(f"Invalid listener: {type(listener_or_functions)} detected")
-
-
-
-
-def thread_context_changed(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def thread_context_changed(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._thread_context_changed_listeners is None:
-        self._thread_context_changed_listeners = []
-    all_matchers = self._merge_matchers(is_assistant_thread_context_changed_event, matchers)
-    if is_used_without_argument(args):
-        func = args[0]
-        self._thread_context_changed_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._thread_context_changed_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def thread_started(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def thread_started(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._thread_started_listeners is None:
-        self._thread_started_listeners = []
-    all_matchers = self._merge_matchers(is_assistant_thread_started_event, matchers)
-    if is_used_without_argument(args):
-        func = args[0]
-        self._thread_started_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._thread_started_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def user_message(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def user_message(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._user_message_listeners is None:
-        self._user_message_listeners = []
-    all_matchers = self._merge_matchers(is_user_message_event_in_assistant_thread, matchers)
-    if is_used_without_argument(args):
-        func = args[0]
-        self._user_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._user_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-

Inherited members

- -
-
-class AssistantThreadContext -(payload: dict) -
-
-
- -Expand source code - -
class AssistantThreadContext(dict):
-    enterprise_id: Optional[str]
-    team_id: Optional[str]
-    channel_id: str
-
-    def __init__(self, payload: dict):
-        dict.__init__(self, **payload)
-        self.enterprise_id = payload.get("enterprise_id")
-        self.team_id = payload.get("team_id")
-        self.channel_id = payload["channel_id"]
-
-

dict() -> new empty dictionary -dict(mapping) -> new dictionary initialized from a mapping object's -(key, value) pairs -dict(iterable) -> new dictionary initialized as if via: -d = {} -for k, v in iterable: -d[k] = v -dict(**kwargs) -> new dictionary initialized with the name=value pairs -in the keyword argument list. -For example: -dict(one=1, two=2)

-

Ancestors

-
    -
  • builtins.dict
  • -
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var enterprise_id : str | None
-
-

The type of the None singleton.

-
-
var team_id : str | None
-
-

The type of the None singleton.

-
-
-
-
-class AssistantThreadContextStore -
-
-
- -Expand source code - -
class AssistantThreadContextStore:
-    def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-        raise NotImplementedError()
-
-    def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-def find(self, *, channel_id: str, thread_ts: str) ‑> AssistantThreadContext | None -
-
-
- -Expand source code - -
def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-    raise NotImplementedError()
-
-
-
-
-def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) ‑> None -
-
-
- -Expand source code - -
def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-    raise NotImplementedError()
-
-
-
-
-
-
-class BoltContext -(*args, **kwargs) -
-
-
- -Expand source code - -
class BoltContext(BaseContext):
-    """Context object associated with a request from Slack."""
-
-    def to_copyable(self) -> "BoltContext":
-        new_dict = {}
-        for prop_name, prop_value in self.items():
-            if prop_name in self.copyable_standard_property_names:
-                # all the standard properties are copiable
-                new_dict[prop_name] = prop_value
-            elif prop_name in self.non_copyable_standard_property_names:
-                # Do nothing with this property (e.g., listener_runner)
-                continue
-            else:
-                try:
-                    copied_value = create_copy(prop_value)
-                    new_dict[prop_name] = copied_value
-                except TypeError as te:
-                    self.logger.warning(
-                        f"Skipped setting '{prop_name}' to a copied request for lazy listeners "
-                        "due to a deep-copy creation error. Consider passing the value not as part of context object "
-                        f"(error: {te})"
-                    )
-        return BoltContext(new_dict)
-
-    # The return type is intentionally string to avoid circular imports
-    @property
-    def listener_runner(self) -> "ThreadListenerRunner":
-        """The properly configured listener_runner that is available for middleware/listeners."""
-        return self["listener_runner"]
-
-    @property
-    def client(self) -> WebClient:
-        """The `WebClient` instance available for this request.
-
-            @app.event("app_mention")
-            def handle_events(context):
-                context.client.chat_postMessage(
-                    channel=context.channel_id,
-                    text="Thanks!",
-                )
-
-            # You can access "client" this way too.
-            @app.event("app_mention")
-            def handle_events(client, context):
-                client.chat_postMessage(
-                    channel=context.channel_id,
-                    text="Thanks!",
-                )
-
-        Returns:
-            `WebClient` instance
-        """
-        if "client" not in self:
-            self["client"] = WebClient(token=None)
-        return self["client"]
-
-    @property
-    def ack(self) -> Ack:
-        """`ack()` function for this request.
-
-            @app.action("button")
-            def handle_button_clicks(context):
-                context.ack()
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            def handle_button_clicks(ack):
-                ack()
-
-        Returns:
-            Callable `ack()` function
-        """
-        if "ack" not in self:
-            self["ack"] = Ack()
-        return self["ack"]
-
-    @property
-    def say(self) -> Say:
-        """`say()` function for this request.
-
-            @app.action("button")
-            def handle_button_clicks(context):
-                context.ack()
-                context.say("Hi!")
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            def handle_button_clicks(ack, say):
-                ack()
-                say("Hi!")
-
-        Returns:
-            Callable `say()` function
-        """
-        if "say" not in self:
-            self["say"] = Say(client=self.client, channel=self.channel_id)
-        return self["say"]
-
-    @property
-    def respond(self) -> Optional[Respond]:
-        """`respond()` function for this request.
-
-            @app.action("button")
-            def handle_button_clicks(context):
-                context.ack()
-                context.respond("Hi!")
-
-            # You can access "ack" this way too.
-            @app.action("button")
-            def handle_button_clicks(ack, respond):
-                ack()
-                respond("Hi!")
-
-        Returns:
-            Callable `respond()` function
-        """
-        if "respond" not in self:
-            self["respond"] = Respond(
-                response_url=self.response_url,
-                proxy=self.client.proxy,
-                ssl=self.client.ssl,
-            )
-        return self["respond"]
-
-    @property
-    def complete(self) -> Complete:
-        """`complete()` function for this request. Once a custom function's state is set to complete,
-        any outputs the function returns will be passed along to the next step of its housing workflow,
-        or complete the workflow if the function is the last step in a workflow. Additionally,
-        any interactivity handlers associated to a function invocation will no longer be invocable.
-
-            @app.function("reverse")
-            def handle_button_clicks(ack, complete):
-                ack()
-                complete(outputs={"stringReverse":"olleh"})
-
-            @app.function("reverse")
-            def handle_button_clicks(context):
-                context.ack()
-                context.complete(outputs={"stringReverse":"olleh"})
-
-        Returns:
-            Callable `complete()` function
-        """
-        if "complete" not in self:
-            self["complete"] = Complete(client=self.client, function_execution_id=self.function_execution_id)
-        return self["complete"]
-
-    @property
-    def fail(self) -> Fail:
-        """`fail()` function for this request. Once a custom function's state is set to error,
-        its housing workflow will be interrupted and any provided error message will be passed
-        on to the end user through SlackBot. Additionally, any interactivity handlers associated
-        to a function invocation will no longer be invocable.
-
-            @app.function("reverse")
-            def handle_button_clicks(ack, fail):
-                ack()
-                fail(error="something went wrong")
-
-            @app.function("reverse")
-            def handle_button_clicks(context):
-                context.ack()
-                context.fail(error="something went wrong")
-
-        Returns:
-            Callable `fail()` function
-        """
-        if "fail" not in self:
-            self["fail"] = Fail(client=self.client, function_execution_id=self.function_execution_id)
-        return self["fail"]
-
-    @property
-    def set_title(self) -> Optional[SetTitle]:
-        return self.get("set_title")
-
-    @property
-    def set_status(self) -> Optional[SetStatus]:
-        return self.get("set_status")
-
-    @property
-    def set_suggested_prompts(self) -> Optional[SetSuggestedPrompts]:
-        return self.get("set_suggested_prompts")
-
-    @property
-    def get_thread_context(self) -> Optional[GetThreadContext]:
-        return self.get("get_thread_context")
-
-    @property
-    def say_stream(self) -> Optional[SayStream]:
-        return self.get("say_stream")
-
-    @property
-    def save_thread_context(self) -> Optional[SaveThreadContext]:
-        return self.get("save_thread_context")
-
-

Context object associated with a request from Slack.

-

Ancestors

- -

Instance variables

-
-
prop ackAck
-
-
- -Expand source code - -
@property
-def ack(self) -> Ack:
-    """`ack()` function for this request.
-
-        @app.action("button")
-        def handle_button_clicks(context):
-            context.ack()
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        def handle_button_clicks(ack):
-            ack()
-
-    Returns:
-        Callable `ack()` function
-    """
-    if "ack" not in self:
-        self["ack"] = Ack()
-    return self["ack"]
-
-

ack() function for this request.

-
@app.action("button")
-def handle_button_clicks(context):
-    context.ack()
-
-# You can access "ack" this way too.
-@app.action("button")
-def handle_button_clicks(ack):
-    ack()
-
-

Returns

-

Callable ack() function

-
-
prop client : slack_sdk.web.client.WebClient
-
-
- -Expand source code - -
@property
-def client(self) -> WebClient:
-    """The `WebClient` instance available for this request.
-
-        @app.event("app_mention")
-        def handle_events(context):
-            context.client.chat_postMessage(
-                channel=context.channel_id,
-                text="Thanks!",
-            )
-
-        # You can access "client" this way too.
-        @app.event("app_mention")
-        def handle_events(client, context):
-            client.chat_postMessage(
-                channel=context.channel_id,
-                text="Thanks!",
-            )
-
-    Returns:
-        `WebClient` instance
-    """
-    if "client" not in self:
-        self["client"] = WebClient(token=None)
-    return self["client"]
-
-

The WebClient instance available for this request.

-
@app.event("app_mention")
-def handle_events(context):
-    context.client.chat_postMessage(
-        channel=context.channel_id,
-        text="Thanks!",
-    )
-
-# You can access "client" this way too.
-@app.event("app_mention")
-def handle_events(client, context):
-    client.chat_postMessage(
-        channel=context.channel_id,
-        text="Thanks!",
-    )
-
-

Returns

-

WebClient instance

-
-
prop completeComplete
-
-
- -Expand source code - -
@property
-def complete(self) -> Complete:
-    """`complete()` function for this request. Once a custom function's state is set to complete,
-    any outputs the function returns will be passed along to the next step of its housing workflow,
-    or complete the workflow if the function is the last step in a workflow. Additionally,
-    any interactivity handlers associated to a function invocation will no longer be invocable.
-
-        @app.function("reverse")
-        def handle_button_clicks(ack, complete):
-            ack()
-            complete(outputs={"stringReverse":"olleh"})
-
-        @app.function("reverse")
-        def handle_button_clicks(context):
-            context.ack()
-            context.complete(outputs={"stringReverse":"olleh"})
-
-    Returns:
-        Callable `complete()` function
-    """
-    if "complete" not in self:
-        self["complete"] = Complete(client=self.client, function_execution_id=self.function_execution_id)
-    return self["complete"]
-
-

complete() function for this request. Once a custom function's state is set to complete, -any outputs the function returns will be passed along to the next step of its housing workflow, -or complete the workflow if the function is the last step in a workflow. Additionally, -any interactivity handlers associated to a function invocation will no longer be invocable.

-
@app.function("reverse")
-def handle_button_clicks(ack, complete):
-    ack()
-    complete(outputs={"stringReverse":"olleh"})
-
-@app.function("reverse")
-def handle_button_clicks(context):
-    context.ack()
-    context.complete(outputs={"stringReverse":"olleh"})
-
-

Returns

-

Callable complete() function

-
-
prop failFail
-
-
- -Expand source code - -
@property
-def fail(self) -> Fail:
-    """`fail()` function for this request. Once a custom function's state is set to error,
-    its housing workflow will be interrupted and any provided error message will be passed
-    on to the end user through SlackBot. Additionally, any interactivity handlers associated
-    to a function invocation will no longer be invocable.
-
-        @app.function("reverse")
-        def handle_button_clicks(ack, fail):
-            ack()
-            fail(error="something went wrong")
-
-        @app.function("reverse")
-        def handle_button_clicks(context):
-            context.ack()
-            context.fail(error="something went wrong")
-
-    Returns:
-        Callable `fail()` function
-    """
-    if "fail" not in self:
-        self["fail"] = Fail(client=self.client, function_execution_id=self.function_execution_id)
-    return self["fail"]
-
-

fail() function for this request. Once a custom function's state is set to error, -its housing workflow will be interrupted and any provided error message will be passed -on to the end user through SlackBot. Additionally, any interactivity handlers associated -to a function invocation will no longer be invocable.

-
@app.function("reverse")
-def handle_button_clicks(ack, fail):
-    ack()
-    fail(error="something went wrong")
-
-@app.function("reverse")
-def handle_button_clicks(context):
-    context.ack()
-    context.fail(error="something went wrong")
-
-

Returns

-

Callable fail() function

-
-
prop get_thread_contextGetThreadContext | None
-
-
- -Expand source code - -
@property
-def get_thread_context(self) -> Optional[GetThreadContext]:
-    return self.get("get_thread_context")
-
-
-
-
prop listener_runner : ThreadListenerRunner
-
-
- -Expand source code - -
@property
-def listener_runner(self) -> "ThreadListenerRunner":
-    """The properly configured listener_runner that is available for middleware/listeners."""
-    return self["listener_runner"]
-
-

The properly configured listener_runner that is available for middleware/listeners.

-
-
prop respondRespond | None
-
-
- -Expand source code - -
@property
-def respond(self) -> Optional[Respond]:
-    """`respond()` function for this request.
-
-        @app.action("button")
-        def handle_button_clicks(context):
-            context.ack()
-            context.respond("Hi!")
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        def handle_button_clicks(ack, respond):
-            ack()
-            respond("Hi!")
-
-    Returns:
-        Callable `respond()` function
-    """
-    if "respond" not in self:
-        self["respond"] = Respond(
-            response_url=self.response_url,
-            proxy=self.client.proxy,
-            ssl=self.client.ssl,
-        )
-    return self["respond"]
-
-

respond() function for this request.

-
@app.action("button")
-def handle_button_clicks(context):
-    context.ack()
-    context.respond("Hi!")
-
-# You can access "ack" this way too.
-@app.action("button")
-def handle_button_clicks(ack, respond):
-    ack()
-    respond("Hi!")
-
-

Returns

-

Callable respond() function

-
-
prop save_thread_contextSaveThreadContext | None
-
-
- -Expand source code - -
@property
-def save_thread_context(self) -> Optional[SaveThreadContext]:
-    return self.get("save_thread_context")
-
-
-
-
prop saySay
-
-
- -Expand source code - -
@property
-def say(self) -> Say:
-    """`say()` function for this request.
-
-        @app.action("button")
-        def handle_button_clicks(context):
-            context.ack()
-            context.say("Hi!")
-
-        # You can access "ack" this way too.
-        @app.action("button")
-        def handle_button_clicks(ack, say):
-            ack()
-            say("Hi!")
-
-    Returns:
-        Callable `say()` function
-    """
-    if "say" not in self:
-        self["say"] = Say(client=self.client, channel=self.channel_id)
-    return self["say"]
-
-

say() function for this request.

-
@app.action("button")
-def handle_button_clicks(context):
-    context.ack()
-    context.say("Hi!")
-
-# You can access "ack" this way too.
-@app.action("button")
-def handle_button_clicks(ack, say):
-    ack()
-    say("Hi!")
-
-

Returns

-

Callable say() function

-
-
prop say_streamSayStream | None
-
-
- -Expand source code - -
@property
-def say_stream(self) -> Optional[SayStream]:
-    return self.get("say_stream")
-
-
-
-
prop set_statusSetStatus | None
-
-
- -Expand source code - -
@property
-def set_status(self) -> Optional[SetStatus]:
-    return self.get("set_status")
-
-
-
-
prop set_suggested_promptsSetSuggestedPrompts | None
-
-
- -Expand source code - -
@property
-def set_suggested_prompts(self) -> Optional[SetSuggestedPrompts]:
-    return self.get("set_suggested_prompts")
-
-
-
-
prop set_titleSetTitle | None
-
-
- -Expand source code - -
@property
-def set_title(self) -> Optional[SetTitle]:
-    return self.get("set_title")
-
-
-
-
-

Methods

-
-
-def to_copyable(self) ‑> BoltContext -
-
-
- -Expand source code - -
def to_copyable(self) -> "BoltContext":
-    new_dict = {}
-    for prop_name, prop_value in self.items():
-        if prop_name in self.copyable_standard_property_names:
-            # all the standard properties are copiable
-            new_dict[prop_name] = prop_value
-        elif prop_name in self.non_copyable_standard_property_names:
-            # Do nothing with this property (e.g., listener_runner)
-            continue
-        else:
-            try:
-                copied_value = create_copy(prop_value)
-                new_dict[prop_name] = copied_value
-            except TypeError as te:
-                self.logger.warning(
-                    f"Skipped setting '{prop_name}' to a copied request for lazy listeners "
-                    "due to a deep-copy creation error. Consider passing the value not as part of context object "
-                    f"(error: {te})"
-                )
-    return BoltContext(new_dict)
-
-
-
-
-

Inherited members

- -
-
-class BoltRequest -(*,
body: str | dict,
query: str | Dict[str, str] | Dict[str, Sequence[str]] | None = None,
headers: Dict[str, str | Sequence[str]] | None = None,
context: Dict[str, Any] | None = None,
mode: str = 'http')
-
-
-
- -Expand source code - -
class BoltRequest:
-    raw_body: str
-    query: Dict[str, Sequence[str]]
-    headers: Dict[str, Sequence[str]]
-    content_type: Optional[str]
-    body: Dict[str, Any]
-    context: BoltContext
-    lazy_only: bool
-    lazy_function_name: Optional[str]
-    mode: str  # either "http" or "socket_mode"
-
-    def __init__(
-        self,
-        *,
-        body: Union[str, dict],
-        query: Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]] = None,
-        headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None,
-        context: Optional[Dict[str, Any]] = None,
-        mode: str = "http",  # either "http" or "socket_mode"
-    ):
-        """Request to a Bolt app.
-
-        Args:
-            body: The raw request body (only plain text is supported for "http" mode)
-            query: The query string data in any data format.
-            headers: The request headers.
-            context: The context in this request.
-            mode: The mode used for this request. (either "http" or "socket_mode")
-        """
-        if mode == "http":
-            # HTTP Mode
-            if body is not None and not isinstance(body, str):
-                raise BoltError(error_message_raw_body_required_in_http_mode())
-            self.raw_body = body if body is not None else ""
-        else:
-            # Socket Mode
-            if body is not None and isinstance(body, str):
-                self.raw_body = body
-            else:
-                # We don't convert the dict value to str
-                # as doing so does not guarantee to keep the original structure/format.
-                self.raw_body = ""
-
-        self.query = parse_query(query)
-        self.headers = build_normalized_headers(headers)
-        self.content_type = extract_content_type(self.headers)
-
-        if isinstance(body, str):
-            self.body = parse_body(self.raw_body, self.content_type)
-        elif isinstance(body, dict):
-            self.body = body
-        else:
-            self.body = {}
-
-        self.context = build_context(BoltContext(context if context else {}), self.body)
-        self.lazy_only = bool(self.headers.get("x-slack-bolt-lazy-only", [False])[0])
-        self.lazy_function_name = self.headers.get("x-slack-bolt-lazy-function-name", [None])[0]
-        self.mode = mode
-
-    def to_copyable(self) -> "BoltRequest":
-        body: Union[str, dict] = self.raw_body if self.mode == "http" else self.body
-        return BoltRequest(
-            body=body,
-            query=self.query,
-            headers=self.headers,
-            context=self.context.to_copyable(),
-            mode=self.mode,
-        )
-
-

Request to a Bolt app.

-

Args

-
-
body
-
The raw request body (only plain text is supported for "http" mode)
-
query
-
The query string data in any data format.
-
headers
-
The request headers.
-
context
-
The context in this request.
-
mode
-
The mode used for this request. (either "http" or "socket_mode")
-
-

Class variables

-
-
var body : Dict[str, Any]
-
-

The type of the None singleton.

-
-
var content_type : str | None
-
-

The type of the None singleton.

-
-
var contextBoltContext
-
-

The type of the None singleton.

-
-
var headers : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var lazy_function_name : str | None
-
-

The type of the None singleton.

-
-
var lazy_only : bool
-
-

The type of the None singleton.

-
-
var mode : str
-
-

The type of the None singleton.

-
-
var query : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var raw_body : str
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def to_copyable(self) ‑> BoltRequest -
-
-
- -Expand source code - -
def to_copyable(self) -> "BoltRequest":
-    body: Union[str, dict] = self.raw_body if self.mode == "http" else self.body
-    return BoltRequest(
-        body=body,
-        query=self.query,
-        headers=self.headers,
-        context=self.context.to_copyable(),
-        mode=self.mode,
-    )
-
-
-
-
-
-
-class BoltResponse -(*,
status: int,
body: str | dict = '',
headers: Dict[str, str | Sequence[str]] | None = None)
-
-
-
- -Expand source code - -
class BoltResponse:
-    status: int
-    body: str
-    headers: Dict[str, Sequence[str]]
-
-    def __init__(
-        self,
-        *,
-        status: int,
-        body: Union[str, dict] = "",
-        headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None,
-    ):
-        """The response from a Bolt app.
-
-        Args:
-            status: HTTP status code
-            body: The response body (dict and str are supported)
-            headers: The response headers.
-        """
-        self.status: int = status
-        self.body: str = json.dumps(body) if isinstance(body, dict) else body
-        self.headers: Dict[str, Sequence[str]] = {}
-        if headers is not None:
-            for name, value in headers.items():
-                if value is None:
-                    continue
-                if isinstance(value, list):
-                    self.headers[name.lower()] = value
-                elif isinstance(value, set):
-                    self.headers[name.lower()] = list(value)
-                else:
-                    self.headers[name.lower()] = [str(value)]
-
-        if "content-type" not in self.headers.keys():
-            if self.body and self.body.startswith("{"):
-                self.headers["content-type"] = ["application/json;charset=utf-8"]
-            else:
-                self.headers["content-type"] = ["text/plain;charset=utf-8"]
-
-    def first_headers(self) -> Dict[str, str]:
-        return {k: list(v)[0] for k, v in self.headers.items()}
-
-    def first_headers_without_set_cookie(self) -> Dict[str, str]:
-        return {k: list(v)[0] for k, v in self.headers.items() if k != "set-cookie"}
-
-    def cookies(self) -> Sequence[SimpleCookie]:
-        header_values = self.headers.get("set-cookie", [])
-        return [self._to_simple_cookie(v) for v in header_values]
-
-    @staticmethod
-    def _to_simple_cookie(header_value: str) -> SimpleCookie:
-        c = SimpleCookie()
-        c.load(header_value)
-        return c
-
-

The response from a Bolt app.

-

Args

-
-
status
-
HTTP status code
-
body
-
The response body (dict and str are supported)
-
headers
-
The response headers.
-
-

Class variables

-
-
var body : str
-
-

The type of the None singleton.

-
-
var headers : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var status : int
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def cookies(self) ‑> Sequence[http.cookies.SimpleCookie] -
-
-
- -Expand source code - -
def cookies(self) -> Sequence[SimpleCookie]:
-    header_values = self.headers.get("set-cookie", [])
-    return [self._to_simple_cookie(v) for v in header_values]
-
-
-
-
-def first_headers(self) ‑> Dict[str, str] -
-
-
- -Expand source code - -
def first_headers(self) -> Dict[str, str]:
-    return {k: list(v)[0] for k, v in self.headers.items()}
-
-
-
- -
-
- -Expand source code - -
def first_headers_without_set_cookie(self) -> Dict[str, str]:
-    return {k: list(v)[0] for k, v in self.headers.items() if k != "set-cookie"}
-
-
-
-
-
-
-class Complete -(client: slack_sdk.web.client.WebClient, function_execution_id: str | None) -
-
-
- -Expand source code - -
class Complete:
-    client: WebClient
-    function_execution_id: Optional[str]
-    _called: bool
-
-    def __init__(
-        self,
-        client: WebClient,
-        function_execution_id: Optional[str],
-    ):
-        self.client = client
-        self.function_execution_id = function_execution_id
-        self._called = False
-
-    def __call__(self, outputs: Optional[Dict[str, Any]] = None) -> SlackResponse:
-        """Signal the successful completion of the custom function.
-
-        Kwargs:
-            outputs: Json serializable object containing the output values
-
-        Returns:
-            SlackResponse: The response object returned from slack
-
-        Raises:
-            ValueError: If this function cannot be used.
-        """
-        if self.function_execution_id is None:
-            raise ValueError("complete is unsupported here as there is no function_execution_id")
-
-        self._called = True
-        return self.client.functions_completeSuccess(function_execution_id=self.function_execution_id, outputs=outputs or {})
-
-    def has_been_called(self) -> bool:
-        """Check if this complete function has been called.
-
-        Returns:
-            bool: True if the complete function has been called, False otherwise.
-        """
-        return self._called
-
-
-

Class variables

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var function_execution_id : str | None
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def has_been_called(self) ‑> bool -
-
-
- -Expand source code - -
def has_been_called(self) -> bool:
-    """Check if this complete function has been called.
-
-    Returns:
-        bool: True if the complete function has been called, False otherwise.
-    """
-    return self._called
-
-

Check if this complete function has been called.

-

Returns

-
-
bool
-
True if the complete function has been called, False otherwise.
-
-
-
-
-
-class CustomListenerMatcher -(*,
app_name: str,
func: Callable[..., bool],
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class CustomListenerMatcher(ListenerMatcher):
-    app_name: str
-    func: Callable[..., bool]
-    arg_names: MutableSequence[str]
-    logger: Logger
-
-    def __init__(self, *, app_name: str, func: Callable[..., bool], base_logger: Optional[Logger] = None):
-        self.app_name = app_name
-        self.func = func
-        self.arg_names = get_arg_names_of_callable(func)
-        self.logger = get_bolt_app_logger(self.app_name, self.func, base_logger)
-
-    def matches(self, req: BoltRequest, resp: BoltResponse) -> bool:
-        return self.func(
-            **build_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,
-                request=req,
-                response=resp,
-                this_func=self.func,
-            )
-        )
-
-
-

Ancestors

- -

Class variables

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : MutableSequence[str]
-
-

The type of the None singleton.

-
-
var func : Callable[..., bool]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class Fail -(client: slack_sdk.web.client.WebClient, function_execution_id: str | None) -
-
-
- -Expand source code - -
class Fail:
-    client: WebClient
-    function_execution_id: Optional[str]
-    _called: bool
-
-    def __init__(
-        self,
-        client: WebClient,
-        function_execution_id: Optional[str],
-    ):
-        self.client = client
-        self.function_execution_id = function_execution_id
-        self._called = False
-
-    def __call__(self, error: str) -> SlackResponse:
-        """Signal that the custom function failed to complete.
-
-        Kwargs:
-            error: Error message to return to slack
-
-        Returns:
-            SlackResponse: The response object returned from slack
-
-        Raises:
-            ValueError: If this function cannot be used.
-        """
-        if self.function_execution_id is None:
-            raise ValueError("fail is unsupported here as there is no function_execution_id")
-
-        self._called = True
-        return self.client.functions_completeError(function_execution_id=self.function_execution_id, error=error)
-
-    def has_been_called(self) -> bool:
-        """Check if this fail function has been called.
-
-        Returns:
-            bool: True if the fail function has been called, False otherwise.
-        """
-        return self._called
-
-
-

Class variables

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var function_execution_id : str | None
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def has_been_called(self) ‑> bool -
-
-
- -Expand source code - -
def has_been_called(self) -> bool:
-    """Check if this fail function has been called.
-
-    Returns:
-        bool: True if the fail function has been called, False otherwise.
-    """
-    return self._called
-
-

Check if this fail function has been called.

-

Returns

-
-
bool
-
True if the fail function has been called, False otherwise.
-
-
-
-
-
-class FileAssistantThreadContextStore -(base_dir: str = '/Users/wbergamin/.bolt-app-assistant-thread-contexts') -
-
-
- -Expand source code - -
class FileAssistantThreadContextStore(AssistantThreadContextStore):
-
-    def __init__(
-        self,
-        base_dir: str = str(Path.home()) + "/.bolt-app-assistant-thread-contexts",
-    ):
-        self.base_dir = base_dir
-        self._mkdir(self.base_dir)
-
-    def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-        path = f"{self.base_dir}/{channel_id}-{thread_ts}.json"
-        with open(path, "w") as f:
-            f.write(json.dumps(context))
-
-    def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-        path = f"{self.base_dir}/{channel_id}-{thread_ts}.json"
-        try:
-            with open(path) as f:
-                data = json.loads(f.read())
-                if data.get("channel_id") is not None:
-                    return AssistantThreadContext(data)
-        except FileNotFoundError:
-            pass
-        return None
-
-    @staticmethod
-    def _mkdir(path: Union[str, Path]):
-        if isinstance(path, str):
-            path = Path(path)
-        path.mkdir(parents=True, exist_ok=True)
-
-
-

Ancestors

- -

Methods

-
-
-def find(self, *, channel_id: str, thread_ts: str) ‑> AssistantThreadContext | None -
-
-
- -Expand source code - -
def find(self, *, channel_id: str, thread_ts: str) -> Optional[AssistantThreadContext]:
-    path = f"{self.base_dir}/{channel_id}-{thread_ts}.json"
-    try:
-        with open(path) as f:
-            data = json.loads(f.read())
-            if data.get("channel_id") is not None:
-                return AssistantThreadContext(data)
-    except FileNotFoundError:
-        pass
-    return None
-
-
-
-
-def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) ‑> None -
-
-
- -Expand source code - -
def save(self, *, channel_id: str, thread_ts: str, context: Dict[str, str]) -> None:
-    path = f"{self.base_dir}/{channel_id}-{thread_ts}.json"
-    with open(path, "w") as f:
-        f.write(json.dumps(context))
-
-
-
-
-
-
-class Listener -
-
-
- -Expand source code - -
class Listener(metaclass=ABCMeta):
-    matchers: Sequence[ListenerMatcher]
-    middleware: Sequence[Middleware]
-    ack_function: Callable[..., BoltResponse]
-    lazy_functions: Sequence[Callable[..., None]]
-    auto_acknowledgement: bool
-    ack_timeout: int = 3
-
-    def matches(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-    ) -> bool:
-        is_matched: bool = False
-        for matcher in self.matchers:
-            is_matched = matcher.matches(req, resp)
-            if not is_matched:
-                return is_matched
-        return is_matched
-
-    def run_middleware(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-    ) -> Tuple[Optional[BoltResponse], bool]:
-        """Runs a middleware.
-
-        Args:
-            req: The incoming request
-            resp: The current response
-
-        Returns:
-            A tuple of the processed response and a flag indicating termination
-        """
-        for m in self.middleware:
-            middleware_state = {"next_called": False}
-
-            def next_():
-                middleware_state["next_called"] = True
-
-            resp = m.process(req=req, resp=resp, next=next_)  # type: ignore[assignment]
-            if not middleware_state["next_called"]:
-                # next() was not called in this middleware
-                return (resp, True)
-        return (resp, False)
-
-    @abstractmethod
-    def run_ack_function(self, *, request: BoltRequest, response: BoltResponse) -> Optional[BoltResponse]:
-        """Runs all the registered middleware and then run the listener function.
-
-        Args:
-            request: The incoming request
-            response: The current response
-
-        Returns:
-            The processed response
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Class variables

-
-
var ack_function : Callable[..., BoltResponse]
-
-

The type of the None singleton.

-
-
var ack_timeout : int
-
-

The type of the None singleton.

-
-
var auto_acknowledgement : bool
-
-

The type of the None singleton.

-
-
var lazy_functions : Sequence[Callable[..., None]]
-
-

The type of the None singleton.

-
-
var matchers : Sequence[ListenerMatcher]
-
-

The type of the None singleton.

-
-
var middleware : Sequence[Middleware]
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def matches(self,
*,
req: BoltRequest,
resp: BoltResponse) ‑> bool
-
-
-
- -Expand source code - -
def matches(
-    self,
-    *,
-    req: BoltRequest,
-    resp: BoltResponse,
-) -> bool:
-    is_matched: bool = False
-    for matcher in self.matchers:
-        is_matched = matcher.matches(req, resp)
-        if not is_matched:
-            return is_matched
-    return is_matched
-
-
-
-
-def run_ack_function(self,
*,
request: BoltRequest,
response: BoltResponse) ‑> BoltResponse | None
-
-
-
- -Expand source code - -
@abstractmethod
-def run_ack_function(self, *, request: BoltRequest, response: BoltResponse) -> Optional[BoltResponse]:
-    """Runs all the registered middleware and then run the listener function.
-
-    Args:
-        request: The incoming request
-        response: The current response
-
-    Returns:
-        The processed response
-    """
-    raise NotImplementedError()
-
-

Runs all the registered middleware and then run the listener function.

-

Args

-
-
request
-
The incoming request
-
response
-
The current response
-
-

Returns

-

The processed response

-
-
-def run_middleware(self,
*,
req: BoltRequest,
resp: BoltResponse) ‑> Tuple[BoltResponse | None, bool]
-
-
-
- -Expand source code - -
def run_middleware(
-    self,
-    *,
-    req: BoltRequest,
-    resp: BoltResponse,
-) -> Tuple[Optional[BoltResponse], bool]:
-    """Runs a middleware.
-
-    Args:
-        req: The incoming request
-        resp: The current response
-
-    Returns:
-        A tuple of the processed response and a flag indicating termination
-    """
-    for m in self.middleware:
-        middleware_state = {"next_called": False}
-
-        def next_():
-            middleware_state["next_called"] = True
-
-        resp = m.process(req=req, resp=resp, next=next_)  # type: ignore[assignment]
-        if not middleware_state["next_called"]:
-            # next() was not called in this middleware
-            return (resp, True)
-    return (resp, False)
-
-

Runs a middleware.

-

Args

-
-
req
-
The incoming request
-
resp
-
The current response
-
-

Returns

-

A tuple of the processed response and a flag indicating termination

-
-
-
-
-class Respond -(*,
response_url: str | None,
proxy: str | None = None,
ssl: ssl.SSLContext | None = None)
-
-
-
- -Expand source code - -
class Respond:
-    response_url: Optional[str]
-    proxy: Optional[str]
-    ssl: Optional[SSLContext]
-
-    def __init__(
-        self,
-        *,
-        response_url: Optional[str],
-        proxy: Optional[str] = None,
-        ssl: Optional[SSLContext] = None,
-    ):
-        self.response_url = response_url
-        self.proxy = proxy
-        self.ssl = ssl
-
-    def __call__(
-        self,
-        text: Union[str, dict] = "",
-        blocks: Optional[Sequence[Union[dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[dict, Attachment]]] = None,
-        response_type: Optional[str] = None,
-        replace_original: Optional[bool] = None,
-        delete_original: Optional[bool] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        thread_ts: Optional[str] = None,
-        metadata: Optional[Dict[str, Any]] = None,
-    ) -> WebhookResponse:
-        if self.response_url is not None:
-            client = WebhookClient(
-                url=self.response_url,
-                proxy=self.proxy,
-                ssl=self.ssl,
-            )
-            text_or_whole_response: Union[str, dict] = text
-            if isinstance(text_or_whole_response, str):
-                text = text_or_whole_response
-                message = _build_message(
-                    text=text,
-                    blocks=blocks,
-                    attachments=attachments,
-                    response_type=response_type,
-                    replace_original=replace_original,
-                    delete_original=delete_original,
-                    unfurl_links=unfurl_links,
-                    unfurl_media=unfurl_media,
-                    thread_ts=thread_ts,
-                    metadata=metadata,
-                )
-                return client.send_dict(message)
-            elif isinstance(text_or_whole_response, dict):
-                message = _build_message(**text_or_whole_response)
-                return client.send_dict(message)
-            else:
-                raise ValueError(f"The arg is unexpected type ({type(text_or_whole_response)})")
-        else:
-            raise ValueError("respond is unsupported here as there is no response_url")
-
-
-

Class variables

-
-
var proxy : str | None
-
-

The type of the None singleton.

-
-
var response_url : str | None
-
-

The type of the None singleton.

-
-
var ssl : ssl.SSLContext | None
-
-

The type of the None singleton.

-
-
-
-
-class SaveThreadContext -(thread_context_store: AssistantThreadContextStore,
channel_id: str,
thread_ts: str)
-
-
-
- -Expand source code - -
class SaveThreadContext:
-    thread_context_store: AssistantThreadContextStore
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        thread_context_store: AssistantThreadContextStore,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.thread_context_store = thread_context_store
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    def __call__(self, new_context: Dict[str, str]) -> None:
-        self.thread_context_store.save(
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-            context=new_context,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var thread_context_storeAssistantThreadContextStore
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-class Say -(client: slack_sdk.web.client.WebClient | None,
channel: str | None,
thread_ts: str | None = None,
metadata: Dict | slack_sdk.models.metadata.Metadata | None = None,
build_metadata: Callable[[], Dict | slack_sdk.models.metadata.Metadata | None] | None = None)
-
-
-
- -Expand source code - -
class Say:
-    client: Optional[WebClient]
-    channel: Optional[str]
-    thread_ts: Optional[str]
-    metadata: Optional[Union[Dict, Metadata]]
-    build_metadata: Optional[Callable[[], Optional[Union[Dict, Metadata]]]]
-
-    def __init__(
-        self,
-        client: Optional[WebClient],
-        channel: Optional[str],
-        thread_ts: Optional[str] = None,
-        metadata: Optional[Union[Dict, Metadata]] = None,
-        build_metadata: Optional[Callable[[], Optional[Union[Dict, Metadata]]]] = None,
-    ):
-        self.client = client
-        self.channel = channel
-        self.thread_ts = thread_ts
-        self.metadata = metadata
-        self.build_metadata = build_metadata
-
-    def __call__(
-        self,
-        text: Union[str, dict] = "",
-        blocks: Optional[Sequence[Union[Dict, Block]]] = None,
-        attachments: Optional[Sequence[Union[Dict, Attachment]]] = None,
-        channel: Optional[str] = None,
-        as_user: Optional[bool] = None,
-        thread_ts: Optional[str] = None,
-        reply_broadcast: Optional[bool] = None,
-        unfurl_links: Optional[bool] = None,
-        unfurl_media: Optional[bool] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        markdown_text: Optional[str] = None,
-        mrkdwn: Optional[bool] = None,
-        link_names: Optional[bool] = None,
-        parse: Optional[str] = None,  # none, full
-        metadata: Optional[Union[Dict, Metadata]] = None,
-        **kwargs,
-    ) -> SlackResponse:
-        if _can_say(self, channel):
-            text_or_whole_response: Union[str, dict] = text
-            if isinstance(text_or_whole_response, str):
-                text = text_or_whole_response
-                if metadata is None:
-                    metadata = self.build_metadata() if self.build_metadata is not None else self.metadata
-                return self.client.chat_postMessage(  # type: ignore[union-attr]
-                    channel=channel or self.channel,  # type: ignore[arg-type]
-                    text=text,
-                    blocks=blocks,
-                    attachments=attachments,
-                    as_user=as_user,
-                    thread_ts=thread_ts or self.thread_ts,
-                    reply_broadcast=reply_broadcast,
-                    unfurl_links=unfurl_links,
-                    unfurl_media=unfurl_media,
-                    icon_emoji=icon_emoji,
-                    icon_url=icon_url,
-                    username=username,
-                    markdown_text=markdown_text,
-                    mrkdwn=mrkdwn,
-                    link_names=link_names,
-                    parse=parse,
-                    metadata=metadata,
-                    **kwargs,
-                )
-            elif isinstance(text_or_whole_response, dict):
-                message: dict = create_copy(text_or_whole_response)
-                if "channel" not in message:
-                    message["channel"] = channel or self.channel
-                if "thread_ts" not in message:
-                    message["thread_ts"] = thread_ts or self.thread_ts
-                if "metadata" not in message:
-                    metadata = self.build_metadata() if self.build_metadata is not None else self.metadata
-                    message["metadata"] = metadata
-                return self.client.chat_postMessage(**message)  # type: ignore[union-attr]
-            else:
-                raise ValueError(f"The arg is unexpected type ({type(text_or_whole_response)})")
-        else:
-            raise ValueError("say without channel_id here is unsupported")
-
-
-

Class variables

-
-
var build_metadata : Callable[[], Dict | slack_sdk.models.metadata.Metadata | None] | None
-
-

The type of the None singleton.

-
-
var channel : str | None
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient | None
-
-

The type of the None singleton.

-
-
var metadata : Dict | slack_sdk.models.metadata.Metadata | None
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-class SayStream -(*,
client: slack_sdk.web.client.WebClient,
channel: str | None = None,
recipient_team_id: str | None = None,
recipient_user_id: str | None = None,
thread_ts: str | None = None)
-
-
-
- -Expand source code - -
class SayStream:
-    client: WebClient
-    channel: Optional[str]
-    recipient_team_id: Optional[str]
-    recipient_user_id: Optional[str]
-    thread_ts: Optional[str]
-
-    def __init__(
-        self,
-        *,
-        client: WebClient,
-        channel: Optional[str] = None,
-        recipient_team_id: Optional[str] = None,
-        recipient_user_id: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-    ):
-        self.client = client
-        self.channel = channel
-        self.recipient_team_id = recipient_team_id
-        self.recipient_user_id = recipient_user_id
-        self.thread_ts = thread_ts
-
-    def __call__(
-        self,
-        *,
-        buffer_size: Optional[int] = None,
-        channel: Optional[str] = None,
-        recipient_team_id: Optional[str] = None,
-        recipient_user_id: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        **kwargs,
-    ) -> ChatStream:
-        """Starts a new chat stream with context."""
-        channel = channel or self.channel
-        thread_ts = thread_ts or self.thread_ts
-        if channel is None:
-            raise ValueError("say_stream without channel here is unsupported")
-        if thread_ts is None:
-            raise ValueError("say_stream without thread_ts here is unsupported")
-
-        if buffer_size is not None:
-            return self.client.chat_stream(
-                buffer_size=buffer_size,
-                channel=channel,
-                recipient_team_id=recipient_team_id or self.recipient_team_id,
-                recipient_user_id=recipient_user_id or self.recipient_user_id,
-                thread_ts=thread_ts,
-                icon_emoji=icon_emoji,
-                icon_url=icon_url,
-                username=username,
-                **kwargs,
-            )
-        return self.client.chat_stream(
-            channel=channel,
-            recipient_team_id=recipient_team_id or self.recipient_team_id,
-            recipient_user_id=recipient_user_id or self.recipient_user_id,
-            thread_ts=thread_ts,
-            icon_emoji=icon_emoji,
-            icon_url=icon_url,
-            username=username,
-            **kwargs,
-        )
-
-
-

Class variables

-
-
var channel : str | None
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var recipient_team_id : str | None
-
-

The type of the None singleton.

-
-
var recipient_user_id : str | None
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-class SetStatus -(client: slack_sdk.web.client.WebClient, channel_id: str, thread_ts: str) -
-
-
- -Expand source code - -
class SetStatus:
-    client: WebClient
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        client: WebClient,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    def __call__(
-        self,
-        status: str,
-        loading_messages: Optional[List[str]] = None,
-        icon_emoji: Optional[str] = None,
-        icon_url: Optional[str] = None,
-        username: Optional[str] = None,
-        **kwargs,
-    ) -> SlackResponse:
-        return self.client.assistant_threads_setStatus(
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-            status=status,
-            loading_messages=loading_messages,
-            icon_emoji=icon_emoji,
-            icon_url=icon_url,
-            username=username,
-            **kwargs,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-class SetSuggestedPrompts -(client: slack_sdk.web.client.WebClient,
channel_id: str,
thread_ts: str | None = None)
-
-
-
- -Expand source code - -
class SetSuggestedPrompts:
-    client: WebClient
-    channel_id: str
-    thread_ts: Optional[str]
-
-    def __init__(
-        self,
-        client: WebClient,
-        channel_id: str,
-        thread_ts: Optional[str] = None,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    def __call__(
-        self,
-        prompts: Sequence[Union[str, Dict[str, str]]],
-        title: Optional[str] = None,
-        thread_ts: Optional[str] = None,
-    ) -> SlackResponse:
-        prompts_arg: List[Dict[str, str]] = []
-        for prompt in prompts:
-            if isinstance(prompt, str):
-                prompts_arg.append({"title": prompt, "message": prompt})
-            else:
-                prompts_arg.append(prompt)
-
-        return self.client.assistant_threads_setSuggestedPrompts(
-            channel_id=self.channel_id,
-            thread_ts=thread_ts if thread_ts is not None else self.thread_ts,
-            prompts=prompts_arg,
-            title=title,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str | None
-
-

The type of the None singleton.

-
-
-
-
-class SetTitle -(client: slack_sdk.web.client.WebClient, channel_id: str, thread_ts: str) -
-
-
- -Expand source code - -
class SetTitle:
-    client: WebClient
-    channel_id: str
-    thread_ts: str
-
-    def __init__(
-        self,
-        client: WebClient,
-        channel_id: str,
-        thread_ts: str,
-    ):
-        self.client = client
-        self.channel_id = channel_id
-        self.thread_ts = thread_ts
-
-    def __call__(self, title: str) -> SlackResponse:
-        return self.client.assistant_threads_setTitle(
-            title=title,
-            channel_id=self.channel_id,
-            thread_ts=self.thread_ts,
-        )
-
-
-

Class variables

-
-
var channel_id : str
-
-

The type of the None singleton.

-
-
var client : slack_sdk.web.client.WebClient
-
-

The type of the None singleton.

-
-
var thread_ts : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/kwargs_injection/args.html b/docs/reference/kwargs_injection/args.html deleted file mode 100644 index bbba71eb8..000000000 --- a/docs/reference/kwargs_injection/args.html +++ /dev/null @@ -1,419 +0,0 @@ - - - - - - -slack_bolt.kwargs_injection.args API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.kwargs_injection.args

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Args -(*,
logger: logging.Logger,
client: slack_sdk.web.client.WebClient,
req: BoltRequest,
resp: BoltResponse,
context: BoltContext,
body: Dict[str, Any],
payload: Dict[str, Any],
options: Dict[str, Any] | None = None,
shortcut: Dict[str, Any] | None = None,
action: Dict[str, Any] | None = None,
view: Dict[str, Any] | None = None,
command: Dict[str, Any] | None = None,
event: Dict[str, Any] | None = None,
message: Dict[str, Any] | None = None,
ack: Ack,
say: Say,
respond: Respond,
complete: Complete,
fail: Fail,
set_status: SetStatus | None = None,
set_title: SetTitle | None = None,
set_suggested_prompts: SetSuggestedPrompts | None = None,
get_thread_context: GetThreadContext | None = None,
save_thread_context: SaveThreadContext | None = None,
say_stream: SayStream | None = None,
next: Callable[[], None],
**kwargs)
-
-
-
- -Expand source code - -
class Args:
-    """All the arguments in this class are available in any middleware / listeners.
-    You can inject the named variables in the argument list in arbitrary order.
-
-        @app.action("link_button")
-        def handle_buttons(ack, respond, logger, context, body, client):
-            logger.info(f"request body: {body}")
-            ack()
-            if context.channel_id is not None:
-                respond("Hi!")
-            client.views_open(
-                trigger_id=body["trigger_id"],
-                view={ ... }
-            )
-
-    Alternatively, you can include a parameter named `args` and it will be injected with an instance of this class.
-
-        @app.action("link_button")
-        def handle_buttons(args):
-            args.logger.info(f"request body: {args.body}")
-            args.ack()
-            if args.context.channel_id is not None:
-                args.respond("Hi!")
-            args.client.views_open(
-                trigger_id=args.body["trigger_id"],
-                view={ ... }
-            )
-
-    """
-
-    client: WebClient
-    """`slack_sdk.web.WebClient` instance with a valid token"""
-    logger: Logger
-    """Logger instance"""
-    req: BoltRequest
-    """Incoming request from Slack"""
-    resp: BoltResponse
-    """Response representation"""
-    request: BoltRequest
-    """Incoming request from Slack"""
-    response: BoltResponse
-    """Response representation"""
-    context: BoltContext
-    """Context data associated with the incoming request"""
-    body: Dict[str, Any]
-    """Parsed request body data"""
-    # payload
-    payload: Dict[str, Any]
-    """The unwrapped core data in the request body"""
-    options: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.options` listener"""
-    shortcut: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.shortcut` listener"""
-    action: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.action` listener"""
-    view: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.view` listener"""
-    command: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.command` listener"""
-    event: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.event` listener"""
-    message: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.message` listener"""
-    # utilities
-    ack: Ack
-    """`ack()` utility function, which returns acknowledgement to the Slack servers"""
-    say: Say
-    """`say()` utility function, which calls `chat.postMessage` API with the associated channel ID"""
-    respond: Respond
-    """`respond()` utility function, which utilizes the associated `response_url`"""
-    complete: Complete
-    """`complete()` utility function, signals a successful completion of the custom function"""
-    fail: Fail
-    """`fail()` utility function, signal that the custom function failed to complete"""
-    set_status: Optional[SetStatus]
-    """`set_status()` utility function for AI Agents & Assistants"""
-    set_title: Optional[SetTitle]
-    """`set_title()` utility function for AI Agents & Assistants"""
-    set_suggested_prompts: Optional[SetSuggestedPrompts]
-    """`set_suggested_prompts()` utility function for AI Agents & Assistants"""
-    get_thread_context: Optional[GetThreadContext]
-    """`get_thread_context()` utility function for AI Agents & Assistants"""
-    save_thread_context: Optional[SaveThreadContext]
-    """`save_thread_context()` utility function for AI Agents & Assistants"""
-    say_stream: Optional[SayStream]
-    """`say_stream()` utility function for conversations, AI Agents & Assistants"""
-    # middleware
-    next: Callable[[], None]
-    """`next()` utility function, which tells the middleware chain that it can continue with the next one"""
-    next_: Callable[[], None]
-    """An alias of `next()` for avoiding the Python built-in method overrides in middleware functions"""
-
-    def __init__(
-        self,
-        *,
-        logger: logging.Logger,
-        client: WebClient,
-        req: BoltRequest,
-        resp: BoltResponse,
-        context: BoltContext,
-        body: Dict[str, Any],
-        payload: Dict[str, Any],
-        options: Optional[Dict[str, Any]] = None,
-        shortcut: Optional[Dict[str, Any]] = None,
-        action: Optional[Dict[str, Any]] = None,
-        view: Optional[Dict[str, Any]] = None,
-        command: Optional[Dict[str, Any]] = None,
-        event: Optional[Dict[str, Any]] = None,
-        message: Optional[Dict[str, Any]] = None,
-        ack: Ack,
-        say: Say,
-        respond: Respond,
-        complete: Complete,
-        fail: Fail,
-        set_status: Optional[SetStatus] = None,
-        set_title: Optional[SetTitle] = None,
-        set_suggested_prompts: Optional[SetSuggestedPrompts] = None,
-        get_thread_context: Optional[GetThreadContext] = None,
-        save_thread_context: Optional[SaveThreadContext] = None,
-        say_stream: Optional[SayStream] = None,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], None],
-        **kwargs,  # noqa
-    ):
-        self.logger: logging.Logger = logger
-        self.client: WebClient = client
-        self.request = self.req = req
-        self.response = self.resp = resp
-        self.context: BoltContext = context
-
-        self.body: Dict[str, Any] = body
-        self.payload: Dict[str, Any] = payload
-        self.options: Optional[Dict[str, Any]] = options
-        self.shortcut: Optional[Dict[str, Any]] = shortcut
-        self.action: Optional[Dict[str, Any]] = action
-        self.view: Optional[Dict[str, Any]] = view
-        self.command: Optional[Dict[str, Any]] = command
-        self.event: Optional[Dict[str, Any]] = event
-        self.message: Optional[Dict[str, Any]] = message
-
-        self.ack: Ack = ack
-        self.say: Say = say
-        self.respond: Respond = respond
-        self.complete: Complete = complete
-        self.fail: Fail = fail
-
-        self.set_status = set_status
-        self.set_title = set_title
-        self.set_suggested_prompts = set_suggested_prompts
-        self.get_thread_context = get_thread_context
-        self.save_thread_context = save_thread_context
-        self.say_stream = say_stream
-
-        self.next: Callable[[], None] = next
-        self.next_: Callable[[], None] = next
-
-

All the arguments in this class are available in any middleware / listeners. -You can inject the named variables in the argument list in arbitrary order.

-
@app.action("link_button")
-def handle_buttons(ack, respond, logger, context, body, client):
-    logger.info(f"request body: {body}")
-    ack()
-    if context.channel_id is not None:
-        respond("Hi!")
-    client.views_open(
-        trigger_id=body["trigger_id"],
-        view={ ... }
-    )
-
-

Alternatively, you can include a parameter named args and it will be injected with an instance of this class.

-
@app.action("link_button")
-def handle_buttons(args):
-    args.logger.info(f"request body: {args.body}")
-    args.ack()
-    if args.context.channel_id is not None:
-        args.respond("Hi!")
-    args.client.views_open(
-        trigger_id=args.body["trigger_id"],
-        view={ ... }
-    )
-
-

Class variables

-
-
var ackAck
-
-

ack() utility function, which returns acknowledgement to the Slack servers

-
-
var action : Dict[str, Any] | None
-
-

An alias for payload in an @app.action listener

-
-
var body : Dict[str, Any]
-
-

Parsed request body data

-
-
var client : slack_sdk.web.client.WebClient
-
-

slack_sdk.web.WebClient instance with a valid token

-
-
var command : Dict[str, Any] | None
-
-

An alias for payload in an @app.command listener

-
-
var completeComplete
-
-

complete() utility function, signals a successful completion of the custom function

-
-
var contextBoltContext
-
-

Context data associated with the incoming request

-
-
var event : Dict[str, Any] | None
-
-

An alias for payload in an @app.event listener

-
-
var failFail
-
-

fail() utility function, signal that the custom function failed to complete

-
-
var get_thread_contextGetThreadContext | None
-
-

get_thread_context() utility function for AI Agents & Assistants

-
-
var logger : logging.Logger
-
-

Logger instance

-
-
var message : Dict[str, Any] | None
-
-

An alias for payload in an @app.message listener

-
-
var next : Callable[[], None]
-
-

next() utility function, which tells the middleware chain that it can continue with the next one

-
-
var next_ : Callable[[], None]
-
-

An alias of next() for avoiding the Python built-in method overrides in middleware functions

-
-
var options : Dict[str, Any] | None
-
-

An alias for payload in an @app.options listener

-
-
var payload : Dict[str, Any]
-
-

The unwrapped core data in the request body

-
-
var reqBoltRequest
-
-

Incoming request from Slack

-
-
var requestBoltRequest
-
-

Incoming request from Slack

-
-
var respBoltResponse
-
-

Response representation

-
-
var respondRespond
-
-

respond() utility function, which utilizes the associated response_url

-
-
var responseBoltResponse
-
-

Response representation

-
-
var save_thread_contextSaveThreadContext | None
-
-

save_thread_context() utility function for AI Agents & Assistants

-
-
var saySay
-
-

say() utility function, which calls chat.postMessage API with the associated channel ID

-
-
var say_streamSayStream | None
-
-

say_stream() utility function for conversations, AI Agents & Assistants

-
-
var set_statusSetStatus | None
-
-

set_status() utility function for AI Agents & Assistants

-
-
var set_suggested_promptsSetSuggestedPrompts | None
-
-

set_suggested_prompts() utility function for AI Agents & Assistants

-
-
var set_titleSetTitle | None
-
-

set_title() utility function for AI Agents & Assistants

-
-
var shortcut : Dict[str, Any] | None
-
-

An alias for payload in an @app.shortcut listener

-
-
var view : Dict[str, Any] | None
-
-

An alias for payload in an @app.view listener

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/kwargs_injection/async_args.html b/docs/reference/kwargs_injection/async_args.html deleted file mode 100644 index 5b0e7b70e..000000000 --- a/docs/reference/kwargs_injection/async_args.html +++ /dev/null @@ -1,416 +0,0 @@ - - - - - - -slack_bolt.kwargs_injection.async_args API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.kwargs_injection.async_args

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncArgs -(*,
logger: logging.Logger,
client: slack_sdk.web.async_client.AsyncWebClient,
req: AsyncBoltRequest,
resp: BoltResponse,
context: AsyncBoltContext,
body: Dict[str, Any],
payload: Dict[str, Any],
options: Dict[str, Any] | None = None,
shortcut: Dict[str, Any] | None = None,
action: Dict[str, Any] | None = None,
view: Dict[str, Any] | None = None,
command: Dict[str, Any] | None = None,
event: Dict[str, Any] | None = None,
message: Dict[str, Any] | None = None,
ack: AsyncAck,
say: AsyncSay,
respond: AsyncRespond,
complete: AsyncComplete,
fail: AsyncFail,
set_status: AsyncSetStatus | None = None,
set_title: AsyncSetTitle | None = None,
set_suggested_prompts: AsyncSetSuggestedPrompts | None = None,
get_thread_context: AsyncGetThreadContext | None = None,
save_thread_context: AsyncSaveThreadContext | None = None,
say_stream: AsyncSayStream | None = None,
next: Callable[[], Awaitable[None]],
**kwargs)
-
-
-
- -Expand source code - -
class AsyncArgs:
-    """All the arguments in this class are available in any middleware / listeners.
-    You can inject the named variables in the argument list in arbitrary order.
-
-        @app.action("link_button")
-        async def handle_buttons(ack, respond, logger, context, body, client):
-            logger.info(f"request body: {body}")
-            await ack()
-            if context.channel_id is not None:
-                await respond("Hi!")
-            await client.views_open(
-                trigger_id=body["trigger_id"],
-                view={ ... }
-            )
-
-    Alternatively, you can include a parameter named `args` and it will be injected with an instance of this class.
-
-        @app.action("link_button")
-        async def handle_buttons(args):
-            args.logger.info(f"request body: {args.body}")
-            await args.ack()
-            if args.context.channel_id is not None:
-                await args.respond("Hi!")
-            await args.client.views_open(
-                trigger_id=args.body["trigger_id"],
-                view={ ... }
-            )
-
-    """
-
-    logger: Logger
-    """Logger instance"""
-    client: AsyncWebClient
-    """`slack_sdk.web.async_client.AsyncWebClient` instance with a valid token"""
-    req: AsyncBoltRequest
-    """Incoming request from Slack"""
-    resp: BoltResponse
-    """Response representation"""
-    request: AsyncBoltRequest
-    """Incoming request from Slack"""
-    response: BoltResponse
-    """Response representation"""
-    context: AsyncBoltContext
-    """Context data associated with the incoming request"""
-    body: Dict[str, Any]
-    """Parsed request body data"""
-    # payload
-    payload: Dict[str, Any]
-    """The unwrapped core data in the request body"""
-    options: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.options` listener"""
-    shortcut: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.shortcut` listener"""
-    action: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.action` listener"""
-    view: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.view` listener"""
-    command: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.command` listener"""
-    event: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.event` listener"""
-    message: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.message` listener"""
-    # utilities
-    ack: AsyncAck
-    """`ack()` utility function, which returns acknowledgement to the Slack servers"""
-    say: AsyncSay
-    """`say()` utility function, which calls chat.postMessage API with the associated channel ID"""
-    respond: AsyncRespond
-    """`respond()` utility function, which utilizes the associated `response_url`"""
-    complete: AsyncComplete
-    """`complete()` utility function, signals a successful completion of the custom function"""
-    fail: AsyncFail
-    """`fail()` utility function, signal that the custom function failed to complete"""
-    set_status: Optional[AsyncSetStatus]
-    """`set_status()` utility function for AI Agents & Assistants"""
-    set_title: Optional[AsyncSetTitle]
-    """`set_title()` utility function for AI Agents & Assistants"""
-    set_suggested_prompts: Optional[AsyncSetSuggestedPrompts]
-    """`set_suggested_prompts()` utility function for AI Agents & Assistants"""
-    get_thread_context: Optional[AsyncGetThreadContext]
-    """`get_thread_context()` utility function for AI Agents & Assistants"""
-    save_thread_context: Optional[AsyncSaveThreadContext]
-    """`save_thread_context()` utility function for AI Agents & Assistants"""
-    say_stream: Optional[AsyncSayStream]
-    """`say_stream()` utility function for AI Agents & Assistants"""
-    # middleware
-    next: Callable[[], Awaitable[None]]
-    """`next()` utility function, which tells the middleware chain that it can continue with the next one"""
-    next_: Callable[[], Awaitable[None]]
-    """An alias of `next()` for avoiding the Python built-in method overrides in middleware functions"""
-
-    def __init__(
-        self,
-        *,
-        logger: Logger,
-        client: AsyncWebClient,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        context: AsyncBoltContext,
-        body: Dict[str, Any],
-        payload: Dict[str, Any],
-        options: Optional[Dict[str, Any]] = None,
-        shortcut: Optional[Dict[str, Any]] = None,
-        action: Optional[Dict[str, Any]] = None,
-        view: Optional[Dict[str, Any]] = None,
-        command: Optional[Dict[str, Any]] = None,
-        event: Optional[Dict[str, Any]] = None,
-        message: Optional[Dict[str, Any]] = None,
-        ack: AsyncAck,
-        say: AsyncSay,
-        respond: AsyncRespond,
-        complete: AsyncComplete,
-        fail: AsyncFail,
-        set_status: Optional[AsyncSetStatus] = None,
-        set_title: Optional[AsyncSetTitle] = None,
-        set_suggested_prompts: Optional[AsyncSetSuggestedPrompts] = None,
-        get_thread_context: Optional[AsyncGetThreadContext] = None,
-        save_thread_context: Optional[AsyncSaveThreadContext] = None,
-        say_stream: Optional[AsyncSayStream] = None,
-        next: Callable[[], Awaitable[None]],
-        **kwargs,  # noqa
-    ):
-        self.logger: Logger = logger
-        self.client: AsyncWebClient = client
-        self.request = self.req = req
-        self.response = self.resp = resp
-        self.context: AsyncBoltContext = context
-
-        self.body: Dict[str, Any] = body
-        self.payload: Dict[str, Any] = payload
-        self.options: Optional[Dict[str, Any]] = options
-        self.shortcut: Optional[Dict[str, Any]] = shortcut
-        self.action: Optional[Dict[str, Any]] = action
-        self.view: Optional[Dict[str, Any]] = view
-        self.command: Optional[Dict[str, Any]] = command
-        self.event: Optional[Dict[str, Any]] = event
-        self.message: Optional[Dict[str, Any]] = message
-
-        self.ack: AsyncAck = ack
-        self.say: AsyncSay = say
-        self.respond: AsyncRespond = respond
-        self.complete: AsyncComplete = complete
-        self.fail: AsyncFail = fail
-
-        self.set_status = set_status
-        self.set_title = set_title
-        self.set_suggested_prompts = set_suggested_prompts
-        self.get_thread_context = get_thread_context
-        self.save_thread_context = save_thread_context
-        self.say_stream = say_stream
-
-        self.next: Callable[[], Awaitable[None]] = next
-        self.next_: Callable[[], Awaitable[None]] = next
-
-

All the arguments in this class are available in any middleware / listeners. -You can inject the named variables in the argument list in arbitrary order.

-
@app.action("link_button")
-async def handle_buttons(ack, respond, logger, context, body, client):
-    logger.info(f"request body: {body}")
-    await ack()
-    if context.channel_id is not None:
-        await respond("Hi!")
-    await client.views_open(
-        trigger_id=body["trigger_id"],
-        view={ ... }
-    )
-
-

Alternatively, you can include a parameter named args and it will be injected with an instance of this class.

-
@app.action("link_button")
-async def handle_buttons(args):
-    args.logger.info(f"request body: {args.body}")
-    await args.ack()
-    if args.context.channel_id is not None:
-        await args.respond("Hi!")
-    await args.client.views_open(
-        trigger_id=args.body["trigger_id"],
-        view={ ... }
-    )
-
-

Class variables

-
-
var ackAsyncAck
-
-

ack() utility function, which returns acknowledgement to the Slack servers

-
-
var action : Dict[str, Any] | None
-
-

An alias for payload in an @app.action listener

-
-
var body : Dict[str, Any]
-
-

Parsed request body data

-
-
var client : slack_sdk.web.async_client.AsyncWebClient
-
-

slack_sdk.web.async_client.AsyncWebClient instance with a valid token

-
-
var command : Dict[str, Any] | None
-
-

An alias for payload in an @app.command listener

-
-
var completeAsyncComplete
-
-

complete() utility function, signals a successful completion of the custom function

-
-
var contextAsyncBoltContext
-
-

Context data associated with the incoming request

-
-
var event : Dict[str, Any] | None
-
-

An alias for payload in an @app.event listener

-
-
var failAsyncFail
-
-

fail() utility function, signal that the custom function failed to complete

-
-
var get_thread_contextAsyncGetThreadContext | None
-
-

get_thread_context() utility function for AI Agents & Assistants

-
-
var logger : logging.Logger
-
-

Logger instance

-
-
var message : Dict[str, Any] | None
-
-

An alias for payload in an @app.message listener

-
-
var next : Callable[[], Awaitable[None]]
-
-

next() utility function, which tells the middleware chain that it can continue with the next one

-
-
var next_ : Callable[[], Awaitable[None]]
-
-

An alias of next() for avoiding the Python built-in method overrides in middleware functions

-
-
var options : Dict[str, Any] | None
-
-

An alias for payload in an @app.options listener

-
-
var payload : Dict[str, Any]
-
-

The unwrapped core data in the request body

-
-
var reqAsyncBoltRequest
-
-

Incoming request from Slack

-
-
var requestAsyncBoltRequest
-
-

Incoming request from Slack

-
-
var respBoltResponse
-
-

Response representation

-
-
var respondAsyncRespond
-
-

respond() utility function, which utilizes the associated response_url

-
-
var responseBoltResponse
-
-

Response representation

-
-
var save_thread_contextAsyncSaveThreadContext | None
-
-

save_thread_context() utility function for AI Agents & Assistants

-
-
var sayAsyncSay
-
-

say() utility function, which calls chat.postMessage API with the associated channel ID

-
-
var say_streamAsyncSayStream | None
-
-

say_stream() utility function for AI Agents & Assistants

-
-
var set_statusAsyncSetStatus | None
-
-

set_status() utility function for AI Agents & Assistants

-
-
var set_suggested_promptsAsyncSetSuggestedPrompts | None
-
-

set_suggested_prompts() utility function for AI Agents & Assistants

-
-
var set_titleAsyncSetTitle | None
-
-

set_title() utility function for AI Agents & Assistants

-
-
var shortcut : Dict[str, Any] | None
-
-

An alias for payload in an @app.shortcut listener

-
-
var view : Dict[str, Any] | None
-
-

An alias for payload in an @app.view listener

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/kwargs_injection/async_utils.html b/docs/reference/kwargs_injection/async_utils.html deleted file mode 100644 index 7af3a7679..000000000 --- a/docs/reference/kwargs_injection/async_utils.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - -slack_bolt.kwargs_injection.async_utils API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.kwargs_injection.async_utils

-
-
-
-
-
-
-
-
-

Functions

-
-
-def build_async_required_kwargs(*,
logger: logging.Logger,
required_arg_names: MutableSequence[str],
request: AsyncBoltRequest,
response: BoltResponse | None,
next_func: Callable[[], None] | None = None,
this_func: Callable | None = None,
error: Exception | None = None,
next_keys_required: bool = True) ‑> Dict[str, Any]
-
-
-
- -Expand source code - -
def build_async_required_kwargs(
-    *,
-    logger: logging.Logger,
-    required_arg_names: MutableSequence[str],
-    request: AsyncBoltRequest,
-    response: Optional[BoltResponse],
-    next_func: Optional[Callable[[], None]] = None,
-    this_func: Optional[Callable] = None,
-    error: Optional[Exception] = None,  # for error handlers
-    next_keys_required: bool = True,  # False for listeners / middleware / error handlers
-) -> Dict[str, Any]:
-    all_available_args: Dict[str, Any] = {
-        "logger": logger,
-        "client": request.context.client,
-        "req": request,
-        "request": request,
-        "resp": response,
-        "response": response,
-        "context": request.context,
-        "body": request.body,
-        # payload
-        "options": to_options(request.body),
-        "shortcut": to_shortcut(request.body),
-        "action": to_action(request.body),
-        "view": to_view(request.body),
-        "command": to_command(request.body),
-        "event": to_event(request.body),
-        "message": to_message(request.body),
-        "step": to_step(request.body),
-        # utilities
-        "ack": request.context.ack,
-        "say": request.context.say,
-        "respond": request.context.respond,
-        "complete": request.context.complete,
-        "fail": request.context.fail,
-        "set_status": request.context.set_status,
-        "set_title": request.context.set_title,
-        "set_suggested_prompts": request.context.set_suggested_prompts,
-        "get_thread_context": request.context.get_thread_context,
-        "save_thread_context": request.context.save_thread_context,
-        "say_stream": request.context.say_stream,
-        # middleware
-        "next": next_func,
-        "next_": next_func,  # for the middleware using Python's built-in `next()` function
-        # error handler
-        "error": error,  # Exception
-    }
-    if not next_keys_required:
-        all_available_args.pop("next")
-        all_available_args.pop("next_")
-
-    all_available_args["payload"] = (
-        all_available_args["options"]
-        or all_available_args["shortcut"]
-        or all_available_args["action"]
-        or all_available_args["view"]
-        or all_available_args["command"]
-        or all_available_args["event"]
-        or all_available_args["message"]
-        or all_available_args["step"]
-        or request.body
-    )
-    for k, v in request.context.items():
-        if k not in all_available_args:
-            all_available_args[k] = v
-
-    if len(required_arg_names) > 0:
-        # To support instance/class methods in a class for listeners/middleware,
-        # check if the first argument is either self or cls
-        first_arg_name = required_arg_names[0]
-        if first_arg_name in {"self", "cls"}:
-            required_arg_names.pop(0)
-        elif first_arg_name not in all_available_args.keys() and first_arg_name != "args":
-            if this_func is None:
-                logger.warning(warning_skip_uncommon_arg_name(first_arg_name))
-                required_arg_names.pop(0)
-            elif inspect.ismethod(this_func):
-                # We are sure that we should skip manipulating this arg
-                required_arg_names.pop(0)
-
-    kwargs: Dict[str, Any] = {k: v for k, v in all_available_args.items() if k in required_arg_names}
-    found_arg_names = kwargs.keys()
-    for name in required_arg_names:
-        if name == "args":
-            if isinstance(request, AsyncBoltRequest):
-                kwargs[name] = AsyncArgs(**all_available_args)
-            else:
-                logger.warning(f"Unknown Request object type detected ({type(request)})")
-
-        elif name not in found_arg_names:
-            logger.warning(f"{name} is not a valid argument")
-            kwargs[name] = None
-    return kwargs
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/kwargs_injection/index.html b/docs/reference/kwargs_injection/index.html deleted file mode 100644 index cb17cea5d..000000000 --- a/docs/reference/kwargs_injection/index.html +++ /dev/null @@ -1,560 +0,0 @@ - - - - - - -slack_bolt.kwargs_injection API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.kwargs_injection

-
-
-

For middleware/listener arguments, Bolt does flexible data injection in accordance with their names.

-

To learn the available arguments, check slack_bolt.kwargs_injection.args's API document. -For steps from apps, checking slack_bolt.workflows.step.utilities as well should be helpful.

-
-
-

Sub-modules

-
-
slack_bolt.kwargs_injection.args
-
-
-
-
slack_bolt.kwargs_injection.async_args
-
-
-
-
slack_bolt.kwargs_injection.async_utils
-
-
-
-
slack_bolt.kwargs_injection.utils
-
-
-
-
-
-
-
-
-

Functions

-
-
-def build_required_kwargs(*,
logger: logging.Logger,
required_arg_names: MutableSequence[str],
request: BoltRequest,
response: BoltResponse | None,
next_func: Callable[[], None] | None = None,
this_func: Callable | None = None,
error: Exception | None = None,
next_keys_required: bool = True) ‑> Dict[str, Any]
-
-
-
- -Expand source code - -
def build_required_kwargs(
-    *,
-    logger: logging.Logger,
-    required_arg_names: MutableSequence[str],
-    request: BoltRequest,
-    response: Optional[BoltResponse],
-    next_func: Optional[Callable[[], None]] = None,
-    this_func: Optional[Callable] = None,
-    error: Optional[Exception] = None,  # for error handlers
-    next_keys_required: bool = True,  # False for listeners / middleware / error handlers
-) -> Dict[str, Any]:
-    all_available_args: Dict[str, Any] = {
-        "logger": logger,
-        "client": request.context.client,
-        "req": request,
-        "request": request,
-        "resp": response,
-        "response": response,
-        "context": request.context,
-        # payload
-        "body": request.body,
-        "options": to_options(request.body),
-        "shortcut": to_shortcut(request.body),
-        "action": to_action(request.body),
-        "view": to_view(request.body),
-        "command": to_command(request.body),
-        "event": to_event(request.body),
-        "message": to_message(request.body),
-        "step": to_step(request.body),
-        # utilities
-        "ack": request.context.ack,
-        "say": request.context.say,
-        "respond": request.context.respond,
-        "complete": request.context.complete,
-        "fail": request.context.fail,
-        "set_status": request.context.set_status,
-        "set_title": request.context.set_title,
-        "set_suggested_prompts": request.context.set_suggested_prompts,
-        "save_thread_context": request.context.save_thread_context,
-        "say_stream": request.context.say_stream,
-        # middleware
-        "next": next_func,
-        "next_": next_func,  # for the middleware using Python's built-in `next()` function
-        # error handler
-        "error": error,  # Exception
-    }
-    if not next_keys_required:
-        all_available_args.pop("next")
-        all_available_args.pop("next_")
-
-    all_available_args["payload"] = (
-        all_available_args["options"]
-        or all_available_args["shortcut"]
-        or all_available_args["action"]
-        or all_available_args["view"]
-        or all_available_args["command"]
-        or all_available_args["event"]
-        or all_available_args["message"]
-        or all_available_args["step"]
-        or request.body
-    )
-    for k, v in request.context.items():
-        if k not in all_available_args:
-            all_available_args[k] = v
-
-    if len(required_arg_names) > 0:
-        # To support instance/class methods in a class for listeners/middleware,
-        # check if the first argument is either self or cls
-        first_arg_name = required_arg_names[0]
-        if first_arg_name in {"self", "cls"}:
-            required_arg_names.pop(0)
-        elif first_arg_name not in all_available_args.keys() and first_arg_name != "args":
-            if this_func is None:
-                logger.warning(warning_skip_uncommon_arg_name(first_arg_name))
-                required_arg_names.pop(0)
-            elif inspect.ismethod(this_func):
-                # We are sure that we should skip manipulating this arg
-                required_arg_names.pop(0)
-
-    kwargs: Dict[str, Any] = {k: v for k, v in all_available_args.items() if k in required_arg_names}
-    found_arg_names = kwargs.keys()
-    for name in required_arg_names:
-        if name == "args":
-            if isinstance(request, BoltRequest):
-                kwargs[name] = Args(**all_available_args)
-            else:
-                logger.warning(f"Unknown Request object type detected ({type(request)})")
-
-        elif name not in found_arg_names:
-            logger.warning(f"{name} is not a valid argument")
-            kwargs[name] = None
-    return kwargs
-
-
-
-
-
-
-

Classes

-
-
-class Args -(*,
logger: logging.Logger,
client: slack_sdk.web.client.WebClient,
req: BoltRequest,
resp: BoltResponse,
context: BoltContext,
body: Dict[str, Any],
payload: Dict[str, Any],
options: Dict[str, Any] | None = None,
shortcut: Dict[str, Any] | None = None,
action: Dict[str, Any] | None = None,
view: Dict[str, Any] | None = None,
command: Dict[str, Any] | None = None,
event: Dict[str, Any] | None = None,
message: Dict[str, Any] | None = None,
ack: Ack,
say: Say,
respond: Respond,
complete: Complete,
fail: Fail,
set_status: SetStatus | None = None,
set_title: SetTitle | None = None,
set_suggested_prompts: SetSuggestedPrompts | None = None,
get_thread_context: GetThreadContext | None = None,
save_thread_context: SaveThreadContext | None = None,
say_stream: SayStream | None = None,
next: Callable[[], None],
**kwargs)
-
-
-
- -Expand source code - -
class Args:
-    """All the arguments in this class are available in any middleware / listeners.
-    You can inject the named variables in the argument list in arbitrary order.
-
-        @app.action("link_button")
-        def handle_buttons(ack, respond, logger, context, body, client):
-            logger.info(f"request body: {body}")
-            ack()
-            if context.channel_id is not None:
-                respond("Hi!")
-            client.views_open(
-                trigger_id=body["trigger_id"],
-                view={ ... }
-            )
-
-    Alternatively, you can include a parameter named `args` and it will be injected with an instance of this class.
-
-        @app.action("link_button")
-        def handle_buttons(args):
-            args.logger.info(f"request body: {args.body}")
-            args.ack()
-            if args.context.channel_id is not None:
-                args.respond("Hi!")
-            args.client.views_open(
-                trigger_id=args.body["trigger_id"],
-                view={ ... }
-            )
-
-    """
-
-    client: WebClient
-    """`slack_sdk.web.WebClient` instance with a valid token"""
-    logger: Logger
-    """Logger instance"""
-    req: BoltRequest
-    """Incoming request from Slack"""
-    resp: BoltResponse
-    """Response representation"""
-    request: BoltRequest
-    """Incoming request from Slack"""
-    response: BoltResponse
-    """Response representation"""
-    context: BoltContext
-    """Context data associated with the incoming request"""
-    body: Dict[str, Any]
-    """Parsed request body data"""
-    # payload
-    payload: Dict[str, Any]
-    """The unwrapped core data in the request body"""
-    options: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.options` listener"""
-    shortcut: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.shortcut` listener"""
-    action: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.action` listener"""
-    view: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.view` listener"""
-    command: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.command` listener"""
-    event: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.event` listener"""
-    message: Optional[Dict[str, Any]]  # payload alias
-    """An alias for payload in an `@app.message` listener"""
-    # utilities
-    ack: Ack
-    """`ack()` utility function, which returns acknowledgement to the Slack servers"""
-    say: Say
-    """`say()` utility function, which calls `chat.postMessage` API with the associated channel ID"""
-    respond: Respond
-    """`respond()` utility function, which utilizes the associated `response_url`"""
-    complete: Complete
-    """`complete()` utility function, signals a successful completion of the custom function"""
-    fail: Fail
-    """`fail()` utility function, signal that the custom function failed to complete"""
-    set_status: Optional[SetStatus]
-    """`set_status()` utility function for AI Agents & Assistants"""
-    set_title: Optional[SetTitle]
-    """`set_title()` utility function for AI Agents & Assistants"""
-    set_suggested_prompts: Optional[SetSuggestedPrompts]
-    """`set_suggested_prompts()` utility function for AI Agents & Assistants"""
-    get_thread_context: Optional[GetThreadContext]
-    """`get_thread_context()` utility function for AI Agents & Assistants"""
-    save_thread_context: Optional[SaveThreadContext]
-    """`save_thread_context()` utility function for AI Agents & Assistants"""
-    say_stream: Optional[SayStream]
-    """`say_stream()` utility function for conversations, AI Agents & Assistants"""
-    # middleware
-    next: Callable[[], None]
-    """`next()` utility function, which tells the middleware chain that it can continue with the next one"""
-    next_: Callable[[], None]
-    """An alias of `next()` for avoiding the Python built-in method overrides in middleware functions"""
-
-    def __init__(
-        self,
-        *,
-        logger: logging.Logger,
-        client: WebClient,
-        req: BoltRequest,
-        resp: BoltResponse,
-        context: BoltContext,
-        body: Dict[str, Any],
-        payload: Dict[str, Any],
-        options: Optional[Dict[str, Any]] = None,
-        shortcut: Optional[Dict[str, Any]] = None,
-        action: Optional[Dict[str, Any]] = None,
-        view: Optional[Dict[str, Any]] = None,
-        command: Optional[Dict[str, Any]] = None,
-        event: Optional[Dict[str, Any]] = None,
-        message: Optional[Dict[str, Any]] = None,
-        ack: Ack,
-        say: Say,
-        respond: Respond,
-        complete: Complete,
-        fail: Fail,
-        set_status: Optional[SetStatus] = None,
-        set_title: Optional[SetTitle] = None,
-        set_suggested_prompts: Optional[SetSuggestedPrompts] = None,
-        get_thread_context: Optional[GetThreadContext] = None,
-        save_thread_context: Optional[SaveThreadContext] = None,
-        say_stream: Optional[SayStream] = None,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], None],
-        **kwargs,  # noqa
-    ):
-        self.logger: logging.Logger = logger
-        self.client: WebClient = client
-        self.request = self.req = req
-        self.response = self.resp = resp
-        self.context: BoltContext = context
-
-        self.body: Dict[str, Any] = body
-        self.payload: Dict[str, Any] = payload
-        self.options: Optional[Dict[str, Any]] = options
-        self.shortcut: Optional[Dict[str, Any]] = shortcut
-        self.action: Optional[Dict[str, Any]] = action
-        self.view: Optional[Dict[str, Any]] = view
-        self.command: Optional[Dict[str, Any]] = command
-        self.event: Optional[Dict[str, Any]] = event
-        self.message: Optional[Dict[str, Any]] = message
-
-        self.ack: Ack = ack
-        self.say: Say = say
-        self.respond: Respond = respond
-        self.complete: Complete = complete
-        self.fail: Fail = fail
-
-        self.set_status = set_status
-        self.set_title = set_title
-        self.set_suggested_prompts = set_suggested_prompts
-        self.get_thread_context = get_thread_context
-        self.save_thread_context = save_thread_context
-        self.say_stream = say_stream
-
-        self.next: Callable[[], None] = next
-        self.next_: Callable[[], None] = next
-
-

All the arguments in this class are available in any middleware / listeners. -You can inject the named variables in the argument list in arbitrary order.

-
@app.action("link_button")
-def handle_buttons(ack, respond, logger, context, body, client):
-    logger.info(f"request body: {body}")
-    ack()
-    if context.channel_id is not None:
-        respond("Hi!")
-    client.views_open(
-        trigger_id=body["trigger_id"],
-        view={ ... }
-    )
-
-

Alternatively, you can include a parameter named slack_bolt.kwargs_injection.args and it will be injected with an instance of this class.

-
@app.action("link_button")
-def handle_buttons(args):
-    args.logger.info(f"request body: {args.body}")
-    args.ack()
-    if args.context.channel_id is not None:
-        args.respond("Hi!")
-    args.client.views_open(
-        trigger_id=args.body["trigger_id"],
-        view={ ... }
-    )
-
-

Class variables

-
-
var ackAck
-
-

ack() utility function, which returns acknowledgement to the Slack servers

-
-
var action : Dict[str, Any] | None
-
-

An alias for payload in an @app.action listener

-
-
var body : Dict[str, Any]
-
-

Parsed request body data

-
-
var client : slack_sdk.web.client.WebClient
-
-

slack_sdk.web.WebClient instance with a valid token

-
-
var command : Dict[str, Any] | None
-
-

An alias for payload in an @app.command listener

-
-
var completeComplete
-
-

complete() utility function, signals a successful completion of the custom function

-
-
var contextBoltContext
-
-

Context data associated with the incoming request

-
-
var event : Dict[str, Any] | None
-
-

An alias for payload in an @app.event listener

-
-
var failFail
-
-

fail() utility function, signal that the custom function failed to complete

-
-
var get_thread_contextGetThreadContext | None
-
-

get_thread_context() utility function for AI Agents & Assistants

-
-
var logger : logging.Logger
-
-

Logger instance

-
-
var message : Dict[str, Any] | None
-
-

An alias for payload in an @app.message listener

-
-
var next : Callable[[], None]
-
-

next() utility function, which tells the middleware chain that it can continue with the next one

-
-
var next_ : Callable[[], None]
-
-

An alias of next() for avoiding the Python built-in method overrides in middleware functions

-
-
var options : Dict[str, Any] | None
-
-

An alias for payload in an @app.options listener

-
-
var payload : Dict[str, Any]
-
-

The unwrapped core data in the request body

-
-
var reqBoltRequest
-
-

Incoming request from Slack

-
-
var requestBoltRequest
-
-

Incoming request from Slack

-
-
var respBoltResponse
-
-

Response representation

-
-
var respondRespond
-
-

respond() utility function, which utilizes the associated response_url

-
-
var responseBoltResponse
-
-

Response representation

-
-
var save_thread_contextSaveThreadContext | None
-
-

save_thread_context() utility function for AI Agents & Assistants

-
-
var saySay
-
-

say() utility function, which calls chat.postMessage API with the associated channel ID

-
-
var say_streamSayStream | None
-
-

say_stream() utility function for conversations, AI Agents & Assistants

-
-
var set_statusSetStatus | None
-
-

set_status() utility function for AI Agents & Assistants

-
-
var set_suggested_promptsSetSuggestedPrompts | None
-
-

set_suggested_prompts() utility function for AI Agents & Assistants

-
-
var set_titleSetTitle | None
-
-

set_title() utility function for AI Agents & Assistants

-
-
var shortcut : Dict[str, Any] | None
-
-

An alias for payload in an @app.shortcut listener

-
-
var view : Dict[str, Any] | None
-
-

An alias for payload in an @app.view listener

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/kwargs_injection/utils.html b/docs/reference/kwargs_injection/utils.html deleted file mode 100644 index 0289fd410..000000000 --- a/docs/reference/kwargs_injection/utils.html +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - -slack_bolt.kwargs_injection.utils API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.kwargs_injection.utils

-
-
-
-
-
-
-
-
-

Functions

-
-
-def build_required_kwargs(*,
logger: logging.Logger,
required_arg_names: MutableSequence[str],
request: BoltRequest,
response: BoltResponse | None,
next_func: Callable[[], None] | None = None,
this_func: Callable | None = None,
error: Exception | None = None,
next_keys_required: bool = True) ‑> Dict[str, Any]
-
-
-
- -Expand source code - -
def build_required_kwargs(
-    *,
-    logger: logging.Logger,
-    required_arg_names: MutableSequence[str],
-    request: BoltRequest,
-    response: Optional[BoltResponse],
-    next_func: Optional[Callable[[], None]] = None,
-    this_func: Optional[Callable] = None,
-    error: Optional[Exception] = None,  # for error handlers
-    next_keys_required: bool = True,  # False for listeners / middleware / error handlers
-) -> Dict[str, Any]:
-    all_available_args: Dict[str, Any] = {
-        "logger": logger,
-        "client": request.context.client,
-        "req": request,
-        "request": request,
-        "resp": response,
-        "response": response,
-        "context": request.context,
-        # payload
-        "body": request.body,
-        "options": to_options(request.body),
-        "shortcut": to_shortcut(request.body),
-        "action": to_action(request.body),
-        "view": to_view(request.body),
-        "command": to_command(request.body),
-        "event": to_event(request.body),
-        "message": to_message(request.body),
-        "step": to_step(request.body),
-        # utilities
-        "ack": request.context.ack,
-        "say": request.context.say,
-        "respond": request.context.respond,
-        "complete": request.context.complete,
-        "fail": request.context.fail,
-        "set_status": request.context.set_status,
-        "set_title": request.context.set_title,
-        "set_suggested_prompts": request.context.set_suggested_prompts,
-        "save_thread_context": request.context.save_thread_context,
-        "say_stream": request.context.say_stream,
-        # middleware
-        "next": next_func,
-        "next_": next_func,  # for the middleware using Python's built-in `next()` function
-        # error handler
-        "error": error,  # Exception
-    }
-    if not next_keys_required:
-        all_available_args.pop("next")
-        all_available_args.pop("next_")
-
-    all_available_args["payload"] = (
-        all_available_args["options"]
-        or all_available_args["shortcut"]
-        or all_available_args["action"]
-        or all_available_args["view"]
-        or all_available_args["command"]
-        or all_available_args["event"]
-        or all_available_args["message"]
-        or all_available_args["step"]
-        or request.body
-    )
-    for k, v in request.context.items():
-        if k not in all_available_args:
-            all_available_args[k] = v
-
-    if len(required_arg_names) > 0:
-        # To support instance/class methods in a class for listeners/middleware,
-        # check if the first argument is either self or cls
-        first_arg_name = required_arg_names[0]
-        if first_arg_name in {"self", "cls"}:
-            required_arg_names.pop(0)
-        elif first_arg_name not in all_available_args.keys() and first_arg_name != "args":
-            if this_func is None:
-                logger.warning(warning_skip_uncommon_arg_name(first_arg_name))
-                required_arg_names.pop(0)
-            elif inspect.ismethod(this_func):
-                # We are sure that we should skip manipulating this arg
-                required_arg_names.pop(0)
-
-    kwargs: Dict[str, Any] = {k: v for k, v in all_available_args.items() if k in required_arg_names}
-    found_arg_names = kwargs.keys()
-    for name in required_arg_names:
-        if name == "args":
-            if isinstance(request, BoltRequest):
-                kwargs[name] = Args(**all_available_args)
-            else:
-                logger.warning(f"Unknown Request object type detected ({type(request)})")
-
-        elif name not in found_arg_names:
-            logger.warning(f"{name} is not a valid argument")
-            kwargs[name] = None
-    return kwargs
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/lazy_listener/async_internals.html b/docs/reference/lazy_listener/async_internals.html deleted file mode 100644 index 9d86a02e5..000000000 --- a/docs/reference/lazy_listener/async_internals.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - -slack_bolt.lazy_listener.async_internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.lazy_listener.async_internals

-
-
-
-
-
-
-
-
-

Functions

-
-
-async def to_runnable_function(internal_func: Callable[..., Awaitable[None]],
logger: logging.Logger,
request: AsyncBoltRequest)
-
-
-
- -Expand source code - -
async def to_runnable_function(
-    internal_func: Callable[..., Awaitable[None]],
-    logger: Logger,
-    request: AsyncBoltRequest,
-):
-    arg_names = get_arg_names_of_callable(internal_func)
-
-    @wraps(internal_func)
-    async def request_wired_wrapper() -> None:
-        try:
-            await internal_func(
-                **build_async_required_kwargs(
-                    logger=logger,
-                    required_arg_names=arg_names,
-                    request=request,
-                    response=None,
-                    this_func=internal_func,
-                )
-            )
-        except Exception as e:
-            logger.error(f"Failed to run an internal function ({e})")
-
-    return await request_wired_wrapper()
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/lazy_listener/async_runner.html b/docs/reference/lazy_listener/async_runner.html deleted file mode 100644 index 701f1640a..000000000 --- a/docs/reference/lazy_listener/async_runner.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - -slack_bolt.lazy_listener.async_runner API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.lazy_listener.async_runner

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncLazyListenerRunner -
-
-
- -Expand source code - -
class AsyncLazyListenerRunner(metaclass=ABCMeta):
-    logger: Logger
-
-    @abstractmethod
-    def start(self, function: Callable[..., Awaitable[None]], request: AsyncBoltRequest) -> None:
-        """Starts a new lazy listener execution.
-
-        Args:
-            function: The function to run.
-            request: The request to pass to the function. The object must be thread-safe.
-        """
-        raise NotImplementedError()
-
-    async def run(self, function: Callable[..., Awaitable[None]], request: AsyncBoltRequest) -> None:
-        """Synchronously run the function with a given request data.
-
-        Args:
-            function: The function to run.
-            request: The request to pass to the function. The object must be thread-safe.
-        """
-        func = to_runnable_function(
-            internal_func=function,
-            logger=self.logger,
-            request=request,
-        )
-        return await func()  # type: ignore[operator]
-
-
-

Subclasses

- -

Class variables

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-async def run(self,
function: Callable[..., Awaitable[None]],
request: AsyncBoltRequest) ‑> None
-
-
-
- -Expand source code - -
async def run(self, function: Callable[..., Awaitable[None]], request: AsyncBoltRequest) -> None:
-    """Synchronously run the function with a given request data.
-
-    Args:
-        function: The function to run.
-        request: The request to pass to the function. The object must be thread-safe.
-    """
-    func = to_runnable_function(
-        internal_func=function,
-        logger=self.logger,
-        request=request,
-    )
-    return await func()  # type: ignore[operator]
-
-

Synchronously run the function with a given request data.

-

Args

-
-
function
-
The function to run.
-
request
-
The request to pass to the function. The object must be thread-safe.
-
-
-
-def start(self,
function: Callable[..., Awaitable[None]],
request: AsyncBoltRequest) ‑> None
-
-
-
- -Expand source code - -
@abstractmethod
-def start(self, function: Callable[..., Awaitable[None]], request: AsyncBoltRequest) -> None:
-    """Starts a new lazy listener execution.
-
-    Args:
-        function: The function to run.
-        request: The request to pass to the function. The object must be thread-safe.
-    """
-    raise NotImplementedError()
-
-

Starts a new lazy listener execution.

-

Args

-
-
function
-
The function to run.
-
request
-
The request to pass to the function. The object must be thread-safe.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/lazy_listener/asyncio_runner.html b/docs/reference/lazy_listener/asyncio_runner.html deleted file mode 100644 index 2fdcf8ffe..000000000 --- a/docs/reference/lazy_listener/asyncio_runner.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - -slack_bolt.lazy_listener.asyncio_runner API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.lazy_listener.asyncio_runner

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncioLazyListenerRunner -(logger: logging.Logger) -
-
-
- -Expand source code - -
class AsyncioLazyListenerRunner(AsyncLazyListenerRunner):
-    logger: Logger
-
-    def __init__(
-        self,
-        logger: Logger,
-    ):
-        self.logger = logger
-
-    def start(self, function: Callable[..., Awaitable[None]], request: AsyncBoltRequest) -> None:
-        asyncio.ensure_future(
-            to_runnable_function(
-                internal_func=function,
-                logger=self.logger,
-                request=request,
-            )
-        )
-
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/lazy_listener/index.html b/docs/reference/lazy_listener/index.html deleted file mode 100644 index 6bc17015e..000000000 --- a/docs/reference/lazy_listener/index.html +++ /dev/null @@ -1,301 +0,0 @@ - - - - - - -slack_bolt.lazy_listener API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.lazy_listener

-
-
-

Lazy listener runner is a beta feature for the apps running on Function-as-a-Service platforms.

-
def respond_to_slack_within_3_seconds(body, ack):
-    text = body.get("text")
-    if text is None or len(text) == 0:
-        ack(f":x: Usage: /start-process (description here)")
-    else:
-        ack(f"Accepted! (task: {body['text']})")
-
-import time
-def run_long_process(respond, body):
-    time.sleep(5)  # longer than 3 seconds
-    respond(f"Completed! (task: {body['text']})")
-
-app.command("/start-process")(
-    # ack() is still called within 3 seconds
-    ack=respond_to_slack_within_3_seconds,
-    # Lazy function is responsible for processing the event
-    lazy=[run_long_process]
-)
-
-

Refer to https://docs.slack.dev/tools/bolt-python/concepts/lazy-listeners for more details.

-
-
-

Sub-modules

-
-
slack_bolt.lazy_listener.async_internals
-
-
-
-
slack_bolt.lazy_listener.async_runner
-
-
-
-
slack_bolt.lazy_listener.asyncio_runner
-
-
-
-
slack_bolt.lazy_listener.internals
-
-
-
-
slack_bolt.lazy_listener.runner
-
-
-
-
slack_bolt.lazy_listener.thread_runner
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class LazyListenerRunner -
-
-
- -Expand source code - -
class LazyListenerRunner(metaclass=ABCMeta):
-    logger: Logger
-
-    @abstractmethod
-    def start(self, function: Callable[..., None], request: BoltRequest) -> None:
-        """Starts a new lazy listener execution.
-
-        Args:
-            function: The function to run.
-            request: The request to pass to the function. The object must be thread-safe.
-        """
-        raise NotImplementedError()
-
-    def run(self, function: Callable[..., None], request: BoltRequest) -> None:
-        """Synchronously runs the function with a given request data.
-
-        Args:
-            function: The function to run.
-            request: The request to pass to the function. The object must be thread-safe.
-        """
-        build_runnable_function(
-            func=function,
-            logger=self.logger,
-            request=request,
-        )()
-
-
-

Subclasses

- -

Class variables

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def run(self,
function: Callable[..., None],
request: BoltRequest) ‑> None
-
-
-
- -Expand source code - -
def run(self, function: Callable[..., None], request: BoltRequest) -> None:
-    """Synchronously runs the function with a given request data.
-
-    Args:
-        function: The function to run.
-        request: The request to pass to the function. The object must be thread-safe.
-    """
-    build_runnable_function(
-        func=function,
-        logger=self.logger,
-        request=request,
-    )()
-
-

Synchronously runs the function with a given request data.

-

Args

-
-
function
-
The function to run.
-
request
-
The request to pass to the function. The object must be thread-safe.
-
-
-
-def start(self,
function: Callable[..., None],
request: BoltRequest) ‑> None
-
-
-
- -Expand source code - -
@abstractmethod
-def start(self, function: Callable[..., None], request: BoltRequest) -> None:
-    """Starts a new lazy listener execution.
-
-    Args:
-        function: The function to run.
-        request: The request to pass to the function. The object must be thread-safe.
-    """
-    raise NotImplementedError()
-
-

Starts a new lazy listener execution.

-

Args

-
-
function
-
The function to run.
-
request
-
The request to pass to the function. The object must be thread-safe.
-
-
-
-
-
-class ThreadLazyListenerRunner -(logger: logging.Logger, executor: concurrent.futures._base.Executor) -
-
-
- -Expand source code - -
class ThreadLazyListenerRunner(LazyListenerRunner):
-    logger: Logger
-
-    def __init__(
-        self,
-        logger: Logger,
-        executor: Executor,
-    ):
-        self.logger = logger
-        self.executor = executor
-
-    def start(self, function: Callable[..., None], request: BoltRequest) -> None:
-        self.executor.submit(
-            build_runnable_function(
-                func=function,
-                logger=self.logger,
-                request=request,
-            )
-        )
-
-
-

Ancestors

- -

Subclasses

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/lazy_listener/internals.html b/docs/reference/lazy_listener/internals.html deleted file mode 100644 index 1801abafd..000000000 --- a/docs/reference/lazy_listener/internals.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - -slack_bolt.lazy_listener.internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.lazy_listener.internals

-
-
-
-
-
-
-
-
-

Functions

-
-
-def build_runnable_function(func: Callable[..., None],
logger: logging.Logger,
request: BoltRequest) ‑> Callable[[], None]
-
-
-
- -Expand source code - -
def build_runnable_function(
-    func: Callable[..., None],
-    logger: Logger,
-    request: BoltRequest,
-) -> Callable[[], None]:
-    arg_names = get_arg_names_of_callable(func)
-
-    @wraps(func)
-    def request_wired_func_wrapper() -> None:
-        try:
-            func(
-                **build_required_kwargs(
-                    logger=logger,
-                    required_arg_names=arg_names,
-                    request=request,
-                    response=None,
-                    this_func=func,
-                )
-            )
-        except Exception as e:
-            logger.error(f"Failed to run an internal function ({e})")
-
-    return request_wired_func_wrapper
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/lazy_listener/runner.html b/docs/reference/lazy_listener/runner.html deleted file mode 100644 index ff4f449a0..000000000 --- a/docs/reference/lazy_listener/runner.html +++ /dev/null @@ -1,191 +0,0 @@ - - - - - - -slack_bolt.lazy_listener.runner API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.lazy_listener.runner

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class LazyListenerRunner -
-
-
- -Expand source code - -
class LazyListenerRunner(metaclass=ABCMeta):
-    logger: Logger
-
-    @abstractmethod
-    def start(self, function: Callable[..., None], request: BoltRequest) -> None:
-        """Starts a new lazy listener execution.
-
-        Args:
-            function: The function to run.
-            request: The request to pass to the function. The object must be thread-safe.
-        """
-        raise NotImplementedError()
-
-    def run(self, function: Callable[..., None], request: BoltRequest) -> None:
-        """Synchronously runs the function with a given request data.
-
-        Args:
-            function: The function to run.
-            request: The request to pass to the function. The object must be thread-safe.
-        """
-        build_runnable_function(
-            func=function,
-            logger=self.logger,
-            request=request,
-        )()
-
-
-

Subclasses

- -

Class variables

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def run(self,
function: Callable[..., None],
request: BoltRequest) ‑> None
-
-
-
- -Expand source code - -
def run(self, function: Callable[..., None], request: BoltRequest) -> None:
-    """Synchronously runs the function with a given request data.
-
-    Args:
-        function: The function to run.
-        request: The request to pass to the function. The object must be thread-safe.
-    """
-    build_runnable_function(
-        func=function,
-        logger=self.logger,
-        request=request,
-    )()
-
-

Synchronously runs the function with a given request data.

-

Args

-
-
function
-
The function to run.
-
request
-
The request to pass to the function. The object must be thread-safe.
-
-
-
-def start(self,
function: Callable[..., None],
request: BoltRequest) ‑> None
-
-
-
- -Expand source code - -
@abstractmethod
-def start(self, function: Callable[..., None], request: BoltRequest) -> None:
-    """Starts a new lazy listener execution.
-
-    Args:
-        function: The function to run.
-        request: The request to pass to the function. The object must be thread-safe.
-    """
-    raise NotImplementedError()
-
-

Starts a new lazy listener execution.

-

Args

-
-
function
-
The function to run.
-
request
-
The request to pass to the function. The object must be thread-safe.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/lazy_listener/thread_runner.html b/docs/reference/lazy_listener/thread_runner.html deleted file mode 100644 index b4ca0711a..000000000 --- a/docs/reference/lazy_listener/thread_runner.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - -slack_bolt.lazy_listener.thread_runner API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.lazy_listener.thread_runner

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class ThreadLazyListenerRunner -(logger: logging.Logger, executor: concurrent.futures._base.Executor) -
-
-
- -Expand source code - -
class ThreadLazyListenerRunner(LazyListenerRunner):
-    logger: Logger
-
-    def __init__(
-        self,
-        logger: Logger,
-        executor: Executor,
-    ):
-        self.logger = logger
-        self.executor = executor
-
-    def start(self, function: Callable[..., None], request: BoltRequest) -> None:
-        self.executor.submit(
-            build_runnable_function(
-                func=function,
-                logger=self.logger,
-                request=request,
-            )
-        )
-
-
-

Ancestors

- -

Subclasses

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/listener/async_builtins.html b/docs/reference/listener/async_builtins.html deleted file mode 100644 index 015dd94b3..000000000 --- a/docs/reference/listener/async_builtins.html +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - -slack_bolt.listener.async_builtins API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.async_builtins

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncTokenRevocationListeners -(installation_store: slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore) -
-
-
- -Expand source code - -
class AsyncTokenRevocationListeners:
-    """Listener functions to handle token revocation / uninstallation events"""
-
-    installation_store: AsyncInstallationStore
-
-    def __init__(self, installation_store: AsyncInstallationStore):
-        self.installation_store = installation_store
-
-    async def handle_tokens_revoked_events(self, event: dict, context: AsyncBoltContext) -> None:
-        user_ids = event.get("tokens", {}).get("oauth", [])
-        if len(user_ids) > 0:
-            for user_id in user_ids:
-                await self.installation_store.async_delete_installation(
-                    enterprise_id=context.enterprise_id,
-                    team_id=context.team_id,
-                    user_id=user_id,
-                )
-        bots = event.get("tokens", {}).get("bot", [])
-        if len(bots) > 0:
-            await self.installation_store.async_delete_bot(
-                enterprise_id=context.enterprise_id,
-                team_id=context.team_id,
-            )
-
-    async def handle_app_uninstalled_events(self, context: AsyncBoltContext) -> None:
-        await self.installation_store.async_delete_all(
-            enterprise_id=context.enterprise_id,
-            team_id=context.team_id,
-        )
-
-

Listener functions to handle token revocation / uninstallation events

-

Class variables

-
-
var installation_store : slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-async def handle_app_uninstalled_events(self,
context: AsyncBoltContext) ‑> None
-
-
-
- -Expand source code - -
async def handle_app_uninstalled_events(self, context: AsyncBoltContext) -> None:
-    await self.installation_store.async_delete_all(
-        enterprise_id=context.enterprise_id,
-        team_id=context.team_id,
-    )
-
-
-
-
-async def handle_tokens_revoked_events(self,
event: dict,
context: AsyncBoltContext) ‑> None
-
-
-
- -Expand source code - -
async def handle_tokens_revoked_events(self, event: dict, context: AsyncBoltContext) -> None:
-    user_ids = event.get("tokens", {}).get("oauth", [])
-    if len(user_ids) > 0:
-        for user_id in user_ids:
-            await self.installation_store.async_delete_installation(
-                enterprise_id=context.enterprise_id,
-                team_id=context.team_id,
-                user_id=user_id,
-            )
-    bots = event.get("tokens", {}).get("bot", [])
-    if len(bots) > 0:
-        await self.installation_store.async_delete_bot(
-            enterprise_id=context.enterprise_id,
-            team_id=context.team_id,
-        )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener/async_listener.html b/docs/reference/listener/async_listener.html deleted file mode 100644 index a3d1a7fef..000000000 --- a/docs/reference/listener/async_listener.html +++ /dev/null @@ -1,551 +0,0 @@ - - - - - - -slack_bolt.listener.async_listener API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.async_listener

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncCustomListener -(*,
app_name: str,
ack_function: Callable[..., Awaitable[BoltResponse | None]],
lazy_functions: Sequence[Callable[..., Awaitable[None]]],
matchers: Sequence[AsyncListenerMatcher],
middleware: Sequence[AsyncMiddleware],
auto_acknowledgement: bool = False,
ack_timeout: int = 3,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncCustomListener(AsyncListener):
-    app_name: str
-    ack_function: Callable[..., Awaitable[Optional[BoltResponse]]]  # type: ignore[assignment]
-    lazy_functions: Sequence[Callable[..., Awaitable[None]]]
-    matchers: Sequence[AsyncListenerMatcher]
-    middleware: Sequence[AsyncMiddleware]
-    auto_acknowledgement: bool
-    ack_timeout: int
-    arg_names: MutableSequence[str]
-    logger: Logger
-
-    def __init__(
-        self,
-        *,
-        app_name: str,
-        ack_function: Callable[..., Awaitable[Optional[BoltResponse]]],
-        lazy_functions: Sequence[Callable[..., Awaitable[None]]],
-        matchers: Sequence[AsyncListenerMatcher],
-        middleware: Sequence[AsyncMiddleware],
-        auto_acknowledgement: bool = False,
-        ack_timeout: int = 3,
-        base_logger: Optional[Logger] = None,
-    ):
-        self.app_name = app_name
-        self.ack_function = ack_function
-        self.lazy_functions = lazy_functions
-        self.matchers = matchers
-        self.middleware = middleware
-        self.auto_acknowledgement = auto_acknowledgement
-        self.ack_timeout = ack_timeout
-        self.arg_names = get_arg_names_of_callable(ack_function)
-        self.logger = get_bolt_app_logger(app_name, self.ack_function, base_logger)
-
-    async def run_ack_function(
-        self,
-        *,
-        request: AsyncBoltRequest,
-        response: BoltResponse,
-    ) -> Optional[BoltResponse]:
-        return await self.ack_function(
-            **build_async_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,
-                request=request,
-                response=response,
-                this_func=self.ack_function,
-            )
-        )
-
-
-

Ancestors

- -

Class variables

-
-
var ack_function : Callable[..., Awaitable[BoltResponse | None]]
-
-

The type of the None singleton.

-
-
var ack_timeout : int
-
-

The type of the None singleton.

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : MutableSequence[str]
-
-

The type of the None singleton.

-
-
var auto_acknowledgement : bool
-
-

The type of the None singleton.

-
-
var lazy_functions : Sequence[Callable[..., Awaitable[None]]]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
var matchers : Sequence[AsyncListenerMatcher]
-
-

The type of the None singleton.

-
-
var middleware : Sequence[AsyncMiddleware]
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-async def run_ack_function(self,
*,
request: AsyncBoltRequest,
response: BoltResponse) ‑> BoltResponse | None
-
-
-
- -Expand source code - -
async def run_ack_function(
-    self,
-    *,
-    request: AsyncBoltRequest,
-    response: BoltResponse,
-) -> Optional[BoltResponse]:
-    return await self.ack_function(
-        **build_async_required_kwargs(
-            logger=self.logger,
-            required_arg_names=self.arg_names,
-            request=request,
-            response=response,
-            this_func=self.ack_function,
-        )
-    )
-
-

Runs all the registered middleware and then run the listener function.

-

Args

-
-
request
-
The incoming request
-
response
-
The current response
-
-

Returns

-

The processed response

-
-
-
-
-class cls -(*,
app_name: str,
ack_function: Callable[..., Awaitable[BoltResponse | None]],
lazy_functions: Sequence[Callable[..., Awaitable[None]]],
matchers: Sequence[AsyncListenerMatcher],
middleware: Sequence[AsyncMiddleware],
auto_acknowledgement: bool = False,
ack_timeout: int = 3,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncCustomListener(AsyncListener):
-    app_name: str
-    ack_function: Callable[..., Awaitable[Optional[BoltResponse]]]  # type: ignore[assignment]
-    lazy_functions: Sequence[Callable[..., Awaitable[None]]]
-    matchers: Sequence[AsyncListenerMatcher]
-    middleware: Sequence[AsyncMiddleware]
-    auto_acknowledgement: bool
-    ack_timeout: int
-    arg_names: MutableSequence[str]
-    logger: Logger
-
-    def __init__(
-        self,
-        *,
-        app_name: str,
-        ack_function: Callable[..., Awaitable[Optional[BoltResponse]]],
-        lazy_functions: Sequence[Callable[..., Awaitable[None]]],
-        matchers: Sequence[AsyncListenerMatcher],
-        middleware: Sequence[AsyncMiddleware],
-        auto_acknowledgement: bool = False,
-        ack_timeout: int = 3,
-        base_logger: Optional[Logger] = None,
-    ):
-        self.app_name = app_name
-        self.ack_function = ack_function
-        self.lazy_functions = lazy_functions
-        self.matchers = matchers
-        self.middleware = middleware
-        self.auto_acknowledgement = auto_acknowledgement
-        self.ack_timeout = ack_timeout
-        self.arg_names = get_arg_names_of_callable(ack_function)
-        self.logger = get_bolt_app_logger(app_name, self.ack_function, base_logger)
-
-    async def run_ack_function(
-        self,
-        *,
-        request: AsyncBoltRequest,
-        response: BoltResponse,
-    ) -> Optional[BoltResponse]:
-        return await self.ack_function(
-            **build_async_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,
-                request=request,
-                response=response,
-                this_func=self.ack_function,
-            )
-        )
-
-
-

Ancestors

- -

Class variables

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : MutableSequence[str]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class AsyncListener -
-
-
- -Expand source code - -
class AsyncListener(metaclass=ABCMeta):
-    matchers: Sequence[AsyncListenerMatcher]
-    middleware: Sequence[AsyncMiddleware]
-    ack_function: Callable[..., Awaitable[BoltResponse]]
-    lazy_functions: Sequence[Callable[..., Awaitable[None]]]
-    auto_acknowledgement: bool
-    ack_timeout: int
-
-    async def async_matches(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-    ) -> bool:
-        is_matched: bool = False
-        for matcher in self.matchers:
-            is_matched = await matcher.async_matches(req, resp)
-            if not is_matched:
-                return is_matched
-        return is_matched
-
-    async def run_async_middleware(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-    ) -> Tuple[Optional[BoltResponse], bool]:
-        """Runs an async middleware.
-
-        Args:
-            req: The incoming request
-            resp: The current response
-
-        Returns:
-            A tuple of the processed response and a flag indicating termination
-        """
-        for m in self.middleware:
-            middleware_state = {"next_called": False}
-
-            async def _next():
-                middleware_state["next_called"] = True
-
-            resp = await m.async_process(req=req, resp=resp, next=_next)  # type: ignore[assignment]
-            if not middleware_state["next_called"]:
-                # next() was not called in this middleware
-                return (resp, True)
-        return (resp, False)
-
-    @abstractmethod
-    async def run_ack_function(self, *, request: AsyncBoltRequest, response: BoltResponse) -> Optional[BoltResponse]:
-        """Runs all the registered middleware and then run the listener function.
-
-        Args:
-            request: The incoming request
-            response: The current response
-
-        Returns:
-            The processed response
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Class variables

-
-
var ack_function : Callable[..., Awaitable[BoltResponse]]
-
-

The type of the None singleton.

-
-
var ack_timeout : int
-
-

The type of the None singleton.

-
-
var auto_acknowledgement : bool
-
-

The type of the None singleton.

-
-
var lazy_functions : Sequence[Callable[..., Awaitable[None]]]
-
-

The type of the None singleton.

-
-
var matchers : Sequence[AsyncListenerMatcher]
-
-

The type of the None singleton.

-
-
var middleware : Sequence[AsyncMiddleware]
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-async def async_matches(self,
*,
req: AsyncBoltRequest,
resp: BoltResponse) ‑> bool
-
-
-
- -Expand source code - -
async def async_matches(
-    self,
-    *,
-    req: AsyncBoltRequest,
-    resp: BoltResponse,
-) -> bool:
-    is_matched: bool = False
-    for matcher in self.matchers:
-        is_matched = await matcher.async_matches(req, resp)
-        if not is_matched:
-            return is_matched
-    return is_matched
-
-
-
-
-async def run_ack_function(self,
*,
request: AsyncBoltRequest,
response: BoltResponse) ‑> BoltResponse | None
-
-
-
- -Expand source code - -
@abstractmethod
-async def run_ack_function(self, *, request: AsyncBoltRequest, response: BoltResponse) -> Optional[BoltResponse]:
-    """Runs all the registered middleware and then run the listener function.
-
-    Args:
-        request: The incoming request
-        response: The current response
-
-    Returns:
-        The processed response
-    """
-    raise NotImplementedError()
-
-

Runs all the registered middleware and then run the listener function.

-

Args

-
-
request
-
The incoming request
-
response
-
The current response
-
-

Returns

-

The processed response

-
-
-async def run_async_middleware(self,
*,
req: AsyncBoltRequest,
resp: BoltResponse) ‑> Tuple[BoltResponse | None, bool]
-
-
-
- -Expand source code - -
async def run_async_middleware(
-    self,
-    *,
-    req: AsyncBoltRequest,
-    resp: BoltResponse,
-) -> Tuple[Optional[BoltResponse], bool]:
-    """Runs an async middleware.
-
-    Args:
-        req: The incoming request
-        resp: The current response
-
-    Returns:
-        A tuple of the processed response and a flag indicating termination
-    """
-    for m in self.middleware:
-        middleware_state = {"next_called": False}
-
-        async def _next():
-            middleware_state["next_called"] = True
-
-        resp = await m.async_process(req=req, resp=resp, next=_next)  # type: ignore[assignment]
-        if not middleware_state["next_called"]:
-            # next() was not called in this middleware
-            return (resp, True)
-    return (resp, False)
-
-

Runs an async middleware.

-

Args

-
-
req
-
The incoming request
-
resp
-
The current response
-
-

Returns

-

A tuple of the processed response and a flag indicating termination

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener/async_listener_completion_handler.html b/docs/reference/listener/async_listener_completion_handler.html deleted file mode 100644 index 6cde66b93..000000000 --- a/docs/reference/listener/async_listener_completion_handler.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - -slack_bolt.listener.async_listener_completion_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.async_listener_completion_handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncCustomListenerCompletionHandler -(logger: logging.Logger, func: Callable[..., Awaitable[None]]) -
-
-
- -Expand source code - -
class AsyncCustomListenerCompletionHandler(AsyncListenerCompletionHandler):
-    def __init__(self, logger: Logger, func: Callable[..., Awaitable[None]]):
-        self.func = func
-        self.logger = logger
-        self.arg_names = get_arg_names_of_callable(func)
-
-    async def handle(
-        self,
-        request: AsyncBoltRequest,
-        response: Optional[BoltResponse],
-    ) -> None:
-        kwargs: Dict[str, Any] = build_async_required_kwargs(
-            required_arg_names=self.arg_names,
-            logger=self.logger,
-            request=request,
-            response=response,
-            next_keys_required=False,
-        )
-        await self.func(**kwargs)
-
-
-

Ancestors

- -

Inherited members

- -
-
-class AsyncDefaultListenerCompletionHandler -(logger: logging.Logger) -
-
-
- -Expand source code - -
class AsyncDefaultListenerCompletionHandler(AsyncListenerCompletionHandler):
-    def __init__(self, logger: Logger):
-        self.logger = logger
-
-    async def handle(
-        self,
-        request: AsyncBoltRequest,
-        response: Optional[BoltResponse],
-    ):
-        pass
-
-
-

Ancestors

- -

Inherited members

- -
-
-class AsyncListenerCompletionHandler -
-
-
- -Expand source code - -
class AsyncListenerCompletionHandler(metaclass=ABCMeta):
-    @abstractmethod
-    async def handle(
-        self,
-        request: AsyncBoltRequest,
-        response: Optional[BoltResponse],
-    ) -> None:
-        """Do something extra after the listener execution
-
-        Args:
-            request: The request.
-            response: The response.
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-async def handle(self,
request: AsyncBoltRequest,
response: BoltResponse | None) ‑> None
-
-
-
- -Expand source code - -
@abstractmethod
-async def handle(
-    self,
-    request: AsyncBoltRequest,
-    response: Optional[BoltResponse],
-) -> None:
-    """Do something extra after the listener execution
-
-    Args:
-        request: The request.
-        response: The response.
-    """
-    raise NotImplementedError()
-
-

Do something extra after the listener execution

-

Args

-
-
request
-
The request.
-
response
-
The response.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener/async_listener_error_handler.html b/docs/reference/listener/async_listener_error_handler.html deleted file mode 100644 index ebee4441a..000000000 --- a/docs/reference/listener/async_listener_error_handler.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - -slack_bolt.listener.async_listener_error_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.async_listener_error_handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncCustomListenerErrorHandler -(logger: logging.Logger,
func: Callable[..., Awaitable[BoltResponse | None]])
-
-
-
- -Expand source code - -
class AsyncCustomListenerErrorHandler(AsyncListenerErrorHandler):
-    def __init__(self, logger: Logger, func: Callable[..., Awaitable[Optional[BoltResponse]]]):
-        self.func = func
-        self.logger = logger
-        self.arg_names = get_arg_names_of_callable(func)
-
-    async def handle(
-        self,
-        error: Exception,
-        request: AsyncBoltRequest,
-        response: Optional[BoltResponse],
-    ) -> None:
-        kwargs: Dict[str, Any] = build_async_required_kwargs(
-            required_arg_names=self.arg_names,
-            logger=self.logger,
-            error=error,
-            request=request,
-            response=response,
-            next_keys_required=False,
-        )
-        returned_response = await self.func(**kwargs)
-        if returned_response is not None and isinstance(returned_response, BoltResponse):
-            assert response is not None, "response must be provided when returning a BoltResponse from an error handler"
-            response.status = returned_response.status
-            response.headers = returned_response.headers
-            response.body = returned_response.body
-
-
-

Ancestors

- -

Inherited members

- -
-
-class AsyncDefaultListenerErrorHandler -(logger: logging.Logger) -
-
-
- -Expand source code - -
class AsyncDefaultListenerErrorHandler(AsyncListenerErrorHandler):
-    def __init__(self, logger: Logger):
-        self.logger = logger
-
-    async def handle(
-        self,
-        error: Exception,
-        request: AsyncBoltRequest,
-        response: Optional[BoltResponse],
-    ):
-        message = f"Failed to run listener function (error: {error})"
-        self.logger.exception(message)
-
-
-

Ancestors

- -

Inherited members

- -
-
-class AsyncListenerErrorHandler -
-
-
- -Expand source code - -
class AsyncListenerErrorHandler(metaclass=ABCMeta):
-    @abstractmethod
-    async def handle(
-        self,
-        error: Exception,
-        request: AsyncBoltRequest,
-        response: Optional[BoltResponse],
-    ) -> None:
-        """Handles an unhandled exception.
-
-        Args:
-            error: The raised exception.
-            request: The request.
-            response: The response.
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-async def handle(self,
error: Exception,
request: AsyncBoltRequest,
response: BoltResponse | None) ‑> None
-
-
-
- -Expand source code - -
@abstractmethod
-async def handle(
-    self,
-    error: Exception,
-    request: AsyncBoltRequest,
-    response: Optional[BoltResponse],
-) -> None:
-    """Handles an unhandled exception.
-
-    Args:
-        error: The raised exception.
-        request: The request.
-        response: The response.
-    """
-    raise NotImplementedError()
-
-

Handles an unhandled exception.

-

Args

-
-
error
-
The raised exception.
-
request
-
The request.
-
response
-
The response.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener/async_listener_start_handler.html b/docs/reference/listener/async_listener_start_handler.html deleted file mode 100644 index 80b25eb29..000000000 --- a/docs/reference/listener/async_listener_start_handler.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - -slack_bolt.listener.async_listener_start_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.async_listener_start_handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncCustomListenerStartHandler -(logger: logging.Logger, func: Callable[..., Awaitable[None]]) -
-
-
- -Expand source code - -
class AsyncCustomListenerStartHandler(AsyncListenerStartHandler):
-    def __init__(self, logger: Logger, func: Callable[..., Awaitable[None]]):
-        self.func = func
-        self.logger = logger
-        self.arg_names = get_arg_names_of_callable(func)
-
-    async def handle(
-        self,
-        request: AsyncBoltRequest,
-        response: Optional[BoltResponse],
-    ) -> None:
-        kwargs: Dict[str, Any] = build_async_required_kwargs(
-            required_arg_names=self.arg_names,
-            logger=self.logger,
-            request=request,
-            response=response,
-            next_keys_required=False,
-        )
-        await self.func(**kwargs)
-
-
-

Ancestors

- -

Inherited members

- -
-
-class AsyncDefaultListenerStartHandler -(logger: logging.Logger) -
-
-
- -Expand source code - -
class AsyncDefaultListenerStartHandler(AsyncListenerStartHandler):
-    def __init__(self, logger: Logger):
-        self.logger = logger
-
-    async def handle(
-        self,
-        request: AsyncBoltRequest,
-        response: Optional[BoltResponse],
-    ):
-        pass
-
-
-

Ancestors

- -

Inherited members

- -
-
-class AsyncListenerStartHandler -
-
-
- -Expand source code - -
class AsyncListenerStartHandler(metaclass=ABCMeta):
-    @abstractmethod
-    async def handle(
-        self,
-        request: AsyncBoltRequest,
-        response: Optional[BoltResponse],
-    ) -> None:
-        """Do something extra before the listener execution
-
-        Args:
-            request: The request.
-            response: The response.
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-async def handle(self,
request: AsyncBoltRequest,
response: BoltResponse | None) ‑> None
-
-
-
- -Expand source code - -
@abstractmethod
-async def handle(
-    self,
-    request: AsyncBoltRequest,
-    response: Optional[BoltResponse],
-) -> None:
-    """Do something extra before the listener execution
-
-    Args:
-        request: The request.
-        response: The response.
-    """
-    raise NotImplementedError()
-
-

Do something extra before the listener execution

-

Args

-
-
request
-
The request.
-
response
-
The response.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener/asyncio_runner.html b/docs/reference/listener/asyncio_runner.html deleted file mode 100644 index 4d71a88a7..000000000 --- a/docs/reference/listener/asyncio_runner.html +++ /dev/null @@ -1,420 +0,0 @@ - - - - - - -slack_bolt.listener.asyncio_runner API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.asyncio_runner

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncioListenerRunner -(logger: logging.Logger,
process_before_response: bool,
listener_error_handler: AsyncListenerErrorHandler,
listener_start_handler: AsyncListenerStartHandler,
listener_completion_handler: AsyncListenerCompletionHandler,
lazy_listener_runner: AsyncLazyListenerRunner)
-
-
-
- -Expand source code - -
class AsyncioListenerRunner:
-    logger: Logger
-    process_before_response: bool
-    listener_error_handler: AsyncListenerErrorHandler
-    listener_start_handler: AsyncListenerStartHandler
-    listener_completion_handler: AsyncListenerCompletionHandler
-    lazy_listener_runner: AsyncLazyListenerRunner
-
-    def __init__(
-        self,
-        logger: Logger,
-        process_before_response: bool,
-        listener_error_handler: AsyncListenerErrorHandler,
-        listener_start_handler: AsyncListenerStartHandler,
-        listener_completion_handler: AsyncListenerCompletionHandler,
-        lazy_listener_runner: AsyncLazyListenerRunner,
-    ):
-        self.logger = logger
-        self.process_before_response = process_before_response
-        self.listener_error_handler = listener_error_handler
-        self.listener_start_handler = listener_start_handler
-        self.listener_completion_handler = listener_completion_handler
-        self.lazy_listener_runner = lazy_listener_runner
-
-    async def run(
-        self,
-        request: AsyncBoltRequest,
-        response: BoltResponse,
-        listener_name: str,
-        listener: AsyncListener,
-        starting_time: Optional[float] = None,
-    ) -> Optional[BoltResponse]:
-        ack = request.context.ack
-        starting_time = starting_time if starting_time is not None else time.time()
-        if self.process_before_response:
-            if not request.lazy_only:
-                try:
-                    await self.listener_start_handler.handle(request=request, response=response)
-                    returned_value = await listener.run_ack_function(request=request, response=response)
-                    if isinstance(returned_value, BoltResponse):
-                        response = returned_value
-                    if ack.response is None and listener.auto_acknowledgement:
-                        await ack()  # automatic ack() call if the call is not yet done
-                except Exception as e:
-                    # The default response status code is 500 in this case.
-                    # You can customize this by passing your own error handler.
-                    if response is None:
-                        response = BoltResponse(status=500)
-                    response.status = 500
-                    await self.listener_error_handler.handle(
-                        error=e,
-                        request=request,
-                        response=response,
-                    )
-                    ack.response = response
-                finally:
-                    await self.listener_completion_handler.handle(request=request, response=response)
-
-            for lazy_func in listener.lazy_functions:
-                if request.lazy_function_name:
-                    func_name = get_name_for_callable(lazy_func)
-                    if func_name == request.lazy_function_name:
-                        await self.lazy_listener_runner.run(function=lazy_func, request=request)
-                        # This HTTP response won't be sent to Slack API servers.
-                        return BoltResponse(status=200)
-                    else:
-                        continue
-                else:
-                    self._start_lazy_function(lazy_func, request)
-
-            if response is not None:
-                self._debug_log_completion(starting_time, response)
-                return response
-            elif ack.response is not None:
-                self._debug_log_completion(starting_time, ack.response)
-                return ack.response
-        else:
-            if listener.auto_acknowledgement:
-                # acknowledge immediately in case of Events API
-                await ack()
-
-            if not request.lazy_only:
-                # start the listener function asynchronously
-                # NOTE: intentionally
-                async def run_ack_function_asynchronously(
-                    ack: AsyncAck,
-                    request: AsyncBoltRequest,
-                    response: BoltResponse,
-                ):
-                    try:
-                        await self.listener_start_handler.handle(request=request, response=response)
-                        await listener.run_ack_function(request=request, response=response)
-                    except Exception as e:
-                        # The default response status code is 500 in this case.
-                        # You can customize this by passing your own error handler.
-                        if response is None:
-                            response = BoltResponse(status=500)
-                        response.status = 500
-                        if ack.response is not None:  # already acknowledged
-                            response = None  # type: ignore[assignment]
-
-                        await self.listener_error_handler.handle(
-                            error=e,
-                            request=request,
-                            response=response,
-                        )
-                        ack.response = response
-                    finally:
-                        await self.listener_completion_handler.handle(request=request, response=response)
-
-                _f: Future = asyncio.ensure_future(run_ack_function_asynchronously(ack, request, response))
-
-            for lazy_func in listener.lazy_functions:
-                if request.lazy_function_name:
-                    func_name = get_name_for_callable(lazy_func)
-                    if func_name == request.lazy_function_name:
-                        await self.lazy_listener_runner.run(function=lazy_func, request=request)
-                        # This HTTP response won't be sent to Slack API servers.
-                        return BoltResponse(status=200)
-                    else:
-                        continue
-                else:
-                    self._start_lazy_function(lazy_func, request)
-
-            # await for the completion of ack() in the async listener execution
-            while ack.response is None and time.time() - starting_time <= listener.ack_timeout:
-                await asyncio.sleep(0.01)
-
-            if response is None and ack.response is None:
-                self.logger.warning(warning_did_not_call_ack(listener_name))
-                return None
-
-            if response is None and ack.response is not None:
-                response = ack.response
-                self._debug_log_completion(starting_time, response)
-                return response
-
-            if response is not None:
-                return response
-
-        # None for both means no ack() in the listener
-        return None
-
-    def _start_lazy_function(self, lazy_func: Callable[..., Awaitable[None]], request: AsyncBoltRequest) -> None:
-        # Start a lazy function asynchronously
-        func_name: str = get_name_for_callable(lazy_func)
-        self.logger.debug(debug_running_lazy_listener(func_name))
-        copied_request = self._build_lazy_request(request, func_name)
-        self.lazy_listener_runner.start(function=lazy_func, request=copied_request)
-
-    def _build_lazy_request(self, request: AsyncBoltRequest, lazy_func_name: str) -> AsyncBoltRequest:
-        copied_request: AsyncBoltRequest = create_copy(request.to_copyable())
-        copied_request.lazy_only = True
-        copied_request.lazy_function_name = lazy_func_name
-        copied_request.context["listener_runner"] = self
-        if request.context.get_thread_context is not None:
-            copied_request.context["get_thread_context"] = request.context.get_thread_context
-        if request.context.save_thread_context is not None:
-            copied_request.context["save_thread_context"] = request.context.save_thread_context
-        return copied_request
-
-    def _debug_log_completion(self, starting_time: float, response: BoltResponse) -> None:
-        millis = int((time.time() - starting_time) * 1000)
-        self.logger.debug(debug_responding(response.status, response.body, millis))
-
-
-

Class variables

-
-
var lazy_listener_runnerAsyncLazyListenerRunner
-
-

The type of the None singleton.

-
-
var listener_completion_handlerAsyncListenerCompletionHandler
-
-

The type of the None singleton.

-
-
var listener_error_handlerAsyncListenerErrorHandler
-
-

The type of the None singleton.

-
-
var listener_start_handlerAsyncListenerStartHandler
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
var process_before_response : bool
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-async def run(self,
request: AsyncBoltRequest,
response: BoltResponse,
listener_name: str,
listener: AsyncListener,
starting_time: float | None = None) ‑> BoltResponse | None
-
-
-
- -Expand source code - -
async def run(
-    self,
-    request: AsyncBoltRequest,
-    response: BoltResponse,
-    listener_name: str,
-    listener: AsyncListener,
-    starting_time: Optional[float] = None,
-) -> Optional[BoltResponse]:
-    ack = request.context.ack
-    starting_time = starting_time if starting_time is not None else time.time()
-    if self.process_before_response:
-        if not request.lazy_only:
-            try:
-                await self.listener_start_handler.handle(request=request, response=response)
-                returned_value = await listener.run_ack_function(request=request, response=response)
-                if isinstance(returned_value, BoltResponse):
-                    response = returned_value
-                if ack.response is None and listener.auto_acknowledgement:
-                    await ack()  # automatic ack() call if the call is not yet done
-            except Exception as e:
-                # The default response status code is 500 in this case.
-                # You can customize this by passing your own error handler.
-                if response is None:
-                    response = BoltResponse(status=500)
-                response.status = 500
-                await self.listener_error_handler.handle(
-                    error=e,
-                    request=request,
-                    response=response,
-                )
-                ack.response = response
-            finally:
-                await self.listener_completion_handler.handle(request=request, response=response)
-
-        for lazy_func in listener.lazy_functions:
-            if request.lazy_function_name:
-                func_name = get_name_for_callable(lazy_func)
-                if func_name == request.lazy_function_name:
-                    await self.lazy_listener_runner.run(function=lazy_func, request=request)
-                    # This HTTP response won't be sent to Slack API servers.
-                    return BoltResponse(status=200)
-                else:
-                    continue
-            else:
-                self._start_lazy_function(lazy_func, request)
-
-        if response is not None:
-            self._debug_log_completion(starting_time, response)
-            return response
-        elif ack.response is not None:
-            self._debug_log_completion(starting_time, ack.response)
-            return ack.response
-    else:
-        if listener.auto_acknowledgement:
-            # acknowledge immediately in case of Events API
-            await ack()
-
-        if not request.lazy_only:
-            # start the listener function asynchronously
-            # NOTE: intentionally
-            async def run_ack_function_asynchronously(
-                ack: AsyncAck,
-                request: AsyncBoltRequest,
-                response: BoltResponse,
-            ):
-                try:
-                    await self.listener_start_handler.handle(request=request, response=response)
-                    await listener.run_ack_function(request=request, response=response)
-                except Exception as e:
-                    # The default response status code is 500 in this case.
-                    # You can customize this by passing your own error handler.
-                    if response is None:
-                        response = BoltResponse(status=500)
-                    response.status = 500
-                    if ack.response is not None:  # already acknowledged
-                        response = None  # type: ignore[assignment]
-
-                    await self.listener_error_handler.handle(
-                        error=e,
-                        request=request,
-                        response=response,
-                    )
-                    ack.response = response
-                finally:
-                    await self.listener_completion_handler.handle(request=request, response=response)
-
-            _f: Future = asyncio.ensure_future(run_ack_function_asynchronously(ack, request, response))
-
-        for lazy_func in listener.lazy_functions:
-            if request.lazy_function_name:
-                func_name = get_name_for_callable(lazy_func)
-                if func_name == request.lazy_function_name:
-                    await self.lazy_listener_runner.run(function=lazy_func, request=request)
-                    # This HTTP response won't be sent to Slack API servers.
-                    return BoltResponse(status=200)
-                else:
-                    continue
-            else:
-                self._start_lazy_function(lazy_func, request)
-
-        # await for the completion of ack() in the async listener execution
-        while ack.response is None and time.time() - starting_time <= listener.ack_timeout:
-            await asyncio.sleep(0.01)
-
-        if response is None and ack.response is None:
-            self.logger.warning(warning_did_not_call_ack(listener_name))
-            return None
-
-        if response is None and ack.response is not None:
-            response = ack.response
-            self._debug_log_completion(starting_time, response)
-            return response
-
-        if response is not None:
-            return response
-
-    # None for both means no ack() in the listener
-    return None
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener/builtins.html b/docs/reference/listener/builtins.html deleted file mode 100644 index 5f3759658..000000000 --- a/docs/reference/listener/builtins.html +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - -slack_bolt.listener.builtins API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.builtins

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class TokenRevocationListeners -(installation_store: slack_sdk.oauth.installation_store.installation_store.InstallationStore) -
-
-
- -Expand source code - -
class TokenRevocationListeners:
-    """Listener functions to handle token revocation / uninstallation events"""
-
-    installation_store: InstallationStore
-
-    def __init__(self, installation_store: InstallationStore):
-        self.installation_store = installation_store
-
-    def handle_tokens_revoked_events(self, event: dict, context: BoltContext) -> None:
-        user_ids = event.get("tokens", {}).get("oauth", [])
-        if len(user_ids) > 0:
-            for user_id in user_ids:
-                self.installation_store.delete_installation(
-                    enterprise_id=context.enterprise_id,
-                    team_id=context.team_id,
-                    user_id=user_id,
-                )
-        bots = event.get("tokens", {}).get("bot", [])
-        if len(bots) > 0:
-            self.installation_store.delete_bot(
-                enterprise_id=context.enterprise_id,
-                team_id=context.team_id,
-            )
-
-    def handle_app_uninstalled_events(self, context: BoltContext) -> None:
-        self.installation_store.delete_all(
-            enterprise_id=context.enterprise_id,
-            team_id=context.team_id,
-        )
-
-

Listener functions to handle token revocation / uninstallation events

-

Class variables

-
-
var installation_store : slack_sdk.oauth.installation_store.installation_store.InstallationStore
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def handle_app_uninstalled_events(self,
context: BoltContext) ‑> None
-
-
-
- -Expand source code - -
def handle_app_uninstalled_events(self, context: BoltContext) -> None:
-    self.installation_store.delete_all(
-        enterprise_id=context.enterprise_id,
-        team_id=context.team_id,
-    )
-
-
-
-
-def handle_tokens_revoked_events(self,
event: dict,
context: BoltContext) ‑> None
-
-
-
- -Expand source code - -
def handle_tokens_revoked_events(self, event: dict, context: BoltContext) -> None:
-    user_ids = event.get("tokens", {}).get("oauth", [])
-    if len(user_ids) > 0:
-        for user_id in user_ids:
-            self.installation_store.delete_installation(
-                enterprise_id=context.enterprise_id,
-                team_id=context.team_id,
-                user_id=user_id,
-            )
-    bots = event.get("tokens", {}).get("bot", [])
-    if len(bots) > 0:
-        self.installation_store.delete_bot(
-            enterprise_id=context.enterprise_id,
-            team_id=context.team_id,
-        )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener/custom_listener.html b/docs/reference/listener/custom_listener.html deleted file mode 100644 index 1f18502f2..000000000 --- a/docs/reference/listener/custom_listener.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - -slack_bolt.listener.custom_listener API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.custom_listener

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class CustomListener -(*,
app_name: str,
ack_function: Callable[..., BoltResponse | None],
lazy_functions: Sequence[Callable[..., None]],
matchers: Sequence[ListenerMatcher],
middleware: Sequence[Middleware],
auto_acknowledgement: bool = False,
ack_timeout: int = 3,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class CustomListener(Listener):
-    app_name: str
-    ack_function: Callable[..., Optional[BoltResponse]]  # type: ignore[assignment]
-    lazy_functions: Sequence[Callable[..., None]]
-    matchers: Sequence[ListenerMatcher]
-    middleware: Sequence[Middleware]
-    auto_acknowledgement: bool
-    ack_timeout: int = 3
-    arg_names: MutableSequence[str]
-    logger: Logger
-
-    def __init__(
-        self,
-        *,
-        app_name: str,
-        ack_function: Callable[..., Optional[BoltResponse]],
-        lazy_functions: Sequence[Callable[..., None]],
-        matchers: Sequence[ListenerMatcher],
-        middleware: Sequence[Middleware],
-        auto_acknowledgement: bool = False,
-        ack_timeout: int = 3,
-        base_logger: Optional[Logger] = None,
-    ):
-        self.app_name = app_name
-        self.ack_function = ack_function
-        self.lazy_functions = lazy_functions
-        self.matchers = matchers
-        self.middleware = middleware
-        self.auto_acknowledgement = auto_acknowledgement
-        self.ack_timeout = ack_timeout
-        self.arg_names = get_arg_names_of_callable(ack_function)
-        self.logger = get_bolt_app_logger(app_name, self.ack_function, base_logger)
-
-    def run_ack_function(
-        self,
-        *,
-        request: BoltRequest,
-        response: BoltResponse,
-    ) -> Optional[BoltResponse]:
-        return self.ack_function(
-            **build_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,
-                request=request,
-                response=response,
-                this_func=self.ack_function,
-            )
-        )
-
-
-

Ancestors

- -

Class variables

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : MutableSequence[str]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/listener/index.html b/docs/reference/listener/index.html deleted file mode 100644 index f31264cac..000000000 --- a/docs/reference/listener/index.html +++ /dev/null @@ -1,471 +0,0 @@ - - - - - - -slack_bolt.listener API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener

-
-
-

Listeners process an incoming request from Slack if the request's type or data structure matches -the predefined conditions of the listener. Typically, a listener acknowledge requests from Slack, -process the request data, and may send response back to Slack.

-
-
-

Sub-modules

-
-
slack_bolt.listener.async_builtins
-
-
-
-
slack_bolt.listener.async_listener
-
-
-
-
slack_bolt.listener.async_listener_completion_handler
-
-
-
-
slack_bolt.listener.async_listener_error_handler
-
-
-
-
slack_bolt.listener.async_listener_start_handler
-
-
-
-
slack_bolt.listener.asyncio_runner
-
-
-
-
slack_bolt.listener.builtins
-
-
-
-
slack_bolt.listener.custom_listener
-
-
-
-
slack_bolt.listener.listener
-
-
-
-
slack_bolt.listener.listener_completion_handler
-
-
-
-
slack_bolt.listener.listener_error_handler
-
-
-
-
slack_bolt.listener.listener_start_handler
-
-
-
-
slack_bolt.listener.thread_runner
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class CustomListener -(*,
app_name: str,
ack_function: Callable[..., BoltResponse | None],
lazy_functions: Sequence[Callable[..., None]],
matchers: Sequence[ListenerMatcher],
middleware: Sequence[Middleware],
auto_acknowledgement: bool = False,
ack_timeout: int = 3,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class CustomListener(Listener):
-    app_name: str
-    ack_function: Callable[..., Optional[BoltResponse]]  # type: ignore[assignment]
-    lazy_functions: Sequence[Callable[..., None]]
-    matchers: Sequence[ListenerMatcher]
-    middleware: Sequence[Middleware]
-    auto_acknowledgement: bool
-    ack_timeout: int = 3
-    arg_names: MutableSequence[str]
-    logger: Logger
-
-    def __init__(
-        self,
-        *,
-        app_name: str,
-        ack_function: Callable[..., Optional[BoltResponse]],
-        lazy_functions: Sequence[Callable[..., None]],
-        matchers: Sequence[ListenerMatcher],
-        middleware: Sequence[Middleware],
-        auto_acknowledgement: bool = False,
-        ack_timeout: int = 3,
-        base_logger: Optional[Logger] = None,
-    ):
-        self.app_name = app_name
-        self.ack_function = ack_function
-        self.lazy_functions = lazy_functions
-        self.matchers = matchers
-        self.middleware = middleware
-        self.auto_acknowledgement = auto_acknowledgement
-        self.ack_timeout = ack_timeout
-        self.arg_names = get_arg_names_of_callable(ack_function)
-        self.logger = get_bolt_app_logger(app_name, self.ack_function, base_logger)
-
-    def run_ack_function(
-        self,
-        *,
-        request: BoltRequest,
-        response: BoltResponse,
-    ) -> Optional[BoltResponse]:
-        return self.ack_function(
-            **build_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,
-                request=request,
-                response=response,
-                this_func=self.ack_function,
-            )
-        )
-
-
-

Ancestors

- -

Class variables

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : MutableSequence[str]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class Listener -
-
-
- -Expand source code - -
class Listener(metaclass=ABCMeta):
-    matchers: Sequence[ListenerMatcher]
-    middleware: Sequence[Middleware]
-    ack_function: Callable[..., BoltResponse]
-    lazy_functions: Sequence[Callable[..., None]]
-    auto_acknowledgement: bool
-    ack_timeout: int = 3
-
-    def matches(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-    ) -> bool:
-        is_matched: bool = False
-        for matcher in self.matchers:
-            is_matched = matcher.matches(req, resp)
-            if not is_matched:
-                return is_matched
-        return is_matched
-
-    def run_middleware(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-    ) -> Tuple[Optional[BoltResponse], bool]:
-        """Runs a middleware.
-
-        Args:
-            req: The incoming request
-            resp: The current response
-
-        Returns:
-            A tuple of the processed response and a flag indicating termination
-        """
-        for m in self.middleware:
-            middleware_state = {"next_called": False}
-
-            def next_():
-                middleware_state["next_called"] = True
-
-            resp = m.process(req=req, resp=resp, next=next_)  # type: ignore[assignment]
-            if not middleware_state["next_called"]:
-                # next() was not called in this middleware
-                return (resp, True)
-        return (resp, False)
-
-    @abstractmethod
-    def run_ack_function(self, *, request: BoltRequest, response: BoltResponse) -> Optional[BoltResponse]:
-        """Runs all the registered middleware and then run the listener function.
-
-        Args:
-            request: The incoming request
-            response: The current response
-
-        Returns:
-            The processed response
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Class variables

-
-
var ack_function : Callable[..., BoltResponse]
-
-

The type of the None singleton.

-
-
var ack_timeout : int
-
-

The type of the None singleton.

-
-
var auto_acknowledgement : bool
-
-

The type of the None singleton.

-
-
var lazy_functions : Sequence[Callable[..., None]]
-
-

The type of the None singleton.

-
-
var matchers : Sequence[ListenerMatcher]
-
-

The type of the None singleton.

-
-
var middleware : Sequence[Middleware]
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def matches(self,
*,
req: BoltRequest,
resp: BoltResponse) ‑> bool
-
-
-
- -Expand source code - -
def matches(
-    self,
-    *,
-    req: BoltRequest,
-    resp: BoltResponse,
-) -> bool:
-    is_matched: bool = False
-    for matcher in self.matchers:
-        is_matched = matcher.matches(req, resp)
-        if not is_matched:
-            return is_matched
-    return is_matched
-
-
-
-
-def run_ack_function(self,
*,
request: BoltRequest,
response: BoltResponse) ‑> BoltResponse | None
-
-
-
- -Expand source code - -
@abstractmethod
-def run_ack_function(self, *, request: BoltRequest, response: BoltResponse) -> Optional[BoltResponse]:
-    """Runs all the registered middleware and then run the listener function.
-
-    Args:
-        request: The incoming request
-        response: The current response
-
-    Returns:
-        The processed response
-    """
-    raise NotImplementedError()
-
-

Runs all the registered middleware and then run the listener function.

-

Args

-
-
request
-
The incoming request
-
response
-
The current response
-
-

Returns

-

The processed response

-
-
-def run_middleware(self,
*,
req: BoltRequest,
resp: BoltResponse) ‑> Tuple[BoltResponse | None, bool]
-
-
-
- -Expand source code - -
def run_middleware(
-    self,
-    *,
-    req: BoltRequest,
-    resp: BoltResponse,
-) -> Tuple[Optional[BoltResponse], bool]:
-    """Runs a middleware.
-
-    Args:
-        req: The incoming request
-        resp: The current response
-
-    Returns:
-        A tuple of the processed response and a flag indicating termination
-    """
-    for m in self.middleware:
-        middleware_state = {"next_called": False}
-
-        def next_():
-            middleware_state["next_called"] = True
-
-        resp = m.process(req=req, resp=resp, next=next_)  # type: ignore[assignment]
-        if not middleware_state["next_called"]:
-            # next() was not called in this middleware
-            return (resp, True)
-    return (resp, False)
-
-

Runs a middleware.

-

Args

-
-
req
-
The incoming request
-
resp
-
The current response
-
-

Returns

-

A tuple of the processed response and a flag indicating termination

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener/listener.html b/docs/reference/listener/listener.html deleted file mode 100644 index 034dbe67f..000000000 --- a/docs/reference/listener/listener.html +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - -slack_bolt.listener.listener API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.listener

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Listener -
-
-
- -Expand source code - -
class Listener(metaclass=ABCMeta):
-    matchers: Sequence[ListenerMatcher]
-    middleware: Sequence[Middleware]
-    ack_function: Callable[..., BoltResponse]
-    lazy_functions: Sequence[Callable[..., None]]
-    auto_acknowledgement: bool
-    ack_timeout: int = 3
-
-    def matches(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-    ) -> bool:
-        is_matched: bool = False
-        for matcher in self.matchers:
-            is_matched = matcher.matches(req, resp)
-            if not is_matched:
-                return is_matched
-        return is_matched
-
-    def run_middleware(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-    ) -> Tuple[Optional[BoltResponse], bool]:
-        """Runs a middleware.
-
-        Args:
-            req: The incoming request
-            resp: The current response
-
-        Returns:
-            A tuple of the processed response and a flag indicating termination
-        """
-        for m in self.middleware:
-            middleware_state = {"next_called": False}
-
-            def next_():
-                middleware_state["next_called"] = True
-
-            resp = m.process(req=req, resp=resp, next=next_)  # type: ignore[assignment]
-            if not middleware_state["next_called"]:
-                # next() was not called in this middleware
-                return (resp, True)
-        return (resp, False)
-
-    @abstractmethod
-    def run_ack_function(self, *, request: BoltRequest, response: BoltResponse) -> Optional[BoltResponse]:
-        """Runs all the registered middleware and then run the listener function.
-
-        Args:
-            request: The incoming request
-            response: The current response
-
-        Returns:
-            The processed response
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Class variables

-
-
var ack_function : Callable[..., BoltResponse]
-
-

The type of the None singleton.

-
-
var ack_timeout : int
-
-

The type of the None singleton.

-
-
var auto_acknowledgement : bool
-
-

The type of the None singleton.

-
-
var lazy_functions : Sequence[Callable[..., None]]
-
-

The type of the None singleton.

-
-
var matchers : Sequence[ListenerMatcher]
-
-

The type of the None singleton.

-
-
var middleware : Sequence[Middleware]
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def matches(self,
*,
req: BoltRequest,
resp: BoltResponse) ‑> bool
-
-
-
- -Expand source code - -
def matches(
-    self,
-    *,
-    req: BoltRequest,
-    resp: BoltResponse,
-) -> bool:
-    is_matched: bool = False
-    for matcher in self.matchers:
-        is_matched = matcher.matches(req, resp)
-        if not is_matched:
-            return is_matched
-    return is_matched
-
-
-
-
-def run_ack_function(self,
*,
request: BoltRequest,
response: BoltResponse) ‑> BoltResponse | None
-
-
-
- -Expand source code - -
@abstractmethod
-def run_ack_function(self, *, request: BoltRequest, response: BoltResponse) -> Optional[BoltResponse]:
-    """Runs all the registered middleware and then run the listener function.
-
-    Args:
-        request: The incoming request
-        response: The current response
-
-    Returns:
-        The processed response
-    """
-    raise NotImplementedError()
-
-

Runs all the registered middleware and then run the listener function.

-

Args

-
-
request
-
The incoming request
-
response
-
The current response
-
-

Returns

-

The processed response

-
-
-def run_middleware(self,
*,
req: BoltRequest,
resp: BoltResponse) ‑> Tuple[BoltResponse | None, bool]
-
-
-
- -Expand source code - -
def run_middleware(
-    self,
-    *,
-    req: BoltRequest,
-    resp: BoltResponse,
-) -> Tuple[Optional[BoltResponse], bool]:
-    """Runs a middleware.
-
-    Args:
-        req: The incoming request
-        resp: The current response
-
-    Returns:
-        A tuple of the processed response and a flag indicating termination
-    """
-    for m in self.middleware:
-        middleware_state = {"next_called": False}
-
-        def next_():
-            middleware_state["next_called"] = True
-
-        resp = m.process(req=req, resp=resp, next=next_)  # type: ignore[assignment]
-        if not middleware_state["next_called"]:
-            # next() was not called in this middleware
-            return (resp, True)
-    return (resp, False)
-
-

Runs a middleware.

-

Args

-
-
req
-
The incoming request
-
resp
-
The current response
-
-

Returns

-

A tuple of the processed response and a flag indicating termination

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener/listener_completion_handler.html b/docs/reference/listener/listener_completion_handler.html deleted file mode 100644 index 42b1b5413..000000000 --- a/docs/reference/listener/listener_completion_handler.html +++ /dev/null @@ -1,227 +0,0 @@ - - - - - - -slack_bolt.listener.listener_completion_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.listener_completion_handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class CustomListenerCompletionHandler -(logger: logging.Logger, func: Callable[..., None]) -
-
-
- -Expand source code - -
class CustomListenerCompletionHandler(ListenerCompletionHandler):
-    def __init__(self, logger: Logger, func: Callable[..., None]):
-        self.func = func
-        self.logger = logger
-        self.arg_names = get_arg_names_of_callable(func)
-
-    def handle(
-        self,
-        request: BoltRequest,
-        response: Optional[BoltResponse],
-    ):
-        kwargs: Dict[str, Any] = build_required_kwargs(
-            required_arg_names=self.arg_names,
-            logger=self.logger,
-            request=request,
-            response=response,
-            next_keys_required=False,
-        )
-        self.func(**kwargs)
-
-
-

Ancestors

- -

Inherited members

- -
-
-class DefaultListenerCompletionHandler -(logger: logging.Logger) -
-
-
- -Expand source code - -
class DefaultListenerCompletionHandler(ListenerCompletionHandler):
-    def __init__(self, logger: Logger):
-        self.logger = logger
-
-    def handle(
-        self,
-        request: BoltRequest,
-        response: Optional[BoltResponse],
-    ):
-        pass
-
-
-

Ancestors

- -

Inherited members

- -
-
-class ListenerCompletionHandler -
-
-
- -Expand source code - -
class ListenerCompletionHandler(metaclass=ABCMeta):
-    @abstractmethod
-    def handle(
-        self,
-        request: BoltRequest,
-        response: Optional[BoltResponse],
-    ) -> None:
-        """Do something extra after the listener execution
-
-        Args:
-            request: The request.
-            response: The response.
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-def handle(self,
request: BoltRequest,
response: BoltResponse | None) ‑> None
-
-
-
- -Expand source code - -
@abstractmethod
-def handle(
-    self,
-    request: BoltRequest,
-    response: Optional[BoltResponse],
-) -> None:
-    """Do something extra after the listener execution
-
-    Args:
-        request: The request.
-        response: The response.
-    """
-    raise NotImplementedError()
-
-

Do something extra after the listener execution

-

Args

-
-
request
-
The request.
-
response
-
The response.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener/listener_error_handler.html b/docs/reference/listener/listener_error_handler.html deleted file mode 100644 index e344b15cb..000000000 --- a/docs/reference/listener/listener_error_handler.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - -slack_bolt.listener.listener_error_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.listener_error_handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class CustomListenerErrorHandler -(logger: logging.Logger,
func: Callable[..., BoltResponse | None])
-
-
-
- -Expand source code - -
class CustomListenerErrorHandler(ListenerErrorHandler):
-    def __init__(self, logger: Logger, func: Callable[..., Optional[BoltResponse]]):
-        self.func = func
-        self.logger = logger
-        self.arg_names = get_arg_names_of_callable(func)
-
-    def handle(
-        self,
-        error: Exception,
-        request: BoltRequest,
-        response: Optional[BoltResponse],
-    ):
-        kwargs: Dict[str, Any] = build_required_kwargs(
-            required_arg_names=self.arg_names,
-            logger=self.logger,
-            error=error,
-            request=request,
-            response=response,
-            next_keys_required=False,
-        )
-        returned_response = self.func(**kwargs)
-        if returned_response is not None and isinstance(returned_response, BoltResponse):
-            assert response is not None, "response must be provided when returning a BoltResponse from an error handler"
-            response.status = returned_response.status
-            response.headers = returned_response.headers
-            response.body = returned_response.body
-
-
-

Ancestors

- -

Inherited members

- -
-
-class DefaultListenerErrorHandler -(logger: logging.Logger) -
-
-
- -Expand source code - -
class DefaultListenerErrorHandler(ListenerErrorHandler):
-    def __init__(self, logger: Logger):
-        self.logger = logger
-
-    def handle(
-        self,
-        error: Exception,
-        request: BoltRequest,
-        response: Optional[BoltResponse],
-    ):
-        message = f"Failed to run listener function (error: {error})"
-        self.logger.exception(message)
-
-
-

Ancestors

- -

Inherited members

- -
-
-class ListenerErrorHandler -
-
-
- -Expand source code - -
class ListenerErrorHandler(metaclass=ABCMeta):
-    @abstractmethod
-    def handle(
-        self,
-        error: Exception,
-        request: BoltRequest,
-        response: Optional[BoltResponse],
-    ) -> None:
-        """Handles an unhandled exception.
-
-        Args:
-            error: The raised exception.
-            request: The request.
-            response: The response.
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-def handle(self,
error: Exception,
request: BoltRequest,
response: BoltResponse | None) ‑> None
-
-
-
- -Expand source code - -
@abstractmethod
-def handle(
-    self,
-    error: Exception,
-    request: BoltRequest,
-    response: Optional[BoltResponse],
-) -> None:
-    """Handles an unhandled exception.
-
-    Args:
-        error: The raised exception.
-        request: The request.
-        response: The response.
-    """
-    raise NotImplementedError()
-
-

Handles an unhandled exception.

-

Args

-
-
error
-
The raised exception.
-
request
-
The request.
-
response
-
The response.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener/listener_start_handler.html b/docs/reference/listener/listener_start_handler.html deleted file mode 100644 index d60c1b9dc..000000000 --- a/docs/reference/listener/listener_start_handler.html +++ /dev/null @@ -1,238 +0,0 @@ - - - - - - -slack_bolt.listener.listener_start_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.listener_start_handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class CustomListenerStartHandler -(logger: logging.Logger, func: Callable[..., None]) -
-
-
- -Expand source code - -
class CustomListenerStartHandler(ListenerStartHandler):
-    def __init__(self, logger: Logger, func: Callable[..., None]):
-        self.func = func
-        self.logger = logger
-        self.arg_names = get_arg_names_of_callable(func)
-
-    def handle(
-        self,
-        request: BoltRequest,
-        response: Optional[BoltResponse],
-    ):
-        kwargs: Dict[str, Any] = build_required_kwargs(
-            required_arg_names=self.arg_names,
-            logger=self.logger,
-            request=request,
-            response=response,
-            next_keys_required=False,
-        )
-        self.func(**kwargs)
-
-
-

Ancestors

- -

Inherited members

- -
-
-class DefaultListenerStartHandler -(logger: logging.Logger) -
-
-
- -Expand source code - -
class DefaultListenerStartHandler(ListenerStartHandler):
-    def __init__(self, logger: Logger):
-        self.logger = logger
-
-    def handle(
-        self,
-        request: BoltRequest,
-        response: Optional[BoltResponse],
-    ):
-        pass
-
-
-

Ancestors

- -

Inherited members

- -
-
-class ListenerStartHandler -
-
-
- -Expand source code - -
class ListenerStartHandler(metaclass=ABCMeta):
-    @abstractmethod
-    def handle(
-        self,
-        request: BoltRequest,
-        response: Optional[BoltResponse],
-    ) -> None:
-        """Do something extra before the listener execution.
-
-        This handler is useful if a developer needs to maintain/clean up
-        thread-local resources such as Django ORM database connections
-        before a listener execution starts.
-
-        Args:
-            request: The request.
-            response: The response.
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-def handle(self,
request: BoltRequest,
response: BoltResponse | None) ‑> None
-
-
-
- -Expand source code - -
@abstractmethod
-def handle(
-    self,
-    request: BoltRequest,
-    response: Optional[BoltResponse],
-) -> None:
-    """Do something extra before the listener execution.
-
-    This handler is useful if a developer needs to maintain/clean up
-    thread-local resources such as Django ORM database connections
-    before a listener execution starts.
-
-    Args:
-        request: The request.
-        response: The response.
-    """
-    raise NotImplementedError()
-
-

Do something extra before the listener execution.

-

This handler is useful if a developer needs to maintain/clean up -thread-local resources such as Django ORM database connections -before a listener execution starts.

-

Args

-
-
request
-
The request.
-
response
-
The response.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener/thread_runner.html b/docs/reference/listener/thread_runner.html deleted file mode 100644 index 5415f9ada..000000000 --- a/docs/reference/listener/thread_runner.html +++ /dev/null @@ -1,457 +0,0 @@ - - - - - - -slack_bolt.listener.thread_runner API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener.thread_runner

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class ThreadListenerRunner -(logger: logging.Logger,
process_before_response: bool,
listener_error_handler: ListenerErrorHandler,
listener_start_handler: ListenerStartHandler,
listener_completion_handler: ListenerCompletionHandler,
listener_executor: concurrent.futures._base.Executor,
lazy_listener_runner: LazyListenerRunner)
-
-
-
- -Expand source code - -
class ThreadListenerRunner:
-    logger: Logger
-    process_before_response: bool
-    listener_error_handler: ListenerErrorHandler
-    listener_start_handler: ListenerStartHandler
-    listener_completion_handler: ListenerCompletionHandler
-    listener_executor: Executor
-    lazy_listener_runner: LazyListenerRunner
-
-    def __init__(
-        self,
-        logger: Logger,
-        process_before_response: bool,
-        listener_error_handler: ListenerErrorHandler,
-        listener_start_handler: ListenerStartHandler,
-        listener_completion_handler: ListenerCompletionHandler,
-        listener_executor: Executor,
-        lazy_listener_runner: LazyListenerRunner,
-    ):
-        self.logger = logger
-        self.process_before_response = process_before_response
-        self.listener_error_handler = listener_error_handler
-        self.listener_start_handler = listener_start_handler
-        self.listener_completion_handler = listener_completion_handler
-        self.listener_executor = listener_executor
-        self.lazy_listener_runner = lazy_listener_runner
-
-    def run(
-        self,
-        request: BoltRequest,
-        response: BoltResponse,
-        listener_name: str,
-        listener: Listener,
-        starting_time: Optional[float] = None,
-    ) -> Optional[BoltResponse]:
-        ack = request.context.ack
-        starting_time = starting_time if starting_time is not None else time.time()
-        if self.process_before_response:
-            if not request.lazy_only:
-                try:
-                    self.listener_start_handler.handle(
-                        request=request,
-                        response=response,
-                    )
-                    returned_value = listener.run_ack_function(request=request, response=response)
-                    if isinstance(returned_value, BoltResponse):
-                        response = returned_value
-                    if ack.response is None and listener.auto_acknowledgement:
-                        ack()  # automatic ack() call if the call is not yet done
-                except Exception as e:
-                    # The default response status code is 500 in this case.
-                    # You can customize this by passing your own error handler.
-                    if response is None:
-                        response = BoltResponse(status=500)
-                    response.status = 500
-                    self.listener_error_handler.handle(
-                        error=e,
-                        request=request,
-                        response=response,
-                    )
-                    ack.response = response
-                finally:
-                    self.listener_completion_handler.handle(
-                        request=request,
-                        response=response,
-                    )
-
-            for lazy_func in listener.lazy_functions:
-                if request.lazy_function_name:
-                    func_name = get_name_for_callable(lazy_func)
-                    if func_name == request.lazy_function_name:
-                        self.lazy_listener_runner.run(function=lazy_func, request=request)
-                        # This HTTP response won't be sent to Slack API servers.
-                        return BoltResponse(status=200)
-                    else:
-                        continue
-                else:
-                    self._start_lazy_function(lazy_func, request)
-
-            if response is not None:
-                self._debug_log_completion(starting_time, response)
-                return response
-            elif ack.response is not None:
-                self._debug_log_completion(starting_time, ack.response)
-                return ack.response
-        else:
-            if listener.auto_acknowledgement:
-                # acknowledge immediately in case of Events API
-                ack()
-
-            if not request.lazy_only:
-                # start the listener function asynchronously
-                def run_ack_function_asynchronously():
-                    nonlocal response
-                    try:
-                        self.listener_start_handler.handle(
-                            request=request,
-                            response=response,
-                        )
-                        listener.run_ack_function(request=request, response=response)
-                    except Exception as e:
-                        # The default response status code is 500 in this case.
-                        # You can customize this by passing your own error handler.
-                        if listener.auto_acknowledgement:
-                            self.listener_error_handler.handle(
-                                error=e,
-                                request=request,
-                                response=response,
-                            )
-                        else:
-                            if response is None:
-                                response = BoltResponse(status=500)
-                            response.status = 500
-                            if ack.response is not None:  # already acknowledged
-                                response = None
-                            self.listener_error_handler.handle(
-                                error=e,
-                                request=request,
-                                response=response,
-                            )
-                            ack.response = response
-                    finally:
-                        self.listener_completion_handler.handle(
-                            request=request,
-                            response=response,
-                        )
-
-                self.listener_executor.submit(run_ack_function_asynchronously)
-
-            for lazy_func in listener.lazy_functions:
-                if request.lazy_function_name:
-                    func_name = get_name_for_callable(lazy_func)
-                    if func_name == request.lazy_function_name:
-                        self.lazy_listener_runner.run(function=lazy_func, request=request)
-                        # This HTTP response won't be sent to Slack API servers.
-                        return BoltResponse(status=200)
-                    else:
-                        continue
-                else:
-                    self._start_lazy_function(lazy_func, request)
-
-            # await for the completion of ack() in the async listener execution
-            while ack.response is None and time.time() - starting_time <= listener.ack_timeout:
-                time.sleep(0.01)
-
-            if response is None and ack.response is None:
-                self.logger.warning(warning_did_not_call_ack(listener_name))
-                return None
-
-            if response is None and ack.response is not None:
-                response = ack.response
-                self._debug_log_completion(starting_time, response)
-                return response
-
-            if response is not None:
-                return response
-
-        # None for both means no ack() in the listener
-        return None
-
-    def _start_lazy_function(self, lazy_func: Callable[..., None], request: BoltRequest) -> None:
-        # Start a lazy function asynchronously
-        func_name: str = get_name_for_callable(lazy_func)
-        self.logger.debug(debug_running_lazy_listener(func_name))
-        copied_request = self._build_lazy_request(request, func_name)
-        self.lazy_listener_runner.start(function=lazy_func, request=copied_request)
-
-    def _build_lazy_request(self, request: BoltRequest, lazy_func_name: str) -> BoltRequest:
-        copied_request: BoltRequest = create_copy(request.to_copyable())
-        copied_request.lazy_only = True
-        copied_request.lazy_function_name = lazy_func_name
-        # These are not copyable objects, so manually set for a different thread
-        copied_request.context["listener_runner"] = self
-        if request.context.get_thread_context is not None:
-            copied_request.context["get_thread_context"] = request.context.get_thread_context
-        if request.context.save_thread_context is not None:
-            copied_request.context["save_thread_context"] = request.context.save_thread_context
-        return copied_request
-
-    def _debug_log_completion(self, starting_time: float, response: BoltResponse) -> None:
-        millis = int((time.time() - starting_time) * 1000)
-        self.logger.debug(debug_responding(response.status, response.body, millis))
-
-
-

Class variables

-
-
var lazy_listener_runnerLazyListenerRunner
-
-

The type of the None singleton.

-
-
var listener_completion_handlerListenerCompletionHandler
-
-

The type of the None singleton.

-
-
var listener_error_handlerListenerErrorHandler
-
-

The type of the None singleton.

-
-
var listener_executor : concurrent.futures._base.Executor
-
-

The type of the None singleton.

-
-
var listener_start_handlerListenerStartHandler
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
var process_before_response : bool
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def run(self,
request: BoltRequest,
response: BoltResponse,
listener_name: str,
listener: Listener,
starting_time: float | None = None) ‑> BoltResponse | None
-
-
-
- -Expand source code - -
def run(
-    self,
-    request: BoltRequest,
-    response: BoltResponse,
-    listener_name: str,
-    listener: Listener,
-    starting_time: Optional[float] = None,
-) -> Optional[BoltResponse]:
-    ack = request.context.ack
-    starting_time = starting_time if starting_time is not None else time.time()
-    if self.process_before_response:
-        if not request.lazy_only:
-            try:
-                self.listener_start_handler.handle(
-                    request=request,
-                    response=response,
-                )
-                returned_value = listener.run_ack_function(request=request, response=response)
-                if isinstance(returned_value, BoltResponse):
-                    response = returned_value
-                if ack.response is None and listener.auto_acknowledgement:
-                    ack()  # automatic ack() call if the call is not yet done
-            except Exception as e:
-                # The default response status code is 500 in this case.
-                # You can customize this by passing your own error handler.
-                if response is None:
-                    response = BoltResponse(status=500)
-                response.status = 500
-                self.listener_error_handler.handle(
-                    error=e,
-                    request=request,
-                    response=response,
-                )
-                ack.response = response
-            finally:
-                self.listener_completion_handler.handle(
-                    request=request,
-                    response=response,
-                )
-
-        for lazy_func in listener.lazy_functions:
-            if request.lazy_function_name:
-                func_name = get_name_for_callable(lazy_func)
-                if func_name == request.lazy_function_name:
-                    self.lazy_listener_runner.run(function=lazy_func, request=request)
-                    # This HTTP response won't be sent to Slack API servers.
-                    return BoltResponse(status=200)
-                else:
-                    continue
-            else:
-                self._start_lazy_function(lazy_func, request)
-
-        if response is not None:
-            self._debug_log_completion(starting_time, response)
-            return response
-        elif ack.response is not None:
-            self._debug_log_completion(starting_time, ack.response)
-            return ack.response
-    else:
-        if listener.auto_acknowledgement:
-            # acknowledge immediately in case of Events API
-            ack()
-
-        if not request.lazy_only:
-            # start the listener function asynchronously
-            def run_ack_function_asynchronously():
-                nonlocal response
-                try:
-                    self.listener_start_handler.handle(
-                        request=request,
-                        response=response,
-                    )
-                    listener.run_ack_function(request=request, response=response)
-                except Exception as e:
-                    # The default response status code is 500 in this case.
-                    # You can customize this by passing your own error handler.
-                    if listener.auto_acknowledgement:
-                        self.listener_error_handler.handle(
-                            error=e,
-                            request=request,
-                            response=response,
-                        )
-                    else:
-                        if response is None:
-                            response = BoltResponse(status=500)
-                        response.status = 500
-                        if ack.response is not None:  # already acknowledged
-                            response = None
-                        self.listener_error_handler.handle(
-                            error=e,
-                            request=request,
-                            response=response,
-                        )
-                        ack.response = response
-                finally:
-                    self.listener_completion_handler.handle(
-                        request=request,
-                        response=response,
-                    )
-
-            self.listener_executor.submit(run_ack_function_asynchronously)
-
-        for lazy_func in listener.lazy_functions:
-            if request.lazy_function_name:
-                func_name = get_name_for_callable(lazy_func)
-                if func_name == request.lazy_function_name:
-                    self.lazy_listener_runner.run(function=lazy_func, request=request)
-                    # This HTTP response won't be sent to Slack API servers.
-                    return BoltResponse(status=200)
-                else:
-                    continue
-            else:
-                self._start_lazy_function(lazy_func, request)
-
-        # await for the completion of ack() in the async listener execution
-        while ack.response is None and time.time() - starting_time <= listener.ack_timeout:
-            time.sleep(0.01)
-
-        if response is None and ack.response is None:
-            self.logger.warning(warning_did_not_call_ack(listener_name))
-            return None
-
-        if response is None and ack.response is not None:
-            response = ack.response
-            self._debug_log_completion(starting_time, response)
-            return response
-
-        if response is not None:
-            return response
-
-    # None for both means no ack() in the listener
-    return None
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener_matcher/async_builtins.html b/docs/reference/listener_matcher/async_builtins.html deleted file mode 100644 index 0df1215de..000000000 --- a/docs/reference/listener_matcher/async_builtins.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - -slack_bolt.listener_matcher.async_builtins API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener_matcher.async_builtins

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncBuiltinListenerMatcher -(*,
func: Callable[..., bool | Awaitable[bool]],
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncBuiltinListenerMatcher(BuiltinListenerMatcher, AsyncListenerMatcher):
-    async def async_matches(self, req: AsyncBoltRequest, resp: BoltResponse) -> bool:
-        return await self.func(  # type: ignore[misc]
-            **build_async_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,
-                request=req,
-                response=resp,
-                this_func=self.func,
-            )
-        )
-
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/listener_matcher/async_listener_matcher.html b/docs/reference/listener_matcher/async_listener_matcher.html deleted file mode 100644 index 1366da4e2..000000000 --- a/docs/reference/listener_matcher/async_listener_matcher.html +++ /dev/null @@ -1,317 +0,0 @@ - - - - - - -slack_bolt.listener_matcher.async_listener_matcher API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener_matcher.async_listener_matcher

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncCustomListenerMatcher -(*,
app_name: str,
func: Callable[..., Awaitable[bool]],
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncCustomListenerMatcher(AsyncListenerMatcher):
-    app_name: str
-    func: Callable[..., Awaitable[bool]]
-    arg_names: Sequence[str]
-    logger: Logger
-
-    def __init__(self, *, app_name: str, func: Callable[..., Awaitable[bool]], base_logger: Optional[Logger] = None):
-        self.app_name = app_name
-        self.func = func
-        self.arg_names = get_arg_names_of_callable(func)
-        self.logger = get_bolt_app_logger(self.app_name, self.func, base_logger)
-
-    async def async_matches(self, req: AsyncBoltRequest, resp: BoltResponse) -> bool:
-        return await self.func(
-            **build_async_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,  # type: ignore[arg-type]
-                request=req,
-                response=resp,
-                this_func=self.func,
-            )
-        )
-
-
-

Ancestors

- -

Class variables

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : Sequence[str]
-
-

The type of the None singleton.

-
-
var func : Callable[..., Awaitable[bool]]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-async def async_matches(self,
req: AsyncBoltRequest,
resp: BoltResponse) ‑> bool
-
-
-
- -Expand source code - -
async def async_matches(self, req: AsyncBoltRequest, resp: BoltResponse) -> bool:
-    return await self.func(
-        **build_async_required_kwargs(
-            logger=self.logger,
-            required_arg_names=self.arg_names,  # type: ignore[arg-type]
-            request=req,
-            response=resp,
-            this_func=self.func,
-        )
-    )
-
-

Matches against the request and returns True if matched.

-

Args

-
-
req
-
The request
-
resp
-
The response
-
-

Returns

-

True if matched

-
-
-
-
-class cls -(*,
app_name: str,
func: Callable[..., Awaitable[bool]],
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncCustomListenerMatcher(AsyncListenerMatcher):
-    app_name: str
-    func: Callable[..., Awaitable[bool]]
-    arg_names: Sequence[str]
-    logger: Logger
-
-    def __init__(self, *, app_name: str, func: Callable[..., Awaitable[bool]], base_logger: Optional[Logger] = None):
-        self.app_name = app_name
-        self.func = func
-        self.arg_names = get_arg_names_of_callable(func)
-        self.logger = get_bolt_app_logger(self.app_name, self.func, base_logger)
-
-    async def async_matches(self, req: AsyncBoltRequest, resp: BoltResponse) -> bool:
-        return await self.func(
-            **build_async_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,  # type: ignore[arg-type]
-                request=req,
-                response=resp,
-                this_func=self.func,
-            )
-        )
-
-
-

Ancestors

- -

Class variables

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : Sequence[str]
-
-

The type of the None singleton.

-
-
var func : Callable[..., Awaitable[bool]]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class AsyncListenerMatcher -
-
-
- -Expand source code - -
class AsyncListenerMatcher(metaclass=ABCMeta):
-    @abstractmethod
-    async def async_matches(self, req: AsyncBoltRequest, resp: BoltResponse) -> bool:
-        """Matches against the request and returns True if matched.
-
-        Args:
-            req: The request
-            resp: The response
-
-        Returns:
-            True if matched
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-async def async_matches(self,
req: AsyncBoltRequest,
resp: BoltResponse) ‑> bool
-
-
-
- -Expand source code - -
@abstractmethod
-async def async_matches(self, req: AsyncBoltRequest, resp: BoltResponse) -> bool:
-    """Matches against the request and returns True if matched.
-
-    Args:
-        req: The request
-        resp: The response
-
-    Returns:
-        True if matched
-    """
-    raise NotImplementedError()
-
-

Matches against the request and returns True if matched.

-

Args

-
-
req
-
The request
-
resp
-
The response
-
-

Returns

-

True if matched

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener_matcher/builtins.html b/docs/reference/listener_matcher/builtins.html deleted file mode 100644 index a5aff3d0b..000000000 --- a/docs/reference/listener_matcher/builtins.html +++ /dev/null @@ -1,698 +0,0 @@ - - - - - - -slack_bolt.listener_matcher.builtins API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener_matcher.builtins

-
-
-
-
-
-
-
-
-

Functions

-
-
-def action(constraints: str | re.Pattern | Dict[str, str | re.Pattern],
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def action(
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    if isinstance(constraints, (str, Pattern)):
-
-        def func(body: Dict[str, Any]) -> bool:
-            return (
-                _block_action(constraints, body)
-                or _attachment_action(constraints, body)
-                or _dialog_submission(constraints, body)
-                or _dialog_cancellation(constraints, body)
-                or _workflow_step_edit(constraints, body)
-            )
-
-        return build_listener_matcher(func, asyncio, base_logger)
-
-    elif "type" in constraints:
-        action_type = constraints["type"]
-        if action_type == "block_actions":
-            return block_action(constraints, asyncio)
-        if action_type == "interactive_message":
-            return attachment_action(constraints["callback_id"], asyncio)
-        if action_type == "dialog_submission":
-            return dialog_submission(constraints["callback_id"], asyncio)
-        if action_type == "dialog_cancellation":
-            return dialog_cancellation(constraints["callback_id"], asyncio)
-        # https://docs.slack.dev/legacy/legacy-steps-from-apps/
-        if action_type == "workflow_step_edit":
-            return workflow_step_edit(constraints["callback_id"], asyncio)
-
-        raise BoltError(f"type: {action_type} is unsupported")
-    elif "action_id" in constraints or "block_id" in constraints:
-        # The default value is "block_actions"
-        return block_action(constraints, asyncio)
-
-    raise BoltError(f"action ({constraints}: {type(constraints)}) must be any of str, Pattern, and dict")
-
-
-
-
-def attachment_action(callback_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def attachment_action(
-    callback_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return _attachment_action(callback_id, body)
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def block_action(constraints: str | re.Pattern | Dict[str, str | re.Pattern],
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def block_action(
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return _block_action(constraints, body)
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def block_suggestion(action_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def block_suggestion(
-    action_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return _block_suggestion(action_id, body)
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def build_listener_matcher(func: Callable[..., bool],
asyncio: bool,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def build_listener_matcher(
-    func: Callable[..., bool],
-    asyncio: bool,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    if asyncio:
-        from .async_builtins import AsyncBuiltinListenerMatcher
-
-        async def async_fun(body: Dict[str, Any]) -> bool:
-            return func(body)
-
-        return AsyncBuiltinListenerMatcher(func=async_fun, base_logger=base_logger)
-    else:
-        return BuiltinListenerMatcher(func=func, base_logger=base_logger)
-
-
-
-
-def command(command: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def command(
-    command: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return is_slash_command(body) and _matches(command, body["command"])
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def dialog_cancellation(callback_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def dialog_cancellation(
-    callback_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return _dialog_cancellation(callback_id, body)
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def dialog_submission(callback_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def dialog_submission(
-    callback_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return _dialog_submission(callback_id, body)
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def dialog_suggestion(callback_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def dialog_suggestion(
-    callback_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return _dialog_suggestion(callback_id, body)
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def event(constraints: str | re.Pattern | Dict[str, str | Sequence[str | re.Pattern | None] | None],
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def event(
-    constraints: Union[
-        str,
-        Pattern,
-        Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]],
-    ],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    if isinstance(constraints, (str, Pattern)):
-        event_type: Union[str, Pattern] = constraints
-        _verify_message_event_type(event_type)
-
-        def func(body: Dict[str, Any]) -> bool:
-            return is_event(body) and _matches(event_type, body["event"]["type"])
-
-        return build_listener_matcher(func, asyncio, base_logger)
-
-    elif "type" in constraints:
-        _verify_message_event_type(constraints["type"])  # type: ignore[arg-type]
-
-        def func(body: Dict[str, Any]) -> bool:
-            if is_event(body):
-                return _check_event_subtype(
-                    event_payload=body["event"],
-                    constraints=constraints,
-                )
-            return False
-
-        return build_listener_matcher(func, asyncio, base_logger)
-
-    raise BoltError(f"event ({constraints}: {type(constraints)}) must be any of str, Pattern, and dict")
-
-
-
-
-def function_executed(callback_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def function_executed(
-    callback_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return is_function(body) and _matches(callback_id, body.get("event", {}).get("function", {}).get("callback_id", ""))
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def global_shortcut(callback_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def global_shortcut(
-    callback_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return is_global_shortcut(body) and _matches(callback_id, body["callback_id"])
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def message_event(constraints: Dict[str, str | Sequence[str | re.Pattern | None] | None],
keyword: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def message_event(
-    constraints: Dict[str, Optional[Union[str, Sequence[Optional[Union[str, Pattern]]]]]],
-    keyword: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    if "type" in constraints and keyword is not None:
-        _verify_message_event_type(constraints["type"])  # type: ignore[arg-type]
-
-        def func(body: Dict[str, Any]) -> bool:
-            if is_event(body):
-                is_valid_subtype = _check_event_subtype(
-                    event_payload=body["event"],
-                    constraints=constraints,
-                )
-                if is_valid_subtype is True:
-                    # Check keyword matching
-                    text = body.get("event", {}).get("text", "")
-                    match_result = re.findall(keyword, text)
-                    if match_result is not None and match_result != []:
-                        return True
-            return False
-
-        return build_listener_matcher(func, asyncio, base_logger)
-
-    raise BoltError(f"event ({constraints}: {type(constraints)}) must be dict")
-
-
-
-
-def message_shortcut(callback_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def message_shortcut(
-    callback_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return is_message_shortcut(body) and _matches(callback_id, body["callback_id"])
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def options(constraints: str | re.Pattern | Dict[str, str | re.Pattern],
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def options(
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    if isinstance(constraints, (str, Pattern)):
-
-        def func(body: Dict[str, Any]) -> bool:
-            return _block_suggestion(constraints, body) or _dialog_suggestion(constraints, body)
-
-        return build_listener_matcher(func, asyncio, base_logger)
-
-    if "action_id" in constraints:
-        return block_suggestion(constraints["action_id"], asyncio)
-    if "callback_id" in constraints:
-        return dialog_suggestion(constraints["callback_id"], asyncio)
-    else:
-        raise BoltError(f"options ({constraints}: {type(constraints)}) must be any of str, Pattern, and dict")
-
-
-
-
-def shortcut(constraints: str | re.Pattern | Dict[str, str | re.Pattern],
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def shortcut(
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    if isinstance(constraints, (str, Pattern)):
-        callback_id: Union[str, Pattern] = constraints
-
-        def func(body: Dict[str, Any]) -> bool:
-            return is_shortcut(body) and _matches(callback_id, body["callback_id"])
-
-        return build_listener_matcher(func, asyncio, base_logger)
-
-    elif "type" in constraints and "callback_id" in constraints:
-        if constraints["type"] == "shortcut":
-            return global_shortcut(constraints["callback_id"], asyncio)
-        if constraints["type"] == "message_action":
-            return message_shortcut(constraints["callback_id"], asyncio)
-
-    raise BoltError(f"shortcut ({constraints}: {type(constraints)}) must be any of str, Pattern, and dict")
-
-
-
-
-def view(constraints: str | re.Pattern | Dict[str, str | re.Pattern],
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def view(
-    constraints: Union[str, Pattern, Dict[str, Union[str, Pattern]]],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    if isinstance(constraints, (str, Pattern)):
-        return view_submission(constraints, asyncio)
-    elif "type" in constraints:
-        if constraints["type"] == "view_submission":
-            return view_submission(constraints["callback_id"], asyncio)
-        if constraints["type"] == "view_closed":
-            return view_closed(constraints["callback_id"], asyncio)
-
-    raise BoltError(f"view ({constraints}: {type(constraints)}) must be any of str, Pattern, and dict")
-
-
-
-
-def view_closed(callback_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def view_closed(
-    callback_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return is_view_closed(body) and _matches(callback_id, body["view"]["callback_id"])
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def view_submission(callback_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def view_submission(
-    callback_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return is_view_submission(body) and _matches(callback_id, body["view"]["callback_id"])
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def workflow_step_edit(callback_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def workflow_step_edit(
-    callback_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return _workflow_step_edit(callback_id, body)
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def workflow_step_execute(callback_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def workflow_step_execute(
-    callback_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return (
-            is_event(body)
-            and _matches("workflow_step_execute", body["event"]["type"])
-            and "workflow_step" in body["event"]
-            and _matches(callback_id, body["event"]["callback_id"])
-        )
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-def workflow_step_save(callback_id: str | re.Pattern,
asyncio: bool = False,
base_logger: logging.Logger | None = None) ‑> ListenerMatcher | AsyncListenerMatcher
-
-
-
- -Expand source code - -
def workflow_step_save(
-    callback_id: Union[str, Pattern],
-    asyncio: bool = False,
-    base_logger: Optional[Logger] = None,
-) -> Union[ListenerMatcher, "AsyncListenerMatcher"]:  # type: ignore[name-defined]
-    def func(body: Dict[str, Any]) -> bool:
-        return is_workflow_step_save(body) and _matches(callback_id, body["view"]["callback_id"])
-
-    return build_listener_matcher(func, asyncio, base_logger)
-
-
-
-
-
-
-

Classes

-
-
-class BuiltinListenerMatcher -(*,
func: Callable[..., bool | Awaitable[bool]],
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class BuiltinListenerMatcher(ListenerMatcher):
-    def __init__(
-        self,
-        *,
-        func: Callable[..., Union[bool, Awaitable[bool]]],
-        base_logger: Optional[Logger] = None,
-    ):
-        self.func = func
-        self.arg_names = get_arg_names_of_callable(func)
-        self.logger = get_bolt_logger(self.func, base_logger)
-
-    def matches(self, req: BoltRequest, resp: BoltResponse) -> bool:
-        return self.func(  # type: ignore[return-value]
-            **build_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,
-                request=req,
-                response=resp,
-                this_func=self.func,
-            )
-        )
-
-
-

Ancestors

- -

Subclasses

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/listener_matcher/custom_listener_matcher.html b/docs/reference/listener_matcher/custom_listener_matcher.html deleted file mode 100644 index 087d36907..000000000 --- a/docs/reference/listener_matcher/custom_listener_matcher.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - -slack_bolt.listener_matcher.custom_listener_matcher API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener_matcher.custom_listener_matcher

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class CustomListenerMatcher -(*,
app_name: str,
func: Callable[..., bool],
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class CustomListenerMatcher(ListenerMatcher):
-    app_name: str
-    func: Callable[..., bool]
-    arg_names: MutableSequence[str]
-    logger: Logger
-
-    def __init__(self, *, app_name: str, func: Callable[..., bool], base_logger: Optional[Logger] = None):
-        self.app_name = app_name
-        self.func = func
-        self.arg_names = get_arg_names_of_callable(func)
-        self.logger = get_bolt_app_logger(self.app_name, self.func, base_logger)
-
-    def matches(self, req: BoltRequest, resp: BoltResponse) -> bool:
-        return self.func(
-            **build_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,
-                request=req,
-                response=resp,
-                this_func=self.func,
-            )
-        )
-
-
-

Ancestors

- -

Class variables

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : MutableSequence[str]
-
-

The type of the None singleton.

-
-
var func : Callable[..., bool]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/listener_matcher/index.html b/docs/reference/listener_matcher/index.html deleted file mode 100644 index a93c86d98..000000000 --- a/docs/reference/listener_matcher/index.html +++ /dev/null @@ -1,253 +0,0 @@ - - - - - - -slack_bolt.listener_matcher API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener_matcher

-
-
-

A listener matcher is a simplified version of listener middleware. -A listener matcher function returns bool value instead of next() method invocation inside. -This interface enables developers to utilize simple predicate functions for additional listener conditions.

-
-
-

Sub-modules

-
-
slack_bolt.listener_matcher.async_builtins
-
-
-
-
slack_bolt.listener_matcher.async_listener_matcher
-
-
-
-
slack_bolt.listener_matcher.builtins
-
-
-
-
slack_bolt.listener_matcher.custom_listener_matcher
-
-
-
-
slack_bolt.listener_matcher.listener_matcher
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class CustomListenerMatcher -(*,
app_name: str,
func: Callable[..., bool],
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class CustomListenerMatcher(ListenerMatcher):
-    app_name: str
-    func: Callable[..., bool]
-    arg_names: MutableSequence[str]
-    logger: Logger
-
-    def __init__(self, *, app_name: str, func: Callable[..., bool], base_logger: Optional[Logger] = None):
-        self.app_name = app_name
-        self.func = func
-        self.arg_names = get_arg_names_of_callable(func)
-        self.logger = get_bolt_app_logger(self.app_name, self.func, base_logger)
-
-    def matches(self, req: BoltRequest, resp: BoltResponse) -> bool:
-        return self.func(
-            **build_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,
-                request=req,
-                response=resp,
-                this_func=self.func,
-            )
-        )
-
-
-

Ancestors

- -

Class variables

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : MutableSequence[str]
-
-

The type of the None singleton.

-
-
var func : Callable[..., bool]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class ListenerMatcher -
-
-
- -Expand source code - -
class ListenerMatcher(metaclass=ABCMeta):
-    @abstractmethod
-    def matches(self, req: BoltRequest, resp: BoltResponse) -> bool:
-        """Matches against the request and returns True if matched.
-
-        Args:
-            req: The request
-            resp: The response
-
-        Returns:
-            True if matched.
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-def matches(self,
req: BoltRequest,
resp: BoltResponse) ‑> bool
-
-
-
- -Expand source code - -
@abstractmethod
-def matches(self, req: BoltRequest, resp: BoltResponse) -> bool:
-    """Matches against the request and returns True if matched.
-
-    Args:
-        req: The request
-        resp: The response
-
-    Returns:
-        True if matched.
-    """
-    raise NotImplementedError()
-
-

Matches against the request and returns True if matched.

-

Args

-
-
req
-
The request
-
resp
-
The response
-
-

Returns

-

True if matched.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/listener_matcher/listener_matcher.html b/docs/reference/listener_matcher/listener_matcher.html deleted file mode 100644 index 0618f7e4e..000000000 --- a/docs/reference/listener_matcher/listener_matcher.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - -slack_bolt.listener_matcher.listener_matcher API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.listener_matcher.listener_matcher

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class ListenerMatcher -
-
-
- -Expand source code - -
class ListenerMatcher(metaclass=ABCMeta):
-    @abstractmethod
-    def matches(self, req: BoltRequest, resp: BoltResponse) -> bool:
-        """Matches against the request and returns True if matched.
-
-        Args:
-            req: The request
-            resp: The response
-
-        Returns:
-            True if matched.
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-def matches(self,
req: BoltRequest,
resp: BoltResponse) ‑> bool
-
-
-
- -Expand source code - -
@abstractmethod
-def matches(self, req: BoltRequest, resp: BoltResponse) -> bool:
-    """Matches against the request and returns True if matched.
-
-    Args:
-        req: The request
-        resp: The response
-
-    Returns:
-        True if matched.
-    """
-    raise NotImplementedError()
-
-

Matches against the request and returns True if matched.

-

Args

-
-
req
-
The request
-
resp
-
The response
-
-

Returns

-

True if matched.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/logger/index.html b/docs/reference/logger/index.html deleted file mode 100644 index d0b2ef33f..000000000 --- a/docs/reference/logger/index.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - -slack_bolt.logger API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.logger

-
-
-

Bolt for Python relies on the standard logging module.

-
-
-

Sub-modules

-
-
slack_bolt.logger.messages
-
-
-
-
-
-
-
-
-

Functions

-
-
-def get_bolt_app_logger(app_name: str, cls: object = None, base_logger: logging.Logger | None = None) ‑> logging.Logger -
-
-
- -Expand source code - -
def get_bolt_app_logger(app_name: str, cls: object = None, base_logger: Optional[Logger] = None) -> Logger:
-    logger: Logger = (
-        logging.getLogger(f"{app_name}:{cls.__name__}") if cls and hasattr(cls, "__name__") else logging.getLogger(app_name)
-    )
-
-    if base_logger is not None:
-        _configure_from_base_logger(logger, base_logger)
-    else:
-        _configure_from_root(logger)
-    return logger
-
-
-
-
-def get_bolt_logger(cls: Any, base_logger: logging.Logger | None = None) ‑> logging.Logger -
-
-
- -Expand source code - -
def get_bolt_logger(cls: Any, base_logger: Optional[Logger] = None) -> Logger:
-    logger = logging.getLogger(f"slack_bolt.{cls.__name__}")
-    if base_logger is not None:
-        _configure_from_base_logger(logger, base_logger)
-    else:
-        _configure_from_root(logger)
-    return logger
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/logger/messages.html b/docs/reference/logger/messages.html deleted file mode 100644 index e69b45fc9..000000000 --- a/docs/reference/logger/messages.html +++ /dev/null @@ -1,626 +0,0 @@ - - - - - - -slack_bolt.logger.messages API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.logger.messages

-
-
-
-
-
-
-
-
-

Functions

-
-
-def debug_applying_middleware(middleware_name: str) ‑> str -
-
-
- -Expand source code - -
def debug_applying_middleware(middleware_name: str) -> str:
-    return f"Applying {middleware_name}"
-
-
-
-
-def debug_checking_listener(listener_name: str) ‑> str -
-
-
- -Expand source code - -
def debug_checking_listener(listener_name: str) -> str:
-    return f"Checking listener: {listener_name} ..."
-
-
-
-
-def debug_responding(status: int, body: str, millis: int) ‑> str -
-
-
- -Expand source code - -
def debug_responding(status: int, body: str, millis: int) -> str:
-    return f'Responding with status: {status} body: "{body}" ({millis} millis)'
-
-
-
-
-def debug_return_listener_middleware_response(listener_name: str, status: int, body: str, starting_time: float) ‑> str -
-
-
- -Expand source code - -
def debug_return_listener_middleware_response(listener_name: str, status: int, body: str, starting_time: float) -> str:
-    millis = int((time.time() - starting_time) * 1000)
-    return (
-        "Responding with listener middleware's response - "
-        f"listener: {listener_name}, status: {status}, body: {body} ({millis} millis)"
-    )
-
-
-
-
-def debug_running_lazy_listener(func_name: str) ‑> str -
-
-
- -Expand source code - -
def debug_running_lazy_listener(func_name: str) -> str:
-    return f"Running lazy listener: {func_name} ..."
-
-
-
-
-def debug_running_listener(listener_name: str) ‑> str -
-
-
- -Expand source code - -
def debug_running_listener(listener_name: str) -> str:
-    return f"Running listener: {listener_name} ..."
-
-
-
-
-def error_auth_test_failure(error_response: slack_sdk.web.slack_response.SlackResponse) ‑> str -
-
-
- -Expand source code - -
def error_auth_test_failure(error_response: SlackResponse) -> str:
-    return f"`token` is invalid (auth.test result: {error_response})"
-
-
-
-
-def error_authorize_conflicts() ‑> str -
-
-
- -Expand source code - -
def error_authorize_conflicts() -> str:
-    return "`authorize` in the top-level arguments is not allowed when you pass either `oauth_settings` or `oauth_flow`"
-
-
-
-
-def error_client_invalid_type() ‑> str -
-
-
- -Expand source code - -
def error_client_invalid_type() -> str:
-    return "`client` must be a slack_sdk.web.WebClient"
-
-
-
-
-def error_client_invalid_type_async() ‑> str -
-
-
- -Expand source code - -
def error_client_invalid_type_async() -> str:
-    return "`client` must be a slack_sdk.web.async_client.AsyncWebClient"
-
-
-
-
-def error_installation_store_required_for_builtin_listeners() ‑> str -
-
-
- -Expand source code - -
def error_installation_store_required_for_builtin_listeners() -> str:
-    return (
-        "To use the event listeners for token revocation handling, "
-        "setting a valid `installation_store` to `App`/`AsyncApp` is required."
-    )
-
-
-
-
-def error_listener_function_must_be_coro_func(func_name: str) ‑> str -
-
-
- -Expand source code - -
def error_listener_function_must_be_coro_func(func_name: str) -> str:
-    return f"The listener function ({func_name}) is not a coroutine function."
-
-
-
-
-def error_message_event_type(event_type: str | re.Pattern) ‑> str -
-
-
- -Expand source code - -
def error_message_event_type(event_type: Union[str, Pattern]) -> str:
-    return (
-        f'Although the document mentions "{event_type}", '
-        'it is not a valid event type. Use "message" instead. '
-        "If you want to filter message events, you can use `event.channel_type` for it."
-    )
-
-
-
-
-def error_oauth_flow_invalid_type_async() ‑> str -
-
-
- -Expand source code - -
def error_oauth_flow_invalid_type_async() -> str:
-    return "`oauth_flow` must be a slack_bolt.oauth.async_oauth_flow.AsyncOAuthFlow"
-
-
-
-
-def error_oauth_flow_or_authorize_required() ‑> str -
-
-
- -Expand source code - -
def error_oauth_flow_or_authorize_required() -> str:
-    return "`oauth_flow` or `authorize` must be configured to make a Bolt app"
-
-
-
-
-def error_oauth_settings_invalid_type_async() ‑> str -
-
-
- -Expand source code - -
def error_oauth_settings_invalid_type_async() -> str:
-    return "`oauth_settings` must be a slack_bolt.oauth.async_oauth_settings.AsyncOAuthSettings"
-
-
-
-
-def error_token_required() ‑> str -
-
-
- -Expand source code - -
def error_token_required() -> str:
-    return "Either an env variable `SLACK_BOT_TOKEN` " "or `token` argument in the constructor is required."
-
-
-
-
-def error_unexpected_listener_middleware(middleware_type) ‑> str -
-
-
- -Expand source code - -
def error_unexpected_listener_middleware(middleware_type) -> str:
-    return f"Unexpected value for a listener middleware: {middleware_type}"
-
-
-
-
-def info_default_oauth_settings_loaded() ‑> str -
-
-
- -Expand source code - -
def info_default_oauth_settings_loaded() -> str:
-    return (
-        "As you've set SLACK_CLIENT_ID and SLACK_CLIENT_SECRET env variables, "
-        "Bolt has enabled the file-based InstallationStore/OAuthStateStore for you. "
-        "Note that these file-based stores are for local development. "
-        "If you'd like to use a different data store, set the oauth_settings argument in the App constructor. "
-        "Please refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth for more details."
-    )
-
-
-
-
-def warning_ack_timeout_has_no_effect(identifier: str | re.Pattern, ack_timeout: int) ‑> str -
-
-
- -Expand source code - -
def warning_ack_timeout_has_no_effect(identifier: Union[str, Pattern], ack_timeout: int) -> str:
-    handler_example = f'@app.function("{identifier}")' if isinstance(identifier, str) else f"@app.function({identifier})"
-    return f"On {handler_example}, as `auto_acknowledge` is `True`, " f"`ack_timeout={ack_timeout}` you gave will be unused"
-
-
-
-
-def warning_bot_only_conflicts() ‑> str -
-
-
- -Expand source code - -
def warning_bot_only_conflicts() -> str:
-    return (
-        "installation_store_bot_only exists in both App and OAuthFlow.settings. "
-        "The one passed in App constructor is used."
-    )
-
-
-
-
-def warning_client_prioritized_and_token_skipped() ‑> str -
-
-
- -Expand source code - -
def warning_client_prioritized_and_token_skipped() -> str:
-    return "As you gave `client` as well, `token` will be unused."
-
-
-
-
-def warning_did_not_call_ack(listener_name: str) ‑> str -
-
-
- -Expand source code - -
def warning_did_not_call_ack(listener_name: str) -> str:
-    return f"{listener_name} didn't call ack()"
-
-
-
-
-def warning_installation_store_conflicts() ‑> str -
-
-
- -Expand source code - -
def warning_installation_store_conflicts() -> str:
-    return "As you gave both `installation_store` and `oauth_settings`/`auth_flow`, the top level one is unused."
-
-
-
-
-def warning_skip_uncommon_arg_name(arg_name: str) ‑> str -
-
-
- -Expand source code - -
def warning_skip_uncommon_arg_name(arg_name: str) -> str:
-    return (
-        f"Bolt skips injecting a value to the first keyword argument ({arg_name}). "
-        "If it is self/cls of a method, we recommend using the common names."
-    )
-
-
-
-
-def warning_token_skipped() ‑> str -
-
-
- -Expand source code - -
def warning_token_skipped() -> str:
-    return (
-        "As `installation_store` or `authorize` has been used, " "`token` (or SLACK_BOT_TOKEN env variable) will be ignored."
-    )
-
-
-
-
-def warning_unhandled_by_global_middleware(name: str,
req: BoltRequest | AsyncBoltRequest) ‑> str
-
-
-
- -Expand source code - -
def warning_unhandled_by_global_middleware(
-    name: str, req: Union[BoltRequest, "AsyncBoltRequest"]  # type: ignore[name-defined]
-) -> str:
-    return (
-        f"A global middleware ({name}) skipped calling either `next()` or `next_()` "
-        f"without providing a response for the request ({req.body})"
-    )
-
-
-
-
-def warning_unhandled_request(req: BoltRequest | AsyncBoltRequest) ‑> str -
-
-
- -Expand source code - -
def warning_unhandled_request(
-    req: Union[BoltRequest, "AsyncBoltRequest"],  # type: ignore[name-defined]
-) -> str:
-    filtered_body = _build_filtered_body(req.body)
-    default_message = f"Unhandled request ({filtered_body})"
-    is_async = not isinstance(req, BoltRequest)
-    if is_workflow_step_edit(req.body) or is_workflow_step_save(req.body) or is_workflow_step_execute(req.body):
-        # @app.step
-        callback_id = (
-            filtered_body.get("callback_id") or filtered_body.get("view", {}).get("callback_id") or "your-callback-id"
-        )
-        return _build_unhandled_request_suggestion(
-            default_message,
-            f"""
-from slack_bolt.workflows.step{'.async_step' if is_async else ''} import {'Async' if is_async else ''}WorkflowStep
-ws = {'Async' if is_async else ''}WorkflowStep(
-    callback_id="{callback_id}",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-# Pass Step to set up listeners
-app.step(ws)
-""",
-        )
-    if is_action(req.body):
-        # @app.action
-        action_id_or_callback_id = req.body.get("callback_id")
-        if req.body.get("type") == "block_actions":
-            action_id_or_callback_id = req.body["actions"][0].get("action_id")
-        return _build_unhandled_request_suggestion(
-            default_message,
-            f"""
-@app.action("{action_id_or_callback_id}")
-{'async ' if is_async else ''}def handle_some_action(ack, body, logger):
-    {'await ' if is_async else ''}ack()
-    logger.info(body)
-""",
-        )
-    if is_options(req.body):
-        # @app.options
-        constraints = '"action-id"'
-        if req.body.get("action_id") is not None:
-            constraints = '"' + req.body["action_id"] + '"'
-        elif req.body.get("type") == "dialog_suggestion":
-            constraints = f"""{{"type": "dialog_suggestion", "callback_id": "{req.body.get('callback_id')}"}}"""
-        return _build_unhandled_request_suggestion(
-            default_message,
-            f"""
-@app.options({constraints})
-{'async ' if is_async else ''}def handle_some_options(ack):
-    {'await ' if is_async else ''}ack(options=[ ... ])
-""",
-        )
-    if is_shortcut(req.body):
-        # @app.shortcut
-        id = req.body.get("action_id") or req.body.get("callback_id")
-        return _build_unhandled_request_suggestion(
-            default_message,
-            f"""
-@app.shortcut("{id}")
-{'async ' if is_async else ''}def handle_shortcuts(ack, body, logger):
-    {'await ' if is_async else ''}ack()
-    logger.info(body)
-""",
-        )
-    if is_view_submission(req.body):
-        # @app.view
-        return _build_unhandled_request_suggestion(
-            default_message,
-            f"""
-@app.view("{req.body.get('view', {}).get('callback_id', 'modal-view-id')}")
-{'async ' if is_async else ''}def handle_view_submission_events(ack, body, logger):
-    {'await ' if is_async else ''}ack()
-    logger.info(body)
-""",
-        )
-    if is_view_closed(req.body):
-        # @app.view
-        return _build_unhandled_request_suggestion(
-            default_message,
-            f"""
-@app.view_closed("{req.body.get('view', {}).get('callback_id', 'modal-view-id')}")
-{'async ' if is_async else ''}def handle_view_closed_events(ack, body, logger):
-    {'await ' if is_async else ''}ack()
-    logger.info(body)
-""",
-        )
-    if is_event(req.body):
-        # @app.event
-        event = req.body.get("event", {})
-        event_type = event.get("type")
-        if is_function(req.body):
-            # @app.function
-            callback_id = event.get("function", {}).get("callback_id", "function_id")
-            return _build_unhandled_request_suggestion(
-                default_message,
-                f"""
-@app.function("{callback_id}")
-{'async ' if is_async else ''}def handle_some_function(ack, body, complete, fail, logger):
-    {'await ' if is_async else ''}ack()
-    logger.info(body)
-    try:
-        # TODO: do something here
-        outputs = {{}}
-        {'await ' if is_async else ''}complete(outputs=outputs)
-    except Exception as e:
-        error = f"Failed to handle a function request (error: {{e}})"
-        {'await ' if is_async else ''}fail(error=error)
-""",
-            )
-        return _build_unhandled_request_suggestion(
-            default_message,
-            f"""
-@app.event("{event_type}")
-{'async ' if is_async else ''}def handle_{event_type}_events(body, logger):
-    logger.info(body)
-""",
-        )
-    if is_slash_command(req.body):
-        # @app.command
-        command = req.body.get("command", "/your-command")
-        return _build_unhandled_request_suggestion(
-            default_message,
-            f"""
-@app.command("{command}")
-{'async ' if is_async else ''}def handle_some_command(ack, body, logger):
-    {'await ' if is_async else ''}ack()
-    logger.info(body)
-""",
-        )
-    return default_message
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/middleware/assistant/assistant.html b/docs/reference/middleware/assistant/assistant.html deleted file mode 100644 index 946416d62..000000000 --- a/docs/reference/middleware/assistant/assistant.html +++ /dev/null @@ -1,664 +0,0 @@ - - - - - - -slack_bolt.middleware.assistant.assistant API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.assistant.assistant

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Assistant -(*,
app_name: str = 'assistant',
thread_context_store: AssistantThreadContextStore | None = None,
logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class Assistant(Middleware):
-    _thread_started_listeners: Optional[List[Listener]]
-    _thread_context_changed_listeners: Optional[List[Listener]]
-    _user_message_listeners: Optional[List[Listener]]
-    _bot_message_listeners: Optional[List[Listener]]
-
-    thread_context_store: Optional[AssistantThreadContextStore]
-    base_logger: Optional[logging.Logger]
-
-    def __init__(
-        self,
-        *,
-        app_name: str = "assistant",
-        thread_context_store: Optional[AssistantThreadContextStore] = None,
-        logger: Optional[logging.Logger] = None,
-    ):
-        self.app_name = app_name
-        self.thread_context_store = thread_context_store
-        self.base_logger = logger
-
-        self._thread_started_listeners = None
-        self._thread_context_changed_listeners = None
-        self._user_message_listeners = None
-        self._bot_message_listeners = None
-
-    def thread_started(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._thread_started_listeners is None:
-            self._thread_started_listeners = []
-        all_matchers = self._merge_matchers(is_assistant_thread_started_event, matchers)
-        if is_used_without_argument(args):
-            func = args[0]
-            self._thread_started_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._thread_started_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def user_message(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._user_message_listeners is None:
-            self._user_message_listeners = []
-        all_matchers = self._merge_matchers(is_user_message_event_in_assistant_thread, matchers)
-        if is_used_without_argument(args):
-            func = args[0]
-            self._user_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._user_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def bot_message(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._bot_message_listeners is None:
-            self._bot_message_listeners = []
-        all_matchers = self._merge_matchers(is_bot_message_event_in_assistant_thread, matchers)
-        if is_used_without_argument(args):
-            func = args[0]
-            self._bot_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._bot_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def thread_context_changed(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._thread_context_changed_listeners is None:
-            self._thread_context_changed_listeners = []
-        all_matchers = self._merge_matchers(is_assistant_thread_context_changed_event, matchers)
-        if is_used_without_argument(args):
-            func = args[0]
-            self._thread_context_changed_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._thread_context_changed_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def _merge_matchers(
-        self,
-        primary_matcher: Callable[..., bool],
-        custom_matchers: Optional[Union[Callable[..., bool], ListenerMatcher]],
-    ):
-        return [CustomListenerMatcher(app_name=self.app_name, func=primary_matcher)] + (
-            custom_matchers or []
-        )  # type: ignore[operator]
-
-    @staticmethod
-    def default_thread_context_changed(save_thread_context: SaveThreadContext, payload: dict):
-        save_thread_context(payload["assistant_thread"]["context"])
-
-    def process(  # type: ignore[return]
-        self, *, req: BoltRequest, resp: BoltResponse, next: Callable[[], BoltResponse]
-    ) -> Optional[BoltResponse]:
-        if self._thread_context_changed_listeners is None:
-            self.thread_context_changed(self.default_thread_context_changed)
-
-        listener_runner: ThreadListenerRunner = req.context.listener_runner
-        for listeners in [
-            self._thread_started_listeners,
-            self._thread_context_changed_listeners,
-            self._user_message_listeners,
-            self._bot_message_listeners,
-        ]:
-            if listeners is not None:
-                for listener in listeners:
-                    if listener.matches(req=req, resp=resp):
-                        middleware_resp, next_was_not_called = listener.run_middleware(req=req, resp=resp)
-                        if next_was_not_called:
-                            if middleware_resp is not None:
-                                return middleware_resp
-                            # The listener middleware didn't call next().
-                            # Skip this listener and try the next one.
-                            continue
-                        if middleware_resp is not None:
-                            resp = middleware_resp
-                        return listener_runner.run(
-                            request=req,
-                            response=resp,
-                            listener_name="assistant_listener",
-                            listener=listener,
-                        )
-        if is_other_message_sub_event_in_assistant_thread(req.body):
-            # message_changed, message_deleted, etc.
-            return req.context.ack()
-
-        next()
-
-    def build_listener(
-        self,
-        listener_or_functions: Union[Listener, Callable, List[Callable]],
-        matchers: Optional[List[Union[ListenerMatcher, Callable[..., bool]]]] = None,
-        middleware: Optional[List[Middleware]] = None,
-        base_logger: Optional[Logger] = None,
-    ) -> Listener:
-        if isinstance(listener_or_functions, Callable):  # type: ignore[arg-type]
-            listener_or_functions = [listener_or_functions]  # type: ignore[list-item]
-
-        if isinstance(listener_or_functions, Listener):
-            return listener_or_functions
-        elif isinstance(listener_or_functions, list):
-            middleware = middleware if middleware else []
-            middleware.insert(0, AttachingConversationKwargs(self.thread_context_store))
-            functions = listener_or_functions
-            ack_function = functions.pop(0)
-
-            matchers = matchers if matchers else []
-            listener_matchers: List[ListenerMatcher] = []
-            for matcher in matchers:
-                if isinstance(matcher, ListenerMatcher):
-                    listener_matchers.append(matcher)
-                elif isinstance(matcher, Callable):  # type: ignore[arg-type]
-                    listener_matchers.append(
-                        build_listener_matcher(
-                            func=matcher,
-                            asyncio=False,
-                            base_logger=base_logger,
-                        )
-                    )
-            return CustomListener(
-                app_name=self.app_name,
-                matchers=listener_matchers,
-                middleware=middleware,
-                ack_function=ack_function,
-                lazy_functions=functions,
-                auto_acknowledgement=True,
-                base_logger=base_logger or self.base_logger,
-            )
-        else:
-            raise BoltError(f"Invalid listener: {type(listener_or_functions)} detected")
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var base_logger : logging.Logger | None
-
-

The type of the None singleton.

-
-
var thread_context_storeAssistantThreadContextStore | None
-
-

The type of the None singleton.

-
-
-

Static methods

-
-
-def default_thread_context_changed(save_thread_context: SaveThreadContext,
payload: dict)
-
-
-
- -Expand source code - -
@staticmethod
-def default_thread_context_changed(save_thread_context: SaveThreadContext, payload: dict):
-    save_thread_context(payload["assistant_thread"]["context"])
-
-
-
-
-

Methods

-
-
-def bot_message(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def bot_message(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._bot_message_listeners is None:
-        self._bot_message_listeners = []
-    all_matchers = self._merge_matchers(is_bot_message_event_in_assistant_thread, matchers)
-    if is_used_without_argument(args):
-        func = args[0]
-        self._bot_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._bot_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def build_listener(self,
listener_or_functions: Listener | Callable | List[Callable],
matchers: List[ListenerMatcher | Callable[..., bool]] | None = None,
middleware: List[Middleware] | None = None,
base_logger: logging.Logger | None = None) ‑> Listener
-
-
-
- -Expand source code - -
def build_listener(
-    self,
-    listener_or_functions: Union[Listener, Callable, List[Callable]],
-    matchers: Optional[List[Union[ListenerMatcher, Callable[..., bool]]]] = None,
-    middleware: Optional[List[Middleware]] = None,
-    base_logger: Optional[Logger] = None,
-) -> Listener:
-    if isinstance(listener_or_functions, Callable):  # type: ignore[arg-type]
-        listener_or_functions = [listener_or_functions]  # type: ignore[list-item]
-
-    if isinstance(listener_or_functions, Listener):
-        return listener_or_functions
-    elif isinstance(listener_or_functions, list):
-        middleware = middleware if middleware else []
-        middleware.insert(0, AttachingConversationKwargs(self.thread_context_store))
-        functions = listener_or_functions
-        ack_function = functions.pop(0)
-
-        matchers = matchers if matchers else []
-        listener_matchers: List[ListenerMatcher] = []
-        for matcher in matchers:
-            if isinstance(matcher, ListenerMatcher):
-                listener_matchers.append(matcher)
-            elif isinstance(matcher, Callable):  # type: ignore[arg-type]
-                listener_matchers.append(
-                    build_listener_matcher(
-                        func=matcher,
-                        asyncio=False,
-                        base_logger=base_logger,
-                    )
-                )
-        return CustomListener(
-            app_name=self.app_name,
-            matchers=listener_matchers,
-            middleware=middleware,
-            ack_function=ack_function,
-            lazy_functions=functions,
-            auto_acknowledgement=True,
-            base_logger=base_logger or self.base_logger,
-        )
-    else:
-        raise BoltError(f"Invalid listener: {type(listener_or_functions)} detected")
-
-
-
-
-def thread_context_changed(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def thread_context_changed(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._thread_context_changed_listeners is None:
-        self._thread_context_changed_listeners = []
-    all_matchers = self._merge_matchers(is_assistant_thread_context_changed_event, matchers)
-    if is_used_without_argument(args):
-        func = args[0]
-        self._thread_context_changed_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._thread_context_changed_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def thread_started(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def thread_started(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._thread_started_listeners is None:
-        self._thread_started_listeners = []
-    all_matchers = self._merge_matchers(is_assistant_thread_started_event, matchers)
-    if is_used_without_argument(args):
-        func = args[0]
-        self._thread_started_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._thread_started_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def user_message(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def user_message(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._user_message_listeners is None:
-        self._user_message_listeners = []
-    all_matchers = self._merge_matchers(is_user_message_event_in_assistant_thread, matchers)
-    if is_used_without_argument(args):
-        func = args[0]
-        self._user_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._user_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/assistant/async_assistant.html b/docs/reference/middleware/assistant/async_assistant.html deleted file mode 100644 index 748be2cbf..000000000 --- a/docs/reference/middleware/assistant/async_assistant.html +++ /dev/null @@ -1,724 +0,0 @@ - - - - - - -slack_bolt.middleware.assistant.async_assistant API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.assistant.async_assistant

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncAssistant -(*,
app_name: str = 'assistant',
thread_context_store: AsyncAssistantThreadContextStore | None = None,
logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncAssistant(AsyncMiddleware):
-    _thread_started_listeners: Optional[List[AsyncListener]]
-    _user_message_listeners: Optional[List[AsyncListener]]
-    _bot_message_listeners: Optional[List[AsyncListener]]
-    _thread_context_changed_listeners: Optional[List[AsyncListener]]
-
-    thread_context_store: Optional[AsyncAssistantThreadContextStore]
-    base_logger: Optional[logging.Logger]
-
-    def __init__(
-        self,
-        *,
-        app_name: str = "assistant",
-        thread_context_store: Optional[AsyncAssistantThreadContextStore] = None,
-        logger: Optional[logging.Logger] = None,
-    ):
-        self.app_name = app_name
-        self.thread_context_store = thread_context_store
-        self.base_logger = logger
-
-        self._thread_started_listeners = None
-        self._thread_context_changed_listeners = None
-        self._user_message_listeners = None
-        self._bot_message_listeners = None
-
-    def thread_started(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._thread_started_listeners is None:
-            self._thread_started_listeners = []
-        all_matchers = self._merge_matchers(
-            build_listener_matcher(
-                func=is_assistant_thread_started_event,
-                asyncio=True,
-                base_logger=self.base_logger,
-            ),  # type: ignore[arg-type]
-            matchers,
-        )
-        if is_used_without_argument(args):
-            func = args[0]
-            self._thread_started_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._thread_started_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def user_message(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._user_message_listeners is None:
-            self._user_message_listeners = []
-        all_matchers = self._merge_matchers(
-            build_listener_matcher(
-                func=is_user_message_event_in_assistant_thread,
-                asyncio=True,
-                base_logger=self.base_logger,
-            ),  # type: ignore[arg-type]
-            matchers,
-        )
-        if is_used_without_argument(args):
-            func = args[0]
-            self._user_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._user_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def bot_message(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._bot_message_listeners is None:
-            self._bot_message_listeners = []
-        all_matchers = self._merge_matchers(
-            build_listener_matcher(
-                func=is_bot_message_event_in_assistant_thread,
-                asyncio=True,
-                base_logger=self.base_logger,
-            ),  # type: ignore[arg-type]
-            matchers,
-        )
-        if is_used_without_argument(args):
-            func = args[0]
-            self._bot_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._bot_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def thread_context_changed(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._thread_context_changed_listeners is None:
-            self._thread_context_changed_listeners = []
-        all_matchers = self._merge_matchers(
-            build_listener_matcher(
-                func=is_assistant_thread_context_changed_event,
-                asyncio=True,
-                base_logger=self.base_logger,
-            ),  # type: ignore[arg-type]
-            matchers,
-        )
-        if is_used_without_argument(args):
-            func = args[0]
-            self._thread_context_changed_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._thread_context_changed_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    @staticmethod
-    def _merge_matchers(
-        primary_matcher: Union[Callable[..., bool], AsyncListenerMatcher],
-        custom_matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]],
-    ):
-        return [primary_matcher] + (custom_matchers or [])  # type: ignore[operator]
-
-    @staticmethod
-    async def default_thread_context_changed(save_thread_context: AsyncSaveThreadContext, payload: dict):
-        new_context: dict = payload["assistant_thread"]["context"]
-        await save_thread_context(new_context)
-
-    async def async_process(  # type: ignore[return]
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> Optional[BoltResponse]:
-        if self._thread_context_changed_listeners is None:
-            self.thread_context_changed(self.default_thread_context_changed)
-
-        listener_runner: AsyncioListenerRunner = req.context.listener_runner
-        for listeners in [
-            self._thread_started_listeners,
-            self._thread_context_changed_listeners,
-            self._user_message_listeners,
-            self._bot_message_listeners,
-        ]:
-            if listeners is not None:
-                for listener in listeners:
-                    if listener is not None and await listener.async_matches(req=req, resp=resp):
-                        middleware_resp, next_was_not_called = await listener.run_async_middleware(req=req, resp=resp)
-                        if next_was_not_called:
-                            if middleware_resp is not None:
-                                return middleware_resp
-                            # The listener middleware didn't call next().
-                            # Skip this listener and try the next one.
-                            continue
-                        if middleware_resp is not None:
-                            resp = middleware_resp
-                        return await listener_runner.run(
-                            request=req,
-                            response=resp,
-                            listener_name="assistant_listener",
-                            listener=listener,
-                        )
-        if is_other_message_sub_event_in_assistant_thread(req.body):
-            # message_changed, message_deleted, etc.
-            return await req.context.ack()
-
-        await next()
-
-    def build_listener(
-        self,
-        listener_or_functions: Union[AsyncListener, Callable, List[Callable]],
-        matchers: Optional[List[Union[AsyncListenerMatcher, Callable[..., Awaitable[bool]]]]] = None,
-        middleware: Optional[List[AsyncMiddleware]] = None,
-        base_logger: Optional[Logger] = None,
-    ) -> AsyncListener:
-        if isinstance(listener_or_functions, Callable):  # type: ignore[arg-type]
-            listener_or_functions = [listener_or_functions]  # type: ignore[list-item]
-
-        if isinstance(listener_or_functions, AsyncListener):
-            return listener_or_functions
-        elif isinstance(listener_or_functions, list):
-            middleware = middleware if middleware else []
-            middleware.insert(0, AsyncAttachingConversationKwargs(self.thread_context_store))
-            functions = listener_or_functions
-            ack_function = functions.pop(0)
-
-            matchers = matchers if matchers else []
-            listener_matchers: List[AsyncListenerMatcher] = []
-            for matcher in matchers:
-                if isinstance(matcher, AsyncListenerMatcher):
-                    listener_matchers.append(matcher)
-                else:
-                    listener_matchers.append(
-                        build_listener_matcher(
-                            func=matcher,  # type: ignore[arg-type]
-                            asyncio=True,
-                            base_logger=base_logger,
-                        )
-                    )
-            return AsyncCustomListener(
-                app_name=self.app_name,
-                matchers=listener_matchers,
-                middleware=middleware,
-                ack_function=ack_function,
-                lazy_functions=functions,
-                auto_acknowledgement=True,
-                base_logger=base_logger or self.base_logger,
-            )
-        else:
-            raise BoltError(f"Invalid listener: {type(listener_or_functions)} detected")
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var base_logger : logging.Logger | None
-
-

The type of the None singleton.

-
-
var thread_context_storeAsyncAssistantThreadContextStore | None
-
-

The type of the None singleton.

-
-
-

Static methods

-
-
-async def default_thread_context_changed(save_thread_context: AsyncSaveThreadContext,
payload: dict)
-
-
-
- -Expand source code - -
@staticmethod
-async def default_thread_context_changed(save_thread_context: AsyncSaveThreadContext, payload: dict):
-    new_context: dict = payload["assistant_thread"]["context"]
-    await save_thread_context(new_context)
-
-
-
-
-

Methods

-
-
-def bot_message(self,
*args,
matchers: Callable[..., bool] | AsyncListenerMatcher | None = None,
middleware: Callable | AsyncMiddleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def bot_message(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._bot_message_listeners is None:
-        self._bot_message_listeners = []
-    all_matchers = self._merge_matchers(
-        build_listener_matcher(
-            func=is_bot_message_event_in_assistant_thread,
-            asyncio=True,
-            base_logger=self.base_logger,
-        ),  # type: ignore[arg-type]
-        matchers,
-    )
-    if is_used_without_argument(args):
-        func = args[0]
-        self._bot_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._bot_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def build_listener(self,
listener_or_functions: AsyncListener | Callable | List[Callable],
matchers: List[AsyncListenerMatcher | Callable[..., Awaitable[bool]]] | None = None,
middleware: List[AsyncMiddleware] | None = None,
base_logger: logging.Logger | None = None) ‑> AsyncListener
-
-
-
- -Expand source code - -
def build_listener(
-    self,
-    listener_or_functions: Union[AsyncListener, Callable, List[Callable]],
-    matchers: Optional[List[Union[AsyncListenerMatcher, Callable[..., Awaitable[bool]]]]] = None,
-    middleware: Optional[List[AsyncMiddleware]] = None,
-    base_logger: Optional[Logger] = None,
-) -> AsyncListener:
-    if isinstance(listener_or_functions, Callable):  # type: ignore[arg-type]
-        listener_or_functions = [listener_or_functions]  # type: ignore[list-item]
-
-    if isinstance(listener_or_functions, AsyncListener):
-        return listener_or_functions
-    elif isinstance(listener_or_functions, list):
-        middleware = middleware if middleware else []
-        middleware.insert(0, AsyncAttachingConversationKwargs(self.thread_context_store))
-        functions = listener_or_functions
-        ack_function = functions.pop(0)
-
-        matchers = matchers if matchers else []
-        listener_matchers: List[AsyncListenerMatcher] = []
-        for matcher in matchers:
-            if isinstance(matcher, AsyncListenerMatcher):
-                listener_matchers.append(matcher)
-            else:
-                listener_matchers.append(
-                    build_listener_matcher(
-                        func=matcher,  # type: ignore[arg-type]
-                        asyncio=True,
-                        base_logger=base_logger,
-                    )
-                )
-        return AsyncCustomListener(
-            app_name=self.app_name,
-            matchers=listener_matchers,
-            middleware=middleware,
-            ack_function=ack_function,
-            lazy_functions=functions,
-            auto_acknowledgement=True,
-            base_logger=base_logger or self.base_logger,
-        )
-    else:
-        raise BoltError(f"Invalid listener: {type(listener_or_functions)} detected")
-
-
-
-
-def thread_context_changed(self,
*args,
matchers: Callable[..., bool] | AsyncListenerMatcher | None = None,
middleware: Callable | AsyncMiddleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def thread_context_changed(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._thread_context_changed_listeners is None:
-        self._thread_context_changed_listeners = []
-    all_matchers = self._merge_matchers(
-        build_listener_matcher(
-            func=is_assistant_thread_context_changed_event,
-            asyncio=True,
-            base_logger=self.base_logger,
-        ),  # type: ignore[arg-type]
-        matchers,
-    )
-    if is_used_without_argument(args):
-        func = args[0]
-        self._thread_context_changed_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._thread_context_changed_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def thread_started(self,
*args,
matchers: Callable[..., bool] | AsyncListenerMatcher | None = None,
middleware: Callable | AsyncMiddleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def thread_started(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._thread_started_listeners is None:
-        self._thread_started_listeners = []
-    all_matchers = self._merge_matchers(
-        build_listener_matcher(
-            func=is_assistant_thread_started_event,
-            asyncio=True,
-            base_logger=self.base_logger,
-        ),  # type: ignore[arg-type]
-        matchers,
-    )
-    if is_used_without_argument(args):
-        func = args[0]
-        self._thread_started_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._thread_started_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def user_message(self,
*args,
matchers: Callable[..., bool] | AsyncListenerMatcher | None = None,
middleware: Callable | AsyncMiddleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def user_message(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], AsyncListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._user_message_listeners is None:
-        self._user_message_listeners = []
-    all_matchers = self._merge_matchers(
-        build_listener_matcher(
-            func=is_user_message_event_in_assistant_thread,
-            asyncio=True,
-            base_logger=self.base_logger,
-        ),  # type: ignore[arg-type]
-        matchers,
-    )
-    if is_used_without_argument(args):
-        func = args[0]
-        self._user_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._user_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/assistant/index.html b/docs/reference/middleware/assistant/index.html deleted file mode 100644 index e9fce8d64..000000000 --- a/docs/reference/middleware/assistant/index.html +++ /dev/null @@ -1,681 +0,0 @@ - - - - - - -slack_bolt.middleware.assistant API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.assistant

-
-
-
-
-

Sub-modules

-
-
slack_bolt.middleware.assistant.assistant
-
-
-
-
slack_bolt.middleware.assistant.async_assistant
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Assistant -(*,
app_name: str = 'assistant',
thread_context_store: AssistantThreadContextStore | None = None,
logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class Assistant(Middleware):
-    _thread_started_listeners: Optional[List[Listener]]
-    _thread_context_changed_listeners: Optional[List[Listener]]
-    _user_message_listeners: Optional[List[Listener]]
-    _bot_message_listeners: Optional[List[Listener]]
-
-    thread_context_store: Optional[AssistantThreadContextStore]
-    base_logger: Optional[logging.Logger]
-
-    def __init__(
-        self,
-        *,
-        app_name: str = "assistant",
-        thread_context_store: Optional[AssistantThreadContextStore] = None,
-        logger: Optional[logging.Logger] = None,
-    ):
-        self.app_name = app_name
-        self.thread_context_store = thread_context_store
-        self.base_logger = logger
-
-        self._thread_started_listeners = None
-        self._thread_context_changed_listeners = None
-        self._user_message_listeners = None
-        self._bot_message_listeners = None
-
-    def thread_started(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._thread_started_listeners is None:
-            self._thread_started_listeners = []
-        all_matchers = self._merge_matchers(is_assistant_thread_started_event, matchers)
-        if is_used_without_argument(args):
-            func = args[0]
-            self._thread_started_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._thread_started_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def user_message(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._user_message_listeners is None:
-            self._user_message_listeners = []
-        all_matchers = self._merge_matchers(is_user_message_event_in_assistant_thread, matchers)
-        if is_used_without_argument(args):
-            func = args[0]
-            self._user_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._user_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def bot_message(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._bot_message_listeners is None:
-            self._bot_message_listeners = []
-        all_matchers = self._merge_matchers(is_bot_message_event_in_assistant_thread, matchers)
-        if is_used_without_argument(args):
-            func = args[0]
-            self._bot_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._bot_message_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def thread_context_changed(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        if self._thread_context_changed_listeners is None:
-            self._thread_context_changed_listeners = []
-        all_matchers = self._merge_matchers(is_assistant_thread_context_changed_event, matchers)
-        if is_used_without_argument(args):
-            func = args[0]
-            self._thread_context_changed_listeners.append(
-                self.build_listener(
-                    listener_or_functions=func,
-                    matchers=all_matchers,
-                    middleware=middleware,  # type: ignore[arg-type]
-                )
-            )
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._thread_context_changed_listeners.append(
-                self.build_listener(
-                    listener_or_functions=functions,
-                    matchers=all_matchers,
-                    middleware=middleware,
-                )
-            )
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def _merge_matchers(
-        self,
-        primary_matcher: Callable[..., bool],
-        custom_matchers: Optional[Union[Callable[..., bool], ListenerMatcher]],
-    ):
-        return [CustomListenerMatcher(app_name=self.app_name, func=primary_matcher)] + (
-            custom_matchers or []
-        )  # type: ignore[operator]
-
-    @staticmethod
-    def default_thread_context_changed(save_thread_context: SaveThreadContext, payload: dict):
-        save_thread_context(payload["assistant_thread"]["context"])
-
-    def process(  # type: ignore[return]
-        self, *, req: BoltRequest, resp: BoltResponse, next: Callable[[], BoltResponse]
-    ) -> Optional[BoltResponse]:
-        if self._thread_context_changed_listeners is None:
-            self.thread_context_changed(self.default_thread_context_changed)
-
-        listener_runner: ThreadListenerRunner = req.context.listener_runner
-        for listeners in [
-            self._thread_started_listeners,
-            self._thread_context_changed_listeners,
-            self._user_message_listeners,
-            self._bot_message_listeners,
-        ]:
-            if listeners is not None:
-                for listener in listeners:
-                    if listener.matches(req=req, resp=resp):
-                        middleware_resp, next_was_not_called = listener.run_middleware(req=req, resp=resp)
-                        if next_was_not_called:
-                            if middleware_resp is not None:
-                                return middleware_resp
-                            # The listener middleware didn't call next().
-                            # Skip this listener and try the next one.
-                            continue
-                        if middleware_resp is not None:
-                            resp = middleware_resp
-                        return listener_runner.run(
-                            request=req,
-                            response=resp,
-                            listener_name="assistant_listener",
-                            listener=listener,
-                        )
-        if is_other_message_sub_event_in_assistant_thread(req.body):
-            # message_changed, message_deleted, etc.
-            return req.context.ack()
-
-        next()
-
-    def build_listener(
-        self,
-        listener_or_functions: Union[Listener, Callable, List[Callable]],
-        matchers: Optional[List[Union[ListenerMatcher, Callable[..., bool]]]] = None,
-        middleware: Optional[List[Middleware]] = None,
-        base_logger: Optional[Logger] = None,
-    ) -> Listener:
-        if isinstance(listener_or_functions, Callable):  # type: ignore[arg-type]
-            listener_or_functions = [listener_or_functions]  # type: ignore[list-item]
-
-        if isinstance(listener_or_functions, Listener):
-            return listener_or_functions
-        elif isinstance(listener_or_functions, list):
-            middleware = middleware if middleware else []
-            middleware.insert(0, AttachingConversationKwargs(self.thread_context_store))
-            functions = listener_or_functions
-            ack_function = functions.pop(0)
-
-            matchers = matchers if matchers else []
-            listener_matchers: List[ListenerMatcher] = []
-            for matcher in matchers:
-                if isinstance(matcher, ListenerMatcher):
-                    listener_matchers.append(matcher)
-                elif isinstance(matcher, Callable):  # type: ignore[arg-type]
-                    listener_matchers.append(
-                        build_listener_matcher(
-                            func=matcher,
-                            asyncio=False,
-                            base_logger=base_logger,
-                        )
-                    )
-            return CustomListener(
-                app_name=self.app_name,
-                matchers=listener_matchers,
-                middleware=middleware,
-                ack_function=ack_function,
-                lazy_functions=functions,
-                auto_acknowledgement=True,
-                base_logger=base_logger or self.base_logger,
-            )
-        else:
-            raise BoltError(f"Invalid listener: {type(listener_or_functions)} detected")
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var base_logger : logging.Logger | None
-
-

The type of the None singleton.

-
-
var thread_context_storeAssistantThreadContextStore | None
-
-

The type of the None singleton.

-
-
-

Static methods

-
-
-def default_thread_context_changed(save_thread_context: SaveThreadContext,
payload: dict)
-
-
-
- -Expand source code - -
@staticmethod
-def default_thread_context_changed(save_thread_context: SaveThreadContext, payload: dict):
-    save_thread_context(payload["assistant_thread"]["context"])
-
-
-
-
-

Methods

-
-
-def bot_message(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def bot_message(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._bot_message_listeners is None:
-        self._bot_message_listeners = []
-    all_matchers = self._merge_matchers(is_bot_message_event_in_assistant_thread, matchers)
-    if is_used_without_argument(args):
-        func = args[0]
-        self._bot_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._bot_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def build_listener(self,
listener_or_functions: Listener | Callable | List[Callable],
matchers: List[ListenerMatcher | Callable[..., bool]] | None = None,
middleware: List[Middleware] | None = None,
base_logger: logging.Logger | None = None) ‑> Listener
-
-
-
- -Expand source code - -
def build_listener(
-    self,
-    listener_or_functions: Union[Listener, Callable, List[Callable]],
-    matchers: Optional[List[Union[ListenerMatcher, Callable[..., bool]]]] = None,
-    middleware: Optional[List[Middleware]] = None,
-    base_logger: Optional[Logger] = None,
-) -> Listener:
-    if isinstance(listener_or_functions, Callable):  # type: ignore[arg-type]
-        listener_or_functions = [listener_or_functions]  # type: ignore[list-item]
-
-    if isinstance(listener_or_functions, Listener):
-        return listener_or_functions
-    elif isinstance(listener_or_functions, list):
-        middleware = middleware if middleware else []
-        middleware.insert(0, AttachingConversationKwargs(self.thread_context_store))
-        functions = listener_or_functions
-        ack_function = functions.pop(0)
-
-        matchers = matchers if matchers else []
-        listener_matchers: List[ListenerMatcher] = []
-        for matcher in matchers:
-            if isinstance(matcher, ListenerMatcher):
-                listener_matchers.append(matcher)
-            elif isinstance(matcher, Callable):  # type: ignore[arg-type]
-                listener_matchers.append(
-                    build_listener_matcher(
-                        func=matcher,
-                        asyncio=False,
-                        base_logger=base_logger,
-                    )
-                )
-        return CustomListener(
-            app_name=self.app_name,
-            matchers=listener_matchers,
-            middleware=middleware,
-            ack_function=ack_function,
-            lazy_functions=functions,
-            auto_acknowledgement=True,
-            base_logger=base_logger or self.base_logger,
-        )
-    else:
-        raise BoltError(f"Invalid listener: {type(listener_or_functions)} detected")
-
-
-
-
-def thread_context_changed(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def thread_context_changed(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._thread_context_changed_listeners is None:
-        self._thread_context_changed_listeners = []
-    all_matchers = self._merge_matchers(is_assistant_thread_context_changed_event, matchers)
-    if is_used_without_argument(args):
-        func = args[0]
-        self._thread_context_changed_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._thread_context_changed_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def thread_started(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def thread_started(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._thread_started_listeners is None:
-        self._thread_started_listeners = []
-    all_matchers = self._merge_matchers(is_assistant_thread_started_event, matchers)
-    if is_used_without_argument(args):
-        func = args[0]
-        self._thread_started_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._thread_started_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-def user_message(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def user_message(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    if self._user_message_listeners is None:
-        self._user_message_listeners = []
-    all_matchers = self._merge_matchers(is_user_message_event_in_assistant_thread, matchers)
-    if is_used_without_argument(args):
-        func = args[0]
-        self._user_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=func,
-                matchers=all_matchers,
-                middleware=middleware,  # type: ignore[arg-type]
-            )
-        )
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._user_message_listeners.append(
-            self.build_listener(
-                listener_or_functions=functions,
-                matchers=all_matchers,
-                middleware=middleware,
-            )
-        )
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-
-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/async_builtins.html b/docs/reference/middleware/async_builtins.html deleted file mode 100644 index 8f7b1ba4f..000000000 --- a/docs/reference/middleware/async_builtins.html +++ /dev/null @@ -1,522 +0,0 @@ - - - - - - -slack_bolt.middleware.async_builtins API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.async_builtins

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncAttachingConversationKwargs -(thread_context_store: AsyncAssistantThreadContextStore | None = None) -
-
-
- -Expand source code - -
class AsyncAttachingConversationKwargs(AsyncMiddleware):
-
-    thread_context_store: Optional[AsyncAssistantThreadContextStore]
-
-    def __init__(self, thread_context_store: Optional[AsyncAssistantThreadContextStore] = None):
-        self.thread_context_store = thread_context_store
-
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> Optional[BoltResponse]:
-        event = to_event(req.body)
-        if event is None:
-            return await next()
-        if req.context.channel_id is None:
-            return await next()
-
-        if is_assistant_event(req.body):
-            # TODO: eventually we might remove this assistant specific logic
-            assistant = AsyncAssistantUtilities(
-                payload=event,
-                context=req.context,
-                thread_context_store=self.thread_context_store,
-            )
-            req.context["say"] = assistant.say
-            req.context["set_title"] = assistant.set_title
-            req.context["get_thread_context"] = assistant.get_thread_context
-            req.context["save_thread_context"] = assistant.save_thread_context
-
-        if (
-            is_im_message_event(req.body)
-            or is_assistant_thread_started_event(req.body)
-            or is_assistant_thread_context_changed_event(req.body)
-            or is_app_home_opened_event(req.body, tab="messages")
-        ):
-            req.context["set_suggested_prompts"] = AsyncSetSuggestedPrompts(
-                client=req.context.client,
-                channel_id=req.context.channel_id,
-                thread_ts=req.context.thread_ts,
-            )
-
-        # TODO: in the future we might want to introduce a "proper" extract_ts utility
-        thread_ts_or_ts = req.context.thread_ts or event.get("ts")
-        if thread_ts_or_ts:
-            req.context["set_status"] = AsyncSetStatus(
-                client=req.context.client,
-                channel_id=req.context.channel_id,
-                thread_ts=thread_ts_or_ts,
-            )
-            req.context["say_stream"] = AsyncSayStream(
-                client=req.context.client,
-                channel=req.context.channel_id,
-                recipient_team_id=req.context.team_id or req.context.enterprise_id,
-                recipient_user_id=req.context.user_id,
-                thread_ts=thread_ts_or_ts,
-            )
-        return await next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var thread_context_storeAsyncAssistantThreadContextStore | None
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class AsyncAttachingFunctionToken -
-
-
- -Expand source code - -
class AsyncAttachingFunctionToken(AsyncMiddleware):
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        # This method is not supposed to be invoked by bolt-python users
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        if req.context.function_bot_access_token is not None:
-            req.context.client.token = req.context.function_bot_access_token
-
-        return await next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Inherited members

- -
-
-class AsyncIgnoringSelfEvents -(base_logger: logging.Logger | None = None,
ignoring_self_assistant_message_events_enabled: bool = True)
-
-
-
- -Expand source code - -
class AsyncIgnoringSelfEvents(IgnoringSelfEvents, AsyncMiddleware):
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        auth_result = req.context.authorize_result
-        # message events can have $.event.bot_id while it does not have its user_id
-        bot_id = req.body.get("event", {}).get("bot_id")
-        if self._is_self_event(auth_result, req.context.user_id, bot_id, req.body):  # type: ignore[arg-type]
-            if self.ignoring_self_assistant_message_events_enabled is False:
-                if is_bot_message_event_in_assistant_thread(req.body):
-                    # Assistant#bot_message handler acknowledges this pattern
-                    return await next()
-
-            self._debug_log(req.body)
-            return await req.context.ack()
-        else:
-            return await next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Ignores the events generated by this bot user itself.

-

Ancestors

- -

Inherited members

- -
-
-class AsyncMessageListenerMatches -(keyword: str | Pattern) -
-
-
- -Expand source code - -
class AsyncMessageListenerMatches(AsyncMiddleware):
-    def __init__(self, keyword: Union[str, Pattern]):
-        """Captures matched keywords and saves the values in context."""
-        self.keyword = keyword
-
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        text = req.body.get("event", {}).get("text", "")
-        if text:
-            m: Optional[Union[Sequence]] = re.findall(self.keyword, text)
-            if m is not None and m != []:
-                if type(m[0]) is not tuple:
-                    m = tuple(m)
-                else:
-                    m = m[0]
-                req.context["matches"] = m  # tuple or list
-                return await next()
-
-        # As the text doesn't match, skip running the listener
-        return resp
-
-

A middleware can process request data before other middleware and listener functions.

-

Captures matched keywords and saves the values in context.

-

Ancestors

- -

Inherited members

- -
-
-class AsyncRequestVerification -(signing_secret: str, base_logger: logging.Logger | None = None) -
-
-
- -Expand source code - -
class AsyncRequestVerification(RequestVerification, AsyncMiddleware):
-    """Verifies an incoming request by checking the validity of
-    `x-slack-signature`, `x-slack-request-timestamp`, and its body data.
-
-    Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details.
-    """
-
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        if self._can_skip(req.mode, req.body):
-            return await next()
-
-        body = req.raw_body
-        timestamp = req.headers.get("x-slack-request-timestamp", ["0"])[0]
-        signature = req.headers.get("x-slack-signature", [""])[0]
-        if self.verifier.is_valid(body, timestamp, signature):
-            return await next()
-        else:
-            self._debug_log_error(signature, timestamp, body)
-            return self._build_error_response()
-
-

Verifies an incoming request by checking the validity of -x-slack-signature, x-slack-request-timestamp, and its body data.

-

Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details.

-

Verifies an incoming request by checking the validity of -x-slack-signature, x-slack-request-timestamp, and its body data.

-

Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details.

-

Args

-
-
signing_secret
-
The signing secret
-
base_logger
-
The base logger
-
-

Ancestors

- -

Inherited members

- -
-
-class AsyncSslCheck -(verification_token: str | None = None,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncSslCheck(SslCheck, AsyncMiddleware):
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        if self._is_ssl_check_request(req.body):
-            if self._verify_token_if_needed(req.body):
-                return self._build_error_response()
-            return self._build_success_response()
-        else:
-            return await next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Handles ssl_check requests. -Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details.

-

Args

-
-
verification_token
-
The verification token to check -(optional as it's already deprecated - https://docs.slack.dev/authentication/verifying-requests-from-slack/#deprecation)
-
base_logger
-
The base logger
-
-

Ancestors

- -

Inherited members

- -
-
-class AsyncUrlVerification -(base_logger: logging.Logger | None = None) -
-
-
- -Expand source code - -
class AsyncUrlVerification(UrlVerification, AsyncMiddleware):
-    def __init__(self, base_logger: Optional[Logger] = None):
-        self.logger = get_bolt_logger(AsyncUrlVerification, base_logger=base_logger)
-
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        if self._is_url_verification_request(req.body):
-            return self._build_success_response(req.body)
-        else:
-            return await next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Handles url_verification requests.

-

Refer to https://docs.slack.dev/reference/events/url_verification/ for details.

-

Args

-
-
base_logger
-
The base logger
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/async_custom_middleware.html b/docs/reference/middleware/async_custom_middleware.html deleted file mode 100644 index d985458ed..000000000 --- a/docs/reference/middleware/async_custom_middleware.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - -slack_bolt.middleware.async_custom_middleware API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.async_custom_middleware

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncCustomMiddleware -(*,
app_name: str,
func: Callable[..., Awaitable[Any]],
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncCustomMiddleware(AsyncMiddleware):
-    app_name: str
-    func: Callable[..., Awaitable[Any]]
-    arg_names: MutableSequence[str]
-    logger: Logger
-
-    def __init__(
-        self,
-        *,
-        app_name: str,
-        func: Callable[..., Awaitable[Any]],
-        base_logger: Optional[Logger] = None,
-    ):
-        self.app_name = app_name
-        if is_callable_coroutine(func):
-            self.func = func
-        else:
-            raise ValueError("Async middleware function must be an async function")
-
-        self.arg_names = get_arg_names_of_callable(func)
-        self.logger = get_bolt_app_logger(self.app_name, self.func, base_logger)
-
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        return await self.func(
-            **build_async_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,
-                request=req,
-                response=resp,
-                next_func=next,  # type: ignore[arg-type]
-                this_func=self.func,
-            )
-        )
-
-    @property
-    def name(self) -> str:
-        return f"AsyncCustomMiddleware(func={get_name_for_callable(self.func)})"
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : MutableSequence[str]
-
-

The type of the None singleton.

-
-
var func : Callable[..., Awaitable[Any]]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/async_middleware.html b/docs/reference/middleware/async_middleware.html deleted file mode 100644 index f7713b881..000000000 --- a/docs/reference/middleware/async_middleware.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - -slack_bolt.middleware.async_middleware API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.async_middleware

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncMiddleware -
-
-
- -Expand source code - -
class AsyncMiddleware(metaclass=ABCMeta):
-    """A middleware can process request data before other middleware and listener functions."""
-
-    @abstractmethod
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> Optional[BoltResponse]:
-        """Processes a request data before other middleware and listeners.
-        A middleware calls `next()` function if the chain should continue.
-
-            @app.middleware
-            async def simple_middleware(req, resp, next):
-                # do something here
-                await next()
-
-        This `async_process(req, resp, next)` method is supposed to be invoked only inside bolt-python.
-        If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead.
-
-            @app.middleware
-            async def simple_middleware(req, resp, next_):
-                # do something here
-                await next_()
-
-        Args:
-            req: The incoming request
-            resp: The response
-            next: The function to tell the chain that it can continue
-
-        Returns:
-            Processed response (optional)
-        """
-        raise NotImplementedError()
-
-    @property
-    def name(self) -> str:
-        """The name of this middleware"""
-        return f"{self.__module__}.{self.__class__.__name__}"
-
-

A middleware can process request data before other middleware and listener functions.

-

Subclasses

- -

Instance variables

-
-
prop name : str
-
-
- -Expand source code - -
@property
-def name(self) -> str:
-    """The name of this middleware"""
-    return f"{self.__module__}.{self.__class__.__name__}"
-
-

The name of this middleware

-
-
-

Methods

-
-
-async def async_process(self,
*,
req: AsyncBoltRequest,
resp: BoltResponse,
next: Callable[[], Awaitable[BoltResponse]]) ‑> BoltResponse | None
-
-
-
- -Expand source code - -
@abstractmethod
-async def async_process(
-    self,
-    *,
-    req: AsyncBoltRequest,
-    resp: BoltResponse,
-    # As this method is not supposed to be invoked by bolt-python users,
-    # the naming conflict with the built-in one affects
-    # only the internals of this method
-    next: Callable[[], Awaitable[BoltResponse]],
-) -> Optional[BoltResponse]:
-    """Processes a request data before other middleware and listeners.
-    A middleware calls `next()` function if the chain should continue.
-
-        @app.middleware
-        async def simple_middleware(req, resp, next):
-            # do something here
-            await next()
-
-    This `async_process(req, resp, next)` method is supposed to be invoked only inside bolt-python.
-    If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead.
-
-        @app.middleware
-        async def simple_middleware(req, resp, next_):
-            # do something here
-            await next_()
-
-    Args:
-        req: The incoming request
-        resp: The response
-        next: The function to tell the chain that it can continue
-
-    Returns:
-        Processed response (optional)
-    """
-    raise NotImplementedError()
-
-

Processes a request data before other middleware and listeners. -A middleware calls next() function if the chain should continue.

-
@app.middleware
-async def simple_middleware(req, resp, next):
-    # do something here
-    await next()
-
-

This async_process(req, resp, next) method is supposed to be invoked only inside bolt-python. -If you want to avoid the name next() in your middleware functions, you can use next_() method instead.

-
@app.middleware
-async def simple_middleware(req, resp, next_):
-    # do something here
-    await next_()
-
-

Args

-
-
req
-
The incoming request
-
resp
-
The response
-
next
-
The function to tell the chain that it can continue
-
-

Returns

-

Processed response (optional)

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/middleware/async_middleware_error_handler.html b/docs/reference/middleware/async_middleware_error_handler.html deleted file mode 100644 index bf5b101f6..000000000 --- a/docs/reference/middleware/async_middleware_error_handler.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - -slack_bolt.middleware.async_middleware_error_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.async_middleware_error_handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncCustomMiddlewareErrorHandler -(logger: logging.Logger,
func: Callable[..., Awaitable[BoltResponse | None]])
-
-
-
- -Expand source code - -
class AsyncCustomMiddlewareErrorHandler(AsyncMiddlewareErrorHandler):
-    def __init__(self, logger: Logger, func: Callable[..., Awaitable[Optional[BoltResponse]]]):
-        self.func = func
-        self.logger = logger
-        self.arg_names = get_arg_names_of_callable(func)
-
-    async def handle(
-        self,
-        error: Exception,
-        request: AsyncBoltRequest,
-        response: Optional[BoltResponse],
-    ) -> None:
-        kwargs: Dict[str, Any] = build_async_required_kwargs(
-            required_arg_names=self.arg_names,
-            logger=self.logger,
-            error=error,
-            request=request,
-            response=response,
-            next_keys_required=False,
-        )
-        returned_response = await self.func(**kwargs)
-        if returned_response is not None and isinstance(returned_response, BoltResponse):
-            assert response is not None, "response must be provided when returning a BoltResponse from an error handler"
-            response.status = returned_response.status
-            response.headers = returned_response.headers
-            response.body = returned_response.body
-
-
-

Ancestors

- -

Inherited members

- -
-
-class AsyncDefaultMiddlewareErrorHandler -(logger: logging.Logger) -
-
-
- -Expand source code - -
class AsyncDefaultMiddlewareErrorHandler(AsyncMiddlewareErrorHandler):
-    def __init__(self, logger: Logger):
-        self.logger = logger
-
-    async def handle(
-        self,
-        error: Exception,
-        request: AsyncBoltRequest,
-        response: Optional[BoltResponse],
-    ):
-        message = f"Failed to run a middleware function (error: {error})"
-        self.logger.exception(message)
-
-
-

Ancestors

- -

Inherited members

- -
-
-class AsyncMiddlewareErrorHandler -
-
-
- -Expand source code - -
class AsyncMiddlewareErrorHandler(metaclass=ABCMeta):
-    @abstractmethod
-    async def handle(
-        self,
-        error: Exception,
-        request: AsyncBoltRequest,
-        response: Optional[BoltResponse],
-    ) -> None:
-        """Handles an unhandled exception.
-
-        Args:
-            error: The raised exception.
-            request: The request.
-            response: The response.
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-async def handle(self,
error: Exception,
request: AsyncBoltRequest,
response: BoltResponse | None) ‑> None
-
-
-
- -Expand source code - -
@abstractmethod
-async def handle(
-    self,
-    error: Exception,
-    request: AsyncBoltRequest,
-    response: Optional[BoltResponse],
-) -> None:
-    """Handles an unhandled exception.
-
-    Args:
-        error: The raised exception.
-        request: The request.
-        response: The response.
-    """
-    raise NotImplementedError()
-
-

Handles an unhandled exception.

-

Args

-
-
error
-
The raised exception.
-
request
-
The request.
-
response
-
The response.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/middleware/attaching_conversation_kwargs/async_attaching_conversation_kwargs.html b/docs/reference/middleware/attaching_conversation_kwargs/async_attaching_conversation_kwargs.html deleted file mode 100644 index e2bbe7045..000000000 --- a/docs/reference/middleware/attaching_conversation_kwargs/async_attaching_conversation_kwargs.html +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - -slack_bolt.middleware.attaching_conversation_kwargs.async_attaching_conversation_kwargs API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.attaching_conversation_kwargs.async_attaching_conversation_kwargs

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncAttachingConversationKwargs -(thread_context_store: AsyncAssistantThreadContextStore | None = None) -
-
-
- -Expand source code - -
class AsyncAttachingConversationKwargs(AsyncMiddleware):
-
-    thread_context_store: Optional[AsyncAssistantThreadContextStore]
-
-    def __init__(self, thread_context_store: Optional[AsyncAssistantThreadContextStore] = None):
-        self.thread_context_store = thread_context_store
-
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> Optional[BoltResponse]:
-        event = to_event(req.body)
-        if event is None:
-            return await next()
-        if req.context.channel_id is None:
-            return await next()
-
-        if is_assistant_event(req.body):
-            # TODO: eventually we might remove this assistant specific logic
-            assistant = AsyncAssistantUtilities(
-                payload=event,
-                context=req.context,
-                thread_context_store=self.thread_context_store,
-            )
-            req.context["say"] = assistant.say
-            req.context["set_title"] = assistant.set_title
-            req.context["get_thread_context"] = assistant.get_thread_context
-            req.context["save_thread_context"] = assistant.save_thread_context
-
-        if (
-            is_im_message_event(req.body)
-            or is_assistant_thread_started_event(req.body)
-            or is_assistant_thread_context_changed_event(req.body)
-            or is_app_home_opened_event(req.body, tab="messages")
-        ):
-            req.context["set_suggested_prompts"] = AsyncSetSuggestedPrompts(
-                client=req.context.client,
-                channel_id=req.context.channel_id,
-                thread_ts=req.context.thread_ts,
-            )
-
-        # TODO: in the future we might want to introduce a "proper" extract_ts utility
-        thread_ts_or_ts = req.context.thread_ts or event.get("ts")
-        if thread_ts_or_ts:
-            req.context["set_status"] = AsyncSetStatus(
-                client=req.context.client,
-                channel_id=req.context.channel_id,
-                thread_ts=thread_ts_or_ts,
-            )
-            req.context["say_stream"] = AsyncSayStream(
-                client=req.context.client,
-                channel=req.context.channel_id,
-                recipient_team_id=req.context.team_id or req.context.enterprise_id,
-                recipient_user_id=req.context.user_id,
-                thread_ts=thread_ts_or_ts,
-            )
-        return await next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var thread_context_storeAsyncAssistantThreadContextStore | None
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/attaching_conversation_kwargs/attaching_conversation_kwargs.html b/docs/reference/middleware/attaching_conversation_kwargs/attaching_conversation_kwargs.html deleted file mode 100644 index e9d558fec..000000000 --- a/docs/reference/middleware/attaching_conversation_kwargs/attaching_conversation_kwargs.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - -slack_bolt.middleware.attaching_conversation_kwargs.attaching_conversation_kwargs API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.attaching_conversation_kwargs.attaching_conversation_kwargs

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AttachingConversationKwargs -(thread_context_store: AssistantThreadContextStore | None = None) -
-
-
- -Expand source code - -
class AttachingConversationKwargs(Middleware):
-
-    thread_context_store: Optional[AssistantThreadContextStore]
-
-    def __init__(self, thread_context_store: Optional[AssistantThreadContextStore] = None):
-        self.thread_context_store = thread_context_store
-
-    def process(self, *, req: BoltRequest, resp: BoltResponse, next: Callable[[], BoltResponse]) -> Optional[BoltResponse]:
-        event = to_event(req.body)
-        if event is None:
-            return next()
-        if req.context.channel_id is None:
-            return next()
-
-        if is_assistant_event(req.body):
-            # TODO: eventually we might remove this assistant specific logic
-            assistant = AssistantUtilities(
-                payload=event,
-                context=req.context,
-                thread_context_store=self.thread_context_store,
-            )
-            req.context["say"] = assistant.say
-            req.context["set_title"] = assistant.set_title
-            req.context["get_thread_context"] = assistant.get_thread_context
-            req.context["save_thread_context"] = assistant.save_thread_context
-
-        if (
-            is_im_message_event(req.body)
-            or is_assistant_thread_started_event(req.body)
-            or is_assistant_thread_context_changed_event(req.body)
-            or is_app_home_opened_event(req.body, tab="messages")
-        ):
-            req.context["set_suggested_prompts"] = SetSuggestedPrompts(
-                client=req.context.client,
-                channel_id=req.context.channel_id,
-                thread_ts=req.context.thread_ts,
-            )
-
-        # TODO: in the future we might want to introduce a "proper" extract_ts utility
-        thread_ts_or_ts = req.context.thread_ts or event.get("ts")
-        if thread_ts_or_ts:
-            req.context["set_status"] = SetStatus(
-                client=req.context.client,
-                channel_id=req.context.channel_id,
-                thread_ts=thread_ts_or_ts,
-            )
-            req.context["say_stream"] = SayStream(
-                client=req.context.client,
-                channel=req.context.channel_id,
-                recipient_team_id=req.context.team_id or req.context.enterprise_id,
-                recipient_user_id=req.context.user_id,
-                thread_ts=thread_ts_or_ts,
-            )
-        return next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var thread_context_storeAssistantThreadContextStore | None
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/attaching_conversation_kwargs/index.html b/docs/reference/middleware/attaching_conversation_kwargs/index.html deleted file mode 100644 index 38da4442e..000000000 --- a/docs/reference/middleware/attaching_conversation_kwargs/index.html +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - -slack_bolt.middleware.attaching_conversation_kwargs API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.attaching_conversation_kwargs

-
-
-
-
-

Sub-modules

-
-
slack_bolt.middleware.attaching_conversation_kwargs.async_attaching_conversation_kwargs
-
-
-
-
slack_bolt.middleware.attaching_conversation_kwargs.attaching_conversation_kwargs
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AttachingConversationKwargs -(thread_context_store: AssistantThreadContextStore | None = None) -
-
-
- -Expand source code - -
class AttachingConversationKwargs(Middleware):
-
-    thread_context_store: Optional[AssistantThreadContextStore]
-
-    def __init__(self, thread_context_store: Optional[AssistantThreadContextStore] = None):
-        self.thread_context_store = thread_context_store
-
-    def process(self, *, req: BoltRequest, resp: BoltResponse, next: Callable[[], BoltResponse]) -> Optional[BoltResponse]:
-        event = to_event(req.body)
-        if event is None:
-            return next()
-        if req.context.channel_id is None:
-            return next()
-
-        if is_assistant_event(req.body):
-            # TODO: eventually we might remove this assistant specific logic
-            assistant = AssistantUtilities(
-                payload=event,
-                context=req.context,
-                thread_context_store=self.thread_context_store,
-            )
-            req.context["say"] = assistant.say
-            req.context["set_title"] = assistant.set_title
-            req.context["get_thread_context"] = assistant.get_thread_context
-            req.context["save_thread_context"] = assistant.save_thread_context
-
-        if (
-            is_im_message_event(req.body)
-            or is_assistant_thread_started_event(req.body)
-            or is_assistant_thread_context_changed_event(req.body)
-            or is_app_home_opened_event(req.body, tab="messages")
-        ):
-            req.context["set_suggested_prompts"] = SetSuggestedPrompts(
-                client=req.context.client,
-                channel_id=req.context.channel_id,
-                thread_ts=req.context.thread_ts,
-            )
-
-        # TODO: in the future we might want to introduce a "proper" extract_ts utility
-        thread_ts_or_ts = req.context.thread_ts or event.get("ts")
-        if thread_ts_or_ts:
-            req.context["set_status"] = SetStatus(
-                client=req.context.client,
-                channel_id=req.context.channel_id,
-                thread_ts=thread_ts_or_ts,
-            )
-            req.context["say_stream"] = SayStream(
-                client=req.context.client,
-                channel=req.context.channel_id,
-                recipient_team_id=req.context.team_id or req.context.enterprise_id,
-                recipient_user_id=req.context.user_id,
-                thread_ts=thread_ts_or_ts,
-            )
-        return next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var thread_context_storeAssistantThreadContextStore | None
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/attaching_function_token/async_attaching_function_token.html b/docs/reference/middleware/attaching_function_token/async_attaching_function_token.html deleted file mode 100644 index 1becac04e..000000000 --- a/docs/reference/middleware/attaching_function_token/async_attaching_function_token.html +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - -slack_bolt.middleware.attaching_function_token.async_attaching_function_token API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.attaching_function_token.async_attaching_function_token

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncAttachingFunctionToken -
-
-
- -Expand source code - -
class AsyncAttachingFunctionToken(AsyncMiddleware):
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        # This method is not supposed to be invoked by bolt-python users
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        if req.context.function_bot_access_token is not None:
-            req.context.client.token = req.context.function_bot_access_token
-
-        return await next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/attaching_function_token/attaching_function_token.html b/docs/reference/middleware/attaching_function_token/attaching_function_token.html deleted file mode 100644 index 8eea36647..000000000 --- a/docs/reference/middleware/attaching_function_token/attaching_function_token.html +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - -slack_bolt.middleware.attaching_function_token.attaching_function_token API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.attaching_function_token.attaching_function_token

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AttachingFunctionToken -
-
-
- -Expand source code - -
class AttachingFunctionToken(Middleware):
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # This method is not supposed to be invoked by bolt-python users
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        if req.context.function_bot_access_token is not None:
-            req.context.client.token = req.context.function_bot_access_token
-
-        return next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/attaching_function_token/index.html b/docs/reference/middleware/attaching_function_token/index.html deleted file mode 100644 index 44efd27a2..000000000 --- a/docs/reference/middleware/attaching_function_token/index.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - -slack_bolt.middleware.attaching_function_token API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.attaching_function_token

-
-
-
-
-

Sub-modules

-
-
slack_bolt.middleware.attaching_function_token.async_attaching_function_token
-
-
-
-
slack_bolt.middleware.attaching_function_token.attaching_function_token
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AttachingFunctionToken -
-
-
- -Expand source code - -
class AttachingFunctionToken(Middleware):
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # This method is not supposed to be invoked by bolt-python users
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        if req.context.function_bot_access_token is not None:
-            req.context.client.token = req.context.function_bot_access_token
-
-        return next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/authorization/async_authorization.html b/docs/reference/middleware/authorization/async_authorization.html deleted file mode 100644 index 9f38ea711..000000000 --- a/docs/reference/middleware/authorization/async_authorization.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - -slack_bolt.middleware.authorization.async_authorization API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.authorization.async_authorization

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncAuthorization -
-
-
- -Expand source code - -
class AsyncAuthorization(AsyncMiddleware, ABC):
-    pass
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Subclasses

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/authorization/async_internals.html b/docs/reference/middleware/authorization/async_internals.html deleted file mode 100644 index 22b709799..000000000 --- a/docs/reference/middleware/authorization/async_internals.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - -slack_bolt.middleware.authorization.async_internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.authorization.async_internals

-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/middleware/authorization/async_multi_teams_authorization.html b/docs/reference/middleware/authorization/async_multi_teams_authorization.html deleted file mode 100644 index 50b529f33..000000000 --- a/docs/reference/middleware/authorization/async_multi_teams_authorization.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - -slack_bolt.middleware.authorization.async_multi_teams_authorization API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.authorization.async_multi_teams_authorization

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncMultiTeamsAuthorization -(authorize: AsyncAuthorize,
base_logger: logging.Logger | None = None,
user_token_resolution: str = 'authed_user',
user_facing_authorize_error_message: str | None = None)
-
-
-
- -Expand source code - -
class AsyncMultiTeamsAuthorization(AsyncAuthorization):
-    authorize: AsyncAuthorize
-    user_token_resolution: str
-
-    def __init__(
-        self,
-        authorize: AsyncAuthorize,
-        base_logger: Optional[Logger] = None,
-        user_token_resolution: str = "authed_user",
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        """Multi-workspace authorization.
-
-        Args:
-            authorize: The function to authorize incoming requests from Slack.
-            base_logger: The base logger
-            user_token_resolution: "authed_user" or "actor"
-            user_facing_authorize_error_message: The user-facing error message when installation is not found
-        """
-        self.authorize = authorize
-        self.logger = get_bolt_logger(AsyncMultiTeamsAuthorization, base_logger=base_logger)
-        self.user_token_resolution = user_token_resolution
-        self.user_facing_authorize_error_message = (
-            user_facing_authorize_error_message or _build_user_facing_authorize_error_message()
-        )
-
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        if _is_no_auth_required(req):
-            return await 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 await next()
-
-        try:
-            auth_result: Optional[AuthorizeResult] = None
-            if self.user_token_resolution == "actor":
-                auth_result = await self.authorize(
-                    context=req.context,
-                    enterprise_id=req.context.enterprise_id,
-                    team_id=req.context.team_id,
-                    user_id=req.context.user_id,
-                    actor_enterprise_id=req.context.actor_enterprise_id,
-                    actor_team_id=req.context.actor_team_id,
-                    actor_user_id=req.context.actor_user_id,
-                )
-            else:
-                auth_result = await 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:
-                req.context.set_authorize_result(auth_result)
-                token = auth_result.bot_token or auth_result.user_token
-                req.context["token"] = token
-                # As AsyncApp#_init_context() generates a new AsyncWebClient for this request,
-                # it's safe to modify this instance.
-                req.context.client.token = token
-                return await next()
-            else:
-                # This situation can arise if:
-                # * A developer installed the app from the "Install to Workspace" button in Slack app config page
-                # * The InstallationStore failed to save or deleted the installation for this workspace
-                self.logger.error(
-                    "Although the app should be installed into this workspace, "
-                    "the AuthorizeResult (returned value from authorize) for it was not found."
-                )
-                if req.context.response_url is not None:
-                    await req.context.respond(self.user_facing_authorize_error_message)  # type: ignore[misc]
-                    return BoltResponse(status=200, body="")
-                return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-
-        except SlackApiError as e:
-            self.logger.error(f"Failed to authorize with the given token ({e})")
-            return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-
-

A middleware can process request data before other middleware and listener functions.

-

Multi-workspace authorization.

-

Args

-
-
authorize
-
The function to authorize incoming requests from Slack.
-
base_logger
-
The base logger
-
user_token_resolution
-
"authed_user" or "actor"
-
user_facing_authorize_error_message
-
The user-facing error message when installation is not found
-
-

Ancestors

- -

Class variables

-
-
var authorizeAsyncAuthorize
-
-

The type of the None singleton.

-
-
var user_token_resolution : str
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/authorization/async_single_team_authorization.html b/docs/reference/middleware/authorization/async_single_team_authorization.html deleted file mode 100644 index a167d1c68..000000000 --- a/docs/reference/middleware/authorization/async_single_team_authorization.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - -slack_bolt.middleware.authorization.async_single_team_authorization API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.authorization.async_single_team_authorization

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSingleTeamAuthorization -(base_logger: logging.Logger | None = None,
user_facing_authorize_error_message: str | None = None)
-
-
-
- -Expand source code - -
class AsyncSingleTeamAuthorization(AsyncAuthorization):
-    def __init__(
-        self,
-        base_logger: Optional[Logger] = None,
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        """Single-workspace authorization."""
-        self.auth_test_result: Optional[AsyncSlackResponse] = None
-        self.logger = get_bolt_logger(AsyncSingleTeamAuthorization, base_logger=base_logger)
-        self.user_facing_authorize_error_message = (
-            user_facing_authorize_error_message or _build_user_facing_authorize_error_message()
-        )
-
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        if _is_no_auth_required(req):
-            return await 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 await next()
-
-        try:
-            if self.auth_test_result is None:
-                self.auth_test_result = await req.context.client.auth_test()
-
-            if self.auth_test_result:
-                req.context.set_authorize_result(
-                    _to_authorize_result(
-                        auth_test_result=self.auth_test_result,
-                        token=req.context.client.token,
-                        request_user_id=req.context.user_id,
-                    )
-                )
-                return await next()
-            else:
-                # Just in case
-                self.logger.error("auth.test API call result is unexpectedly None")
-                if req.context.response_url is not None:
-                    await req.context.respond(self.user_facing_authorize_error_message)  # type: ignore[misc]
-                    return BoltResponse(status=200, body="")
-                return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-        except SlackApiError as e:
-            self.logger.error(f"Failed to authorize with the given token ({e})")
-            return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-
-

A middleware can process request data before other middleware and listener functions.

-

Single-workspace authorization.

-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/authorization/authorization.html b/docs/reference/middleware/authorization/authorization.html deleted file mode 100644 index 7ddd4ce41..000000000 --- a/docs/reference/middleware/authorization/authorization.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - -slack_bolt.middleware.authorization.authorization API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.authorization.authorization

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Authorization -
-
-
- -Expand source code - -
class Authorization(Middleware):
-    pass
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Subclasses

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/authorization/index.html b/docs/reference/middleware/authorization/index.html deleted file mode 100644 index 9f5c3f393..000000000 --- a/docs/reference/middleware/authorization/index.html +++ /dev/null @@ -1,404 +0,0 @@ - - - - - - -slack_bolt.middleware.authorization API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.authorization

-
-
-
-
-

Sub-modules

-
-
slack_bolt.middleware.authorization.async_authorization
-
-
-
-
slack_bolt.middleware.authorization.async_internals
-
-
-
-
slack_bolt.middleware.authorization.async_multi_teams_authorization
-
-
-
-
slack_bolt.middleware.authorization.async_single_team_authorization
-
-
-
-
slack_bolt.middleware.authorization.authorization
-
-
-
-
slack_bolt.middleware.authorization.internals
-
-
-
-
slack_bolt.middleware.authorization.multi_teams_authorization
-
-
-
-
slack_bolt.middleware.authorization.single_team_authorization
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Authorization -
-
-
- -Expand source code - -
class Authorization(Middleware):
-    pass
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Subclasses

- -

Inherited members

- -
-
-class MultiTeamsAuthorization -(*,
authorize: Authorize,
base_logger: logging.Logger | None = None,
user_token_resolution: str = 'authed_user',
user_facing_authorize_error_message: str | None = None)
-
-
-
- -Expand source code - -
class MultiTeamsAuthorization(Authorization):
-    authorize: Authorize
-    user_token_resolution: str
-
-    def __init__(
-        self,
-        *,
-        authorize: Authorize,
-        base_logger: Optional[Logger] = None,
-        user_token_resolution: str = "authed_user",
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        """Multi-workspace authorization.
-
-        Args:
-            authorize: The function to authorize incoming requests from Slack.
-            base_logger: The base logger
-            user_token_resolution: "authed_user" or "actor"
-            user_facing_authorize_error_message: The user-facing error message when installation is not found
-        """
-        self.authorize = authorize
-        self.logger = get_bolt_logger(MultiTeamsAuthorization, base_logger=base_logger)
-        self.user_token_resolution = user_token_resolution
-        self.user_facing_authorize_error_message = (
-            user_facing_authorize_error_message or _build_user_facing_authorize_error_message()
-        )
-
-    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] = None
-            if self.user_token_resolution == "actor":
-                auth_result = self.authorize(
-                    context=req.context,
-                    enterprise_id=req.context.enterprise_id,
-                    team_id=req.context.team_id,
-                    user_id=req.context.user_id,
-                    actor_enterprise_id=req.context.actor_enterprise_id,
-                    actor_team_id=req.context.actor_team_id,
-                    actor_user_id=req.context.actor_user_id,
-                )
-            else:
-                auth_result = 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
-                # As App#_init_context() generates a new WebClient for this request,
-                # it's safe to modify this instance.
-                req.context.client.token = token
-                return next()
-            else:
-                # This situation can arise if:
-                # * A developer installed the app from the "Install to Workspace" button in Slack app config page
-                # * The InstallationStore failed to save or deleted the installation for this workspace
-                self.logger.error(
-                    "Although the app should be installed into this workspace, "
-                    "the AuthorizeResult (returned value from authorize) for it was not found."
-                )
-                if req.context.response_url is not None:
-                    req.context.respond(self.user_facing_authorize_error_message)  # type: ignore[misc]
-                    return BoltResponse(status=200, body="")
-                return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-
-        except SlackApiError as e:
-            self.logger.error(f"Failed to authorize with the given token ({e})")
-            return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-
-

A middleware can process request data before other middleware and listener functions.

-

Multi-workspace authorization.

-

Args

-
-
authorize
-
The function to authorize incoming requests from Slack.
-
base_logger
-
The base logger
-
user_token_resolution
-
"authed_user" or "actor"
-
user_facing_authorize_error_message
-
The user-facing error message when installation is not found
-
-

Ancestors

- -

Class variables

-
-
var authorizeAuthorize
-
-

The type of the None singleton.

-
-
var user_token_resolution : str
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class SingleTeamAuthorization -(*,
auth_test_result: slack_sdk.web.slack_response.SlackResponse | None = None,
base_logger: logging.Logger | None = None,
user_facing_authorize_error_message: str | None = None)
-
-
-
- -Expand source code - -
class SingleTeamAuthorization(Authorization):
-    def __init__(
-        self,
-        *,
-        auth_test_result: Optional[SlackResponse] = None,
-        base_logger: Optional[Logger] = None,
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        """Single-workspace authorization.
-
-        Args:
-            auth_test_result: The initial `auth.test` API call result.
-            base_logger: The base logger
-        """
-        self.auth_test_result = auth_test_result
-        self.logger = get_bolt_logger(SingleTeamAuthorization, base_logger=base_logger)
-        self.user_facing_authorize_error_message = (
-            user_facing_authorize_error_message or _build_user_facing_authorize_error_message()
-        )
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        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:
-            if not self.auth_test_result:
-                self.auth_test_result = req.context.client.auth_test()
-
-            if self.auth_test_result:
-                req.context.set_authorize_result(
-                    _to_authorize_result(
-                        auth_test_result=self.auth_test_result,
-                        token=req.context.client.token,
-                        request_user_id=req.context.user_id,
-                    )
-                )
-                return next()
-            else:
-                # Just in case
-                self.logger.error("auth.test API call result is unexpectedly None")
-                if req.context.response_url is not None:
-                    req.context.respond(self.user_facing_authorize_error_message)  # type: ignore[misc]
-                    return BoltResponse(status=200, body="")
-                return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-        except SlackApiError as e:
-            self.logger.error(f"Failed to authorize with the given token ({e})")
-            return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-
-

A middleware can process request data before other middleware and listener functions.

-

Single-workspace authorization.

-

Args

-
-
auth_test_result
-
The initial auth.test API call result.
-
base_logger
-
The base logger
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/authorization/internals.html b/docs/reference/middleware/authorization/internals.html deleted file mode 100644 index c64a7e0f3..000000000 --- a/docs/reference/middleware/authorization/internals.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - -slack_bolt.middleware.authorization.internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.authorization.internals

-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/middleware/authorization/multi_teams_authorization.html b/docs/reference/middleware/authorization/multi_teams_authorization.html deleted file mode 100644 index c2a6a7964..000000000 --- a/docs/reference/middleware/authorization/multi_teams_authorization.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - -slack_bolt.middleware.authorization.multi_teams_authorization API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.authorization.multi_teams_authorization

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class MultiTeamsAuthorization -(*,
authorize: Authorize,
base_logger: logging.Logger | None = None,
user_token_resolution: str = 'authed_user',
user_facing_authorize_error_message: str | None = None)
-
-
-
- -Expand source code - -
class MultiTeamsAuthorization(Authorization):
-    authorize: Authorize
-    user_token_resolution: str
-
-    def __init__(
-        self,
-        *,
-        authorize: Authorize,
-        base_logger: Optional[Logger] = None,
-        user_token_resolution: str = "authed_user",
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        """Multi-workspace authorization.
-
-        Args:
-            authorize: The function to authorize incoming requests from Slack.
-            base_logger: The base logger
-            user_token_resolution: "authed_user" or "actor"
-            user_facing_authorize_error_message: The user-facing error message when installation is not found
-        """
-        self.authorize = authorize
-        self.logger = get_bolt_logger(MultiTeamsAuthorization, base_logger=base_logger)
-        self.user_token_resolution = user_token_resolution
-        self.user_facing_authorize_error_message = (
-            user_facing_authorize_error_message or _build_user_facing_authorize_error_message()
-        )
-
-    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] = None
-            if self.user_token_resolution == "actor":
-                auth_result = self.authorize(
-                    context=req.context,
-                    enterprise_id=req.context.enterprise_id,
-                    team_id=req.context.team_id,
-                    user_id=req.context.user_id,
-                    actor_enterprise_id=req.context.actor_enterprise_id,
-                    actor_team_id=req.context.actor_team_id,
-                    actor_user_id=req.context.actor_user_id,
-                )
-            else:
-                auth_result = 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
-                # As App#_init_context() generates a new WebClient for this request,
-                # it's safe to modify this instance.
-                req.context.client.token = token
-                return next()
-            else:
-                # This situation can arise if:
-                # * A developer installed the app from the "Install to Workspace" button in Slack app config page
-                # * The InstallationStore failed to save or deleted the installation for this workspace
-                self.logger.error(
-                    "Although the app should be installed into this workspace, "
-                    "the AuthorizeResult (returned value from authorize) for it was not found."
-                )
-                if req.context.response_url is not None:
-                    req.context.respond(self.user_facing_authorize_error_message)  # type: ignore[misc]
-                    return BoltResponse(status=200, body="")
-                return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-
-        except SlackApiError as e:
-            self.logger.error(f"Failed to authorize with the given token ({e})")
-            return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-
-

A middleware can process request data before other middleware and listener functions.

-

Multi-workspace authorization.

-

Args

-
-
authorize
-
The function to authorize incoming requests from Slack.
-
base_logger
-
The base logger
-
user_token_resolution
-
"authed_user" or "actor"
-
user_facing_authorize_error_message
-
The user-facing error message when installation is not found
-
-

Ancestors

- -

Class variables

-
-
var authorizeAuthorize
-
-

The type of the None singleton.

-
-
var user_token_resolution : str
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/authorization/single_team_authorization.html b/docs/reference/middleware/authorization/single_team_authorization.html deleted file mode 100644 index 7687be155..000000000 --- a/docs/reference/middleware/authorization/single_team_authorization.html +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - -slack_bolt.middleware.authorization.single_team_authorization API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.authorization.single_team_authorization

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SingleTeamAuthorization -(*,
auth_test_result: slack_sdk.web.slack_response.SlackResponse | None = None,
base_logger: logging.Logger | None = None,
user_facing_authorize_error_message: str | None = None)
-
-
-
- -Expand source code - -
class SingleTeamAuthorization(Authorization):
-    def __init__(
-        self,
-        *,
-        auth_test_result: Optional[SlackResponse] = None,
-        base_logger: Optional[Logger] = None,
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        """Single-workspace authorization.
-
-        Args:
-            auth_test_result: The initial `auth.test` API call result.
-            base_logger: The base logger
-        """
-        self.auth_test_result = auth_test_result
-        self.logger = get_bolt_logger(SingleTeamAuthorization, base_logger=base_logger)
-        self.user_facing_authorize_error_message = (
-            user_facing_authorize_error_message or _build_user_facing_authorize_error_message()
-        )
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        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:
-            if not self.auth_test_result:
-                self.auth_test_result = req.context.client.auth_test()
-
-            if self.auth_test_result:
-                req.context.set_authorize_result(
-                    _to_authorize_result(
-                        auth_test_result=self.auth_test_result,
-                        token=req.context.client.token,
-                        request_user_id=req.context.user_id,
-                    )
-                )
-                return next()
-            else:
-                # Just in case
-                self.logger.error("auth.test API call result is unexpectedly None")
-                if req.context.response_url is not None:
-                    req.context.respond(self.user_facing_authorize_error_message)  # type: ignore[misc]
-                    return BoltResponse(status=200, body="")
-                return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-        except SlackApiError as e:
-            self.logger.error(f"Failed to authorize with the given token ({e})")
-            return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-
-

A middleware can process request data before other middleware and listener functions.

-

Single-workspace authorization.

-

Args

-
-
auth_test_result
-
The initial auth.test API call result.
-
base_logger
-
The base logger
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/custom_middleware.html b/docs/reference/middleware/custom_middleware.html deleted file mode 100644 index aba9dc14b..000000000 --- a/docs/reference/middleware/custom_middleware.html +++ /dev/null @@ -1,162 +0,0 @@ - - - - - - -slack_bolt.middleware.custom_middleware API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.custom_middleware

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class CustomMiddleware -(*, app_name: str, func: Callable, base_logger: logging.Logger | None = None) -
-
-
- -Expand source code - -
class CustomMiddleware(Middleware):
-    app_name: str
-    func: Callable[..., Any]
-    arg_names: MutableSequence[str]
-    logger: Logger
-
-    def __init__(self, *, app_name: str, func: Callable, base_logger: Optional[Logger] = None):
-        self.app_name = app_name
-        self.func = func
-        self.arg_names = get_arg_names_of_callable(func)
-        self.logger = get_bolt_app_logger(self.app_name, self.func, base_logger)
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        return self.func(
-            **build_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,
-                request=req,
-                response=resp,
-                next_func=next,  # type: ignore[arg-type]
-                this_func=self.func,
-            )
-        )
-
-    @property
-    def name(self) -> str:
-        return f"CustomMiddleware(func={get_name_for_callable(self.func)})"
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : MutableSequence[str]
-
-

The type of the None singleton.

-
-
var func : Callable[..., Any]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/ignoring_self_events/async_ignoring_self_events.html b/docs/reference/middleware/ignoring_self_events/async_ignoring_self_events.html deleted file mode 100644 index 4d48b16b9..000000000 --- a/docs/reference/middleware/ignoring_self_events/async_ignoring_self_events.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - -slack_bolt.middleware.ignoring_self_events.async_ignoring_self_events API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.ignoring_self_events.async_ignoring_self_events

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncIgnoringSelfEvents -(base_logger: logging.Logger | None = None,
ignoring_self_assistant_message_events_enabled: bool = True)
-
-
-
- -Expand source code - -
class AsyncIgnoringSelfEvents(IgnoringSelfEvents, AsyncMiddleware):
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        auth_result = req.context.authorize_result
-        # message events can have $.event.bot_id while it does not have its user_id
-        bot_id = req.body.get("event", {}).get("bot_id")
-        if self._is_self_event(auth_result, req.context.user_id, bot_id, req.body):  # type: ignore[arg-type]
-            if self.ignoring_self_assistant_message_events_enabled is False:
-                if is_bot_message_event_in_assistant_thread(req.body):
-                    # Assistant#bot_message handler acknowledges this pattern
-                    return await next()
-
-            self._debug_log(req.body)
-            return await req.context.ack()
-        else:
-            return await next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Ignores the events generated by this bot user itself.

-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/ignoring_self_events/ignoring_self_events.html b/docs/reference/middleware/ignoring_self_events/ignoring_self_events.html deleted file mode 100644 index 111c096c4..000000000 --- a/docs/reference/middleware/ignoring_self_events/ignoring_self_events.html +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - -slack_bolt.middleware.ignoring_self_events.ignoring_self_events API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.ignoring_self_events.ignoring_self_events

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class IgnoringSelfEvents -(base_logger: logging.Logger | None = None,
ignoring_self_assistant_message_events_enabled: bool = True)
-
-
-
- -Expand source code - -
class IgnoringSelfEvents(Middleware):
-    def __init__(
-        self,
-        base_logger: Optional[logging.Logger] = None,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-    ):
-        """Ignores the events generated by this bot user itself."""
-        self.logger = get_bolt_logger(IgnoringSelfEvents, base_logger=base_logger)
-        self.ignoring_self_assistant_message_events_enabled = ignoring_self_assistant_message_events_enabled
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        auth_result = req.context.authorize_result
-        # message events can have $.event.bot_id while it does not have its user_id
-        bot_id = req.body.get("event", {}).get("bot_id")
-        if self._is_self_event(auth_result, req.context.user_id, bot_id, req.body):  # type: ignore[arg-type]
-            if self.ignoring_self_assistant_message_events_enabled is False:
-                if is_bot_message_event_in_assistant_thread(req.body):
-                    # Assistant#bot_message handler acknowledges this pattern
-                    return next()
-
-            self._debug_log(req.body)
-            return req.context.ack()
-        else:
-            return next()
-
-    # -----------------------------------------
-
-    # It's an Events API event that isn't of type message,
-    # but the user ID might match our own app. Filter these out.
-    # However, some events still must be fired, because they can make sense.
-    events_that_should_be_kept = ["member_joined_channel", "member_left_channel"]
-
-    @classmethod
-    def _is_self_event(
-        cls,
-        auth_result: AuthorizeResult,
-        user_id: Optional[str],
-        bot_id: Optional[str],
-        body: Dict[str, Any],
-    ):
-        return (
-            auth_result is not None
-            and (
-                (user_id is not None and user_id == auth_result.bot_user_id)
-                or (bot_id is not None and bot_id == auth_result.bot_id)  # for bot_message events
-            )
-            and body.get("event") is not None
-            and body.get("event", {}).get("type") not in cls.events_that_should_be_kept
-        )
-
-    def _debug_log(self, body: dict):
-        if self.logger.level <= logging.DEBUG:
-            event = body.get("event")
-            self.logger.debug(f"Skipped self event: {event}")
-
-

A middleware can process request data before other middleware and listener functions.

-

Ignores the events generated by this bot user itself.

-

Ancestors

- -

Subclasses

- -

Class variables

-
-
var events_that_should_be_kept
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/ignoring_self_events/index.html b/docs/reference/middleware/ignoring_self_events/index.html deleted file mode 100644 index f81603f4a..000000000 --- a/docs/reference/middleware/ignoring_self_events/index.html +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - -slack_bolt.middleware.ignoring_self_events API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.ignoring_self_events

-
-
-
-
-

Sub-modules

-
-
slack_bolt.middleware.ignoring_self_events.async_ignoring_self_events
-
-
-
-
slack_bolt.middleware.ignoring_self_events.ignoring_self_events
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class IgnoringSelfEvents -(base_logger: logging.Logger | None = None,
ignoring_self_assistant_message_events_enabled: bool = True)
-
-
-
- -Expand source code - -
class IgnoringSelfEvents(Middleware):
-    def __init__(
-        self,
-        base_logger: Optional[logging.Logger] = None,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-    ):
-        """Ignores the events generated by this bot user itself."""
-        self.logger = get_bolt_logger(IgnoringSelfEvents, base_logger=base_logger)
-        self.ignoring_self_assistant_message_events_enabled = ignoring_self_assistant_message_events_enabled
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        auth_result = req.context.authorize_result
-        # message events can have $.event.bot_id while it does not have its user_id
-        bot_id = req.body.get("event", {}).get("bot_id")
-        if self._is_self_event(auth_result, req.context.user_id, bot_id, req.body):  # type: ignore[arg-type]
-            if self.ignoring_self_assistant_message_events_enabled is False:
-                if is_bot_message_event_in_assistant_thread(req.body):
-                    # Assistant#bot_message handler acknowledges this pattern
-                    return next()
-
-            self._debug_log(req.body)
-            return req.context.ack()
-        else:
-            return next()
-
-    # -----------------------------------------
-
-    # It's an Events API event that isn't of type message,
-    # but the user ID might match our own app. Filter these out.
-    # However, some events still must be fired, because they can make sense.
-    events_that_should_be_kept = ["member_joined_channel", "member_left_channel"]
-
-    @classmethod
-    def _is_self_event(
-        cls,
-        auth_result: AuthorizeResult,
-        user_id: Optional[str],
-        bot_id: Optional[str],
-        body: Dict[str, Any],
-    ):
-        return (
-            auth_result is not None
-            and (
-                (user_id is not None and user_id == auth_result.bot_user_id)
-                or (bot_id is not None and bot_id == auth_result.bot_id)  # for bot_message events
-            )
-            and body.get("event") is not None
-            and body.get("event", {}).get("type") not in cls.events_that_should_be_kept
-        )
-
-    def _debug_log(self, body: dict):
-        if self.logger.level <= logging.DEBUG:
-            event = body.get("event")
-            self.logger.debug(f"Skipped self event: {event}")
-
-

A middleware can process request data before other middleware and listener functions.

-

Ignores the events generated by this bot user itself.

-

Ancestors

- -

Subclasses

- -

Class variables

-
-
var events_that_should_be_kept
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/index.html b/docs/reference/middleware/index.html deleted file mode 100644 index 153342bc1..000000000 --- a/docs/reference/middleware/index.html +++ /dev/null @@ -1,1210 +0,0 @@ - - - - - - -slack_bolt.middleware API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware

-
-
-

A middleware processes request data and calls next() method -if the execution chain should continue running the following middleware.

-

Middleware can be used globally before all listener executions. -It's also possible to run a middleware only for a particular listener.

-
-
-

Sub-modules

-
-
slack_bolt.middleware.assistant
-
-
-
-
slack_bolt.middleware.async_builtins
-
-
-
-
slack_bolt.middleware.async_custom_middleware
-
-
-
-
slack_bolt.middleware.async_middleware
-
-
-
-
slack_bolt.middleware.async_middleware_error_handler
-
-
-
-
slack_bolt.middleware.attaching_conversation_kwargs
-
-
-
-
slack_bolt.middleware.attaching_function_token
-
-
-
-
slack_bolt.middleware.authorization
-
-
-
-
slack_bolt.middleware.custom_middleware
-
-
-
-
slack_bolt.middleware.ignoring_self_events
-
-
-
-
slack_bolt.middleware.message_listener_matches
-
-
-
-
slack_bolt.middleware.middleware
-
-
-
-
slack_bolt.middleware.middleware_error_handler
-
-
-
-
slack_bolt.middleware.request_verification
-
-
-
-
slack_bolt.middleware.ssl_check
-
-
-
-
slack_bolt.middleware.url_verification
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AttachingConversationKwargs -(thread_context_store: AssistantThreadContextStore | None = None) -
-
-
- -Expand source code - -
class AttachingConversationKwargs(Middleware):
-
-    thread_context_store: Optional[AssistantThreadContextStore]
-
-    def __init__(self, thread_context_store: Optional[AssistantThreadContextStore] = None):
-        self.thread_context_store = thread_context_store
-
-    def process(self, *, req: BoltRequest, resp: BoltResponse, next: Callable[[], BoltResponse]) -> Optional[BoltResponse]:
-        event = to_event(req.body)
-        if event is None:
-            return next()
-        if req.context.channel_id is None:
-            return next()
-
-        if is_assistant_event(req.body):
-            # TODO: eventually we might remove this assistant specific logic
-            assistant = AssistantUtilities(
-                payload=event,
-                context=req.context,
-                thread_context_store=self.thread_context_store,
-            )
-            req.context["say"] = assistant.say
-            req.context["set_title"] = assistant.set_title
-            req.context["get_thread_context"] = assistant.get_thread_context
-            req.context["save_thread_context"] = assistant.save_thread_context
-
-        if (
-            is_im_message_event(req.body)
-            or is_assistant_thread_started_event(req.body)
-            or is_assistant_thread_context_changed_event(req.body)
-            or is_app_home_opened_event(req.body, tab="messages")
-        ):
-            req.context["set_suggested_prompts"] = SetSuggestedPrompts(
-                client=req.context.client,
-                channel_id=req.context.channel_id,
-                thread_ts=req.context.thread_ts,
-            )
-
-        # TODO: in the future we might want to introduce a "proper" extract_ts utility
-        thread_ts_or_ts = req.context.thread_ts or event.get("ts")
-        if thread_ts_or_ts:
-            req.context["set_status"] = SetStatus(
-                client=req.context.client,
-                channel_id=req.context.channel_id,
-                thread_ts=thread_ts_or_ts,
-            )
-            req.context["say_stream"] = SayStream(
-                client=req.context.client,
-                channel=req.context.channel_id,
-                recipient_team_id=req.context.team_id or req.context.enterprise_id,
-                recipient_user_id=req.context.user_id,
-                thread_ts=thread_ts_or_ts,
-            )
-        return next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var thread_context_storeAssistantThreadContextStore | None
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class AttachingFunctionToken -
-
-
- -Expand source code - -
class AttachingFunctionToken(Middleware):
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # This method is not supposed to be invoked by bolt-python users
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        if req.context.function_bot_access_token is not None:
-            req.context.client.token = req.context.function_bot_access_token
-
-        return next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Inherited members

- -
-
-class CustomMiddleware -(*, app_name: str, func: Callable, base_logger: logging.Logger | None = None) -
-
-
- -Expand source code - -
class CustomMiddleware(Middleware):
-    app_name: str
-    func: Callable[..., Any]
-    arg_names: MutableSequence[str]
-    logger: Logger
-
-    def __init__(self, *, app_name: str, func: Callable, base_logger: Optional[Logger] = None):
-        self.app_name = app_name
-        self.func = func
-        self.arg_names = get_arg_names_of_callable(func)
-        self.logger = get_bolt_app_logger(self.app_name, self.func, base_logger)
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        return self.func(
-            **build_required_kwargs(
-                logger=self.logger,
-                required_arg_names=self.arg_names,
-                request=req,
-                response=resp,
-                next_func=next,  # type: ignore[arg-type]
-                this_func=self.func,
-            )
-        )
-
-    @property
-    def name(self) -> str:
-        return f"CustomMiddleware(func={get_name_for_callable(self.func)})"
-
-

A middleware can process request data before other middleware and listener functions.

-

Ancestors

- -

Class variables

-
-
var app_name : str
-
-

The type of the None singleton.

-
-
var arg_names : MutableSequence[str]
-
-

The type of the None singleton.

-
-
var func : Callable[..., Any]
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class IgnoringSelfEvents -(base_logger: logging.Logger | None = None,
ignoring_self_assistant_message_events_enabled: bool = True)
-
-
-
- -Expand source code - -
class IgnoringSelfEvents(Middleware):
-    def __init__(
-        self,
-        base_logger: Optional[logging.Logger] = None,
-        ignoring_self_assistant_message_events_enabled: bool = True,
-    ):
-        """Ignores the events generated by this bot user itself."""
-        self.logger = get_bolt_logger(IgnoringSelfEvents, base_logger=base_logger)
-        self.ignoring_self_assistant_message_events_enabled = ignoring_self_assistant_message_events_enabled
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        auth_result = req.context.authorize_result
-        # message events can have $.event.bot_id while it does not have its user_id
-        bot_id = req.body.get("event", {}).get("bot_id")
-        if self._is_self_event(auth_result, req.context.user_id, bot_id, req.body):  # type: ignore[arg-type]
-            if self.ignoring_self_assistant_message_events_enabled is False:
-                if is_bot_message_event_in_assistant_thread(req.body):
-                    # Assistant#bot_message handler acknowledges this pattern
-                    return next()
-
-            self._debug_log(req.body)
-            return req.context.ack()
-        else:
-            return next()
-
-    # -----------------------------------------
-
-    # It's an Events API event that isn't of type message,
-    # but the user ID might match our own app. Filter these out.
-    # However, some events still must be fired, because they can make sense.
-    events_that_should_be_kept = ["member_joined_channel", "member_left_channel"]
-
-    @classmethod
-    def _is_self_event(
-        cls,
-        auth_result: AuthorizeResult,
-        user_id: Optional[str],
-        bot_id: Optional[str],
-        body: Dict[str, Any],
-    ):
-        return (
-            auth_result is not None
-            and (
-                (user_id is not None and user_id == auth_result.bot_user_id)
-                or (bot_id is not None and bot_id == auth_result.bot_id)  # for bot_message events
-            )
-            and body.get("event") is not None
-            and body.get("event", {}).get("type") not in cls.events_that_should_be_kept
-        )
-
-    def _debug_log(self, body: dict):
-        if self.logger.level <= logging.DEBUG:
-            event = body.get("event")
-            self.logger.debug(f"Skipped self event: {event}")
-
-

A middleware can process request data before other middleware and listener functions.

-

Ignores the events generated by this bot user itself.

-

Ancestors

- -

Subclasses

- -

Class variables

-
-
var events_that_should_be_kept
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class Middleware -
-
-
- -Expand source code - -
class Middleware(metaclass=ABCMeta):
-    """A middleware can process request data before other middleware and listener functions."""
-
-    @abstractmethod
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> Optional[BoltResponse]:
-        """Processes a request data before other middleware and listeners.
-        A middleware calls `next()` function if the chain should continue.
-
-            @app.middleware
-            def simple_middleware(req, resp, next):
-                # do something here
-                next()
-
-        This `process(req, resp, next)` method is supposed to be invoked only inside bolt-python.
-        If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead.
-
-            @app.middleware
-            def simple_middleware(req, resp, next_):
-                # do something here
-                next_()
-
-        Args:
-            req: The incoming request
-            resp: The response
-            next: The function to tell the chain that it can continue
-
-        Returns:
-            Processed response (optional)
-        """
-        raise NotImplementedError()
-
-    @property
-    def name(self) -> str:
-        """The name of this middleware"""
-        return f"{self.__module__}.{self.__class__.__name__}"
-
-

A middleware can process request data before other middleware and listener functions.

-

Subclasses

- -

Instance variables

-
-
prop name : str
-
-
- -Expand source code - -
@property
-def name(self) -> str:
-    """The name of this middleware"""
-    return f"{self.__module__}.{self.__class__.__name__}"
-
-

The name of this middleware

-
-
-

Methods

-
-
-def process(self,
*,
req: BoltRequest,
resp: BoltResponse,
next: Callable[[], BoltResponse]) ‑> BoltResponse | None
-
-
-
- -Expand source code - -
@abstractmethod
-def process(
-    self,
-    *,
-    req: BoltRequest,
-    resp: BoltResponse,
-    # As this method is not supposed to be invoked by bolt-python users,
-    # the naming conflict with the built-in one affects
-    # only the internals of this method
-    next: Callable[[], BoltResponse],
-) -> Optional[BoltResponse]:
-    """Processes a request data before other middleware and listeners.
-    A middleware calls `next()` function if the chain should continue.
-
-        @app.middleware
-        def simple_middleware(req, resp, next):
-            # do something here
-            next()
-
-    This `process(req, resp, next)` method is supposed to be invoked only inside bolt-python.
-    If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead.
-
-        @app.middleware
-        def simple_middleware(req, resp, next_):
-            # do something here
-            next_()
-
-    Args:
-        req: The incoming request
-        resp: The response
-        next: The function to tell the chain that it can continue
-
-    Returns:
-        Processed response (optional)
-    """
-    raise NotImplementedError()
-
-

Processes a request data before other middleware and listeners. -A middleware calls next() function if the chain should continue.

-
@app.middleware
-def simple_middleware(req, resp, next):
-    # do something here
-    next()
-
-

This process(req, resp, next) method is supposed to be invoked only inside bolt-python. -If you want to avoid the name next() in your middleware functions, you can use next_() method instead.

-
@app.middleware
-def simple_middleware(req, resp, next_):
-    # do something here
-    next_()
-
-

Args

-
-
req
-
The incoming request
-
resp
-
The response
-
next
-
The function to tell the chain that it can continue
-
-

Returns

-

Processed response (optional)

-
-
-
-
-class MultiTeamsAuthorization -(*,
authorize: Authorize,
base_logger: logging.Logger | None = None,
user_token_resolution: str = 'authed_user',
user_facing_authorize_error_message: str | None = None)
-
-
-
- -Expand source code - -
class MultiTeamsAuthorization(Authorization):
-    authorize: Authorize
-    user_token_resolution: str
-
-    def __init__(
-        self,
-        *,
-        authorize: Authorize,
-        base_logger: Optional[Logger] = None,
-        user_token_resolution: str = "authed_user",
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        """Multi-workspace authorization.
-
-        Args:
-            authorize: The function to authorize incoming requests from Slack.
-            base_logger: The base logger
-            user_token_resolution: "authed_user" or "actor"
-            user_facing_authorize_error_message: The user-facing error message when installation is not found
-        """
-        self.authorize = authorize
-        self.logger = get_bolt_logger(MultiTeamsAuthorization, base_logger=base_logger)
-        self.user_token_resolution = user_token_resolution
-        self.user_facing_authorize_error_message = (
-            user_facing_authorize_error_message or _build_user_facing_authorize_error_message()
-        )
-
-    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] = None
-            if self.user_token_resolution == "actor":
-                auth_result = self.authorize(
-                    context=req.context,
-                    enterprise_id=req.context.enterprise_id,
-                    team_id=req.context.team_id,
-                    user_id=req.context.user_id,
-                    actor_enterprise_id=req.context.actor_enterprise_id,
-                    actor_team_id=req.context.actor_team_id,
-                    actor_user_id=req.context.actor_user_id,
-                )
-            else:
-                auth_result = 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
-                # As App#_init_context() generates a new WebClient for this request,
-                # it's safe to modify this instance.
-                req.context.client.token = token
-                return next()
-            else:
-                # This situation can arise if:
-                # * A developer installed the app from the "Install to Workspace" button in Slack app config page
-                # * The InstallationStore failed to save or deleted the installation for this workspace
-                self.logger.error(
-                    "Although the app should be installed into this workspace, "
-                    "the AuthorizeResult (returned value from authorize) for it was not found."
-                )
-                if req.context.response_url is not None:
-                    req.context.respond(self.user_facing_authorize_error_message)  # type: ignore[misc]
-                    return BoltResponse(status=200, body="")
-                return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-
-        except SlackApiError as e:
-            self.logger.error(f"Failed to authorize with the given token ({e})")
-            return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-
-

A middleware can process request data before other middleware and listener functions.

-

Multi-workspace authorization.

-

Args

-
-
authorize
-
The function to authorize incoming requests from Slack.
-
base_logger
-
The base logger
-
user_token_resolution
-
"authed_user" or "actor"
-
user_facing_authorize_error_message
-
The user-facing error message when installation is not found
-
-

Ancestors

- -

Class variables

-
-
var authorizeAuthorize
-
-

The type of the None singleton.

-
-
var user_token_resolution : str
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class RequestVerification -(signing_secret: str, base_logger: logging.Logger | None = None) -
-
-
- -Expand source code - -
class RequestVerification(Middleware):
-    def __init__(self, signing_secret: str, base_logger: Optional[Logger] = None):
-        """Verifies an incoming request by checking the validity of
-        `x-slack-signature`, `x-slack-request-timestamp`, and its body data.
-
-        Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details.
-
-        Args:
-            signing_secret: The signing secret
-            base_logger: The base logger
-        """
-        self._signing_secret = signing_secret
-        self._verifier: Optional[SignatureVerifier] = None
-        self.logger = get_bolt_logger(RequestVerification, base_logger=base_logger)
-
-    @property
-    def verifier(self) -> SignatureVerifier:
-        # Defer initialization to avoid errors during start up
-        if self._verifier is None:
-            self._verifier = SignatureVerifier(signing_secret=self._signing_secret)
-        return self._verifier
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        if self._can_skip(req.mode, req.body):
-            return next()
-
-        body = req.raw_body
-        timestamp = req.headers.get("x-slack-request-timestamp", ["0"])[0]
-        signature = req.headers.get("x-slack-signature", [""])[0]
-        if self.verifier.is_valid(body, timestamp, signature):
-            return next()
-        else:
-            self._debug_log_error(signature, timestamp, body)
-            return self._build_error_response()
-
-    # -----------------------------------------
-
-    @staticmethod
-    def _can_skip(mode: str, body: Dict[str, Any]) -> bool:
-        return mode == "socket_mode"
-
-    @staticmethod
-    def _build_error_response() -> BoltResponse:
-        return BoltResponse(status=401, body={"error": "invalid request"})
-
-    def _debug_log_error(self, signature, timestamp, body) -> None:
-        self.logger.info(
-            "Invalid request signature detected " f"(signature: {signature}, timestamp: {timestamp}, body: {body})"
-        )
-
-

A middleware can process request data before other middleware and listener functions.

-

Verifies an incoming request by checking the validity of -x-slack-signature, x-slack-request-timestamp, and its body data.

-

Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details.

-

Args

-
-
signing_secret
-
The signing secret
-
base_logger
-
The base logger
-
-

Ancestors

- -

Subclasses

- -

Instance variables

-
-
prop verifier : slack_sdk.signature.SignatureVerifier
-
-
- -Expand source code - -
@property
-def verifier(self) -> SignatureVerifier:
-    # Defer initialization to avoid errors during start up
-    if self._verifier is None:
-        self._verifier = SignatureVerifier(signing_secret=self._signing_secret)
-    return self._verifier
-
-
-
-
-

Inherited members

- -
-
-class SingleTeamAuthorization -(*,
auth_test_result: slack_sdk.web.slack_response.SlackResponse | None = None,
base_logger: logging.Logger | None = None,
user_facing_authorize_error_message: str | None = None)
-
-
-
- -Expand source code - -
class SingleTeamAuthorization(Authorization):
-    def __init__(
-        self,
-        *,
-        auth_test_result: Optional[SlackResponse] = None,
-        base_logger: Optional[Logger] = None,
-        user_facing_authorize_error_message: Optional[str] = None,
-    ):
-        """Single-workspace authorization.
-
-        Args:
-            auth_test_result: The initial `auth.test` API call result.
-            base_logger: The base logger
-        """
-        self.auth_test_result = auth_test_result
-        self.logger = get_bolt_logger(SingleTeamAuthorization, base_logger=base_logger)
-        self.user_facing_authorize_error_message = (
-            user_facing_authorize_error_message or _build_user_facing_authorize_error_message()
-        )
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        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:
-            if not self.auth_test_result:
-                self.auth_test_result = req.context.client.auth_test()
-
-            if self.auth_test_result:
-                req.context.set_authorize_result(
-                    _to_authorize_result(
-                        auth_test_result=self.auth_test_result,
-                        token=req.context.client.token,
-                        request_user_id=req.context.user_id,
-                    )
-                )
-                return next()
-            else:
-                # Just in case
-                self.logger.error("auth.test API call result is unexpectedly None")
-                if req.context.response_url is not None:
-                    req.context.respond(self.user_facing_authorize_error_message)  # type: ignore[misc]
-                    return BoltResponse(status=200, body="")
-                return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-        except SlackApiError as e:
-            self.logger.error(f"Failed to authorize with the given token ({e})")
-            return _build_user_facing_error_response(self.user_facing_authorize_error_message)
-
-

A middleware can process request data before other middleware and listener functions.

-

Single-workspace authorization.

-

Args

-
-
auth_test_result
-
The initial auth.test API call result.
-
base_logger
-
The base logger
-
-

Ancestors

- -

Inherited members

- -
-
-class SslCheck -(verification_token: str | None = None,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class SslCheck(Middleware):
-    verification_token: Optional[str]
-    logger: Logger
-
-    def __init__(
-        self,
-        verification_token: Optional[str] = None,
-        base_logger: Optional[Logger] = None,
-    ):
-        """Handles `ssl_check` requests.
-        Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details.
-
-        Args:
-            verification_token: The verification token to check
-                (optional as it's already deprecated - https://docs.slack.dev/authentication/verifying-requests-from-slack/#deprecation)
-            base_logger: The base logger
-        """  # noqa: E501
-        self.verification_token = verification_token
-        self.logger = get_bolt_logger(SslCheck, base_logger=base_logger)
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        if self._is_ssl_check_request(req.body):
-            if self._verify_token_if_needed(req.body):
-                return self._build_error_response()
-            return self._build_success_response()
-        else:
-            return next()
-
-    # -----------------------------------------
-
-    @staticmethod
-    def _is_ssl_check_request(body: dict):
-        return "ssl_check" in body and body["ssl_check"] == "1"
-
-    def _verify_token_if_needed(self, body: dict):
-        return self.verification_token and self.verification_token == body["token"]
-
-    @staticmethod
-    def _build_success_response() -> BoltResponse:
-        return BoltResponse(status=200, body="")
-
-    @staticmethod
-    def _build_error_response() -> BoltResponse:
-        return BoltResponse(status=401, body={"error": "invalid verification token"})
-
-

A middleware can process request data before other middleware and listener functions.

-

Handles slack_bolt.middleware.ssl_check requests. -Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details.

-

Args

-
-
verification_token
-
The verification token to check -(optional as it's already deprecated - https://docs.slack.dev/authentication/verifying-requests-from-slack/#deprecation)
-
base_logger
-
The base logger
-
-

Ancestors

- -

Subclasses

- -

Class variables

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
var verification_token : str | None
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-class UrlVerification -(base_logger: logging.Logger | None = None) -
-
-
- -Expand source code - -
class UrlVerification(Middleware):
-    def __init__(self, base_logger: Optional[Logger] = None):
-        """Handles url_verification requests.
-
-        Refer to https://docs.slack.dev/reference/events/url_verification/ for details.
-
-        Args:
-            base_logger: The base logger
-        """
-        self.logger = get_bolt_logger(UrlVerification, base_logger=base_logger)
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        if self._is_url_verification_request(req.body):
-            return self._build_success_response(req.body)
-        else:
-            return next()
-
-    # -----------------------------------------
-
-    @staticmethod
-    def _is_url_verification_request(body: dict) -> bool:
-        return body is not None and body.get("type") == "url_verification"
-
-    @staticmethod
-    def _build_success_response(body: dict) -> BoltResponse:
-        return BoltResponse(status=200, body={"challenge": body.get("challenge")})
-
-

A middleware can process request data before other middleware and listener functions.

-

Handles url_verification requests.

-

Refer to https://docs.slack.dev/reference/events/url_verification/ for details.

-

Args

-
-
base_logger
-
The base logger
-
-

Ancestors

- -

Subclasses

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/message_listener_matches/async_message_listener_matches.html b/docs/reference/middleware/message_listener_matches/async_message_listener_matches.html deleted file mode 100644 index 9cbee09ca..000000000 --- a/docs/reference/middleware/message_listener_matches/async_message_listener_matches.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - -slack_bolt.middleware.message_listener_matches.async_message_listener_matches API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.message_listener_matches.async_message_listener_matches

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncMessageListenerMatches -(keyword: str | Pattern) -
-
-
- -Expand source code - -
class AsyncMessageListenerMatches(AsyncMiddleware):
-    def __init__(self, keyword: Union[str, Pattern]):
-        """Captures matched keywords and saves the values in context."""
-        self.keyword = keyword
-
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        text = req.body.get("event", {}).get("text", "")
-        if text:
-            m: Optional[Union[Sequence]] = re.findall(self.keyword, text)
-            if m is not None and m != []:
-                if type(m[0]) is not tuple:
-                    m = tuple(m)
-                else:
-                    m = m[0]
-                req.context["matches"] = m  # tuple or list
-                return await next()
-
-        # As the text doesn't match, skip running the listener
-        return resp
-
-

A middleware can process request data before other middleware and listener functions.

-

Captures matched keywords and saves the values in context.

-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/message_listener_matches/index.html b/docs/reference/middleware/message_listener_matches/index.html deleted file mode 100644 index 29dfbb861..000000000 --- a/docs/reference/middleware/message_listener_matches/index.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - -slack_bolt.middleware.message_listener_matches API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.message_listener_matches

-
-
-
-
-

Sub-modules

-
-
slack_bolt.middleware.message_listener_matches.async_message_listener_matches
-
-
-
-
slack_bolt.middleware.message_listener_matches.message_listener_matches
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class MessageListenerMatches -(keyword: str | Pattern) -
-
-
- -Expand source code - -
class MessageListenerMatches(Middleware):
-    def __init__(self, keyword: Union[str, Pattern]):
-        """Captures matched keywords and saves the values in context."""
-        self.keyword = keyword
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        text = req.body.get("event", {}).get("text", "")
-        if text:
-            m: Optional[Union[Sequence]] = re.findall(self.keyword, text)
-            if m is not None and m != []:
-                if type(m[0]) is not tuple:
-                    m = tuple(m)
-                else:
-                    m = m[0]
-                req.context["matches"] = m  # tuple or list
-                return next()
-
-        # As the text doesn't match, skip running the listener
-        return resp
-
-

A middleware can process request data before other middleware and listener functions.

-

Captures matched keywords and saves the values in context.

-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/message_listener_matches/message_listener_matches.html b/docs/reference/middleware/message_listener_matches/message_listener_matches.html deleted file mode 100644 index 35b5bfa7a..000000000 --- a/docs/reference/middleware/message_listener_matches/message_listener_matches.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - -slack_bolt.middleware.message_listener_matches.message_listener_matches API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.message_listener_matches.message_listener_matches

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class MessageListenerMatches -(keyword: str | Pattern) -
-
-
- -Expand source code - -
class MessageListenerMatches(Middleware):
-    def __init__(self, keyword: Union[str, Pattern]):
-        """Captures matched keywords and saves the values in context."""
-        self.keyword = keyword
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        text = req.body.get("event", {}).get("text", "")
-        if text:
-            m: Optional[Union[Sequence]] = re.findall(self.keyword, text)
-            if m is not None and m != []:
-                if type(m[0]) is not tuple:
-                    m = tuple(m)
-                else:
-                    m = m[0]
-                req.context["matches"] = m  # tuple or list
-                return next()
-
-        # As the text doesn't match, skip running the listener
-        return resp
-
-

A middleware can process request data before other middleware and listener functions.

-

Captures matched keywords and saves the values in context.

-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/middleware.html b/docs/reference/middleware/middleware.html deleted file mode 100644 index efa8e6c30..000000000 --- a/docs/reference/middleware/middleware.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - -slack_bolt.middleware.middleware API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.middleware

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Middleware -
-
-
- -Expand source code - -
class Middleware(metaclass=ABCMeta):
-    """A middleware can process request data before other middleware and listener functions."""
-
-    @abstractmethod
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> Optional[BoltResponse]:
-        """Processes a request data before other middleware and listeners.
-        A middleware calls `next()` function if the chain should continue.
-
-            @app.middleware
-            def simple_middleware(req, resp, next):
-                # do something here
-                next()
-
-        This `process(req, resp, next)` method is supposed to be invoked only inside bolt-python.
-        If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead.
-
-            @app.middleware
-            def simple_middleware(req, resp, next_):
-                # do something here
-                next_()
-
-        Args:
-            req: The incoming request
-            resp: The response
-            next: The function to tell the chain that it can continue
-
-        Returns:
-            Processed response (optional)
-        """
-        raise NotImplementedError()
-
-    @property
-    def name(self) -> str:
-        """The name of this middleware"""
-        return f"{self.__module__}.{self.__class__.__name__}"
-
-

A middleware can process request data before other middleware and listener functions.

-

Subclasses

- -

Instance variables

-
-
prop name : str
-
-
- -Expand source code - -
@property
-def name(self) -> str:
-    """The name of this middleware"""
-    return f"{self.__module__}.{self.__class__.__name__}"
-
-

The name of this middleware

-
-
-

Methods

-
-
-def process(self,
*,
req: BoltRequest,
resp: BoltResponse,
next: Callable[[], BoltResponse]) ‑> BoltResponse | None
-
-
-
- -Expand source code - -
@abstractmethod
-def process(
-    self,
-    *,
-    req: BoltRequest,
-    resp: BoltResponse,
-    # As this method is not supposed to be invoked by bolt-python users,
-    # the naming conflict with the built-in one affects
-    # only the internals of this method
-    next: Callable[[], BoltResponse],
-) -> Optional[BoltResponse]:
-    """Processes a request data before other middleware and listeners.
-    A middleware calls `next()` function if the chain should continue.
-
-        @app.middleware
-        def simple_middleware(req, resp, next):
-            # do something here
-            next()
-
-    This `process(req, resp, next)` method is supposed to be invoked only inside bolt-python.
-    If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead.
-
-        @app.middleware
-        def simple_middleware(req, resp, next_):
-            # do something here
-            next_()
-
-    Args:
-        req: The incoming request
-        resp: The response
-        next: The function to tell the chain that it can continue
-
-    Returns:
-        Processed response (optional)
-    """
-    raise NotImplementedError()
-
-

Processes a request data before other middleware and listeners. -A middleware calls next() function if the chain should continue.

-
@app.middleware
-def simple_middleware(req, resp, next):
-    # do something here
-    next()
-
-

This process(req, resp, next) method is supposed to be invoked only inside bolt-python. -If you want to avoid the name next() in your middleware functions, you can use next_() method instead.

-
@app.middleware
-def simple_middleware(req, resp, next_):
-    # do something here
-    next_()
-
-

Args

-
-
req
-
The incoming request
-
resp
-
The response
-
next
-
The function to tell the chain that it can continue
-
-

Returns

-

Processed response (optional)

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/middleware/middleware_error_handler.html b/docs/reference/middleware/middleware_error_handler.html deleted file mode 100644 index 1c5319feb..000000000 --- a/docs/reference/middleware/middleware_error_handler.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - -slack_bolt.middleware.middleware_error_handler API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.middleware_error_handler

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class CustomMiddlewareErrorHandler -(logger: logging.Logger,
func: Callable[..., BoltResponse | None])
-
-
-
- -Expand source code - -
class CustomMiddlewareErrorHandler(MiddlewareErrorHandler):
-    def __init__(self, logger: Logger, func: Callable[..., Optional[BoltResponse]]):
-        self.func = func
-        self.logger = logger
-        self.arg_names = get_arg_names_of_callable(func)
-
-    def handle(
-        self,
-        error: Exception,
-        request: BoltRequest,
-        response: Optional[BoltResponse],
-    ):
-        kwargs: Dict[str, Any] = build_required_kwargs(
-            required_arg_names=self.arg_names,
-            logger=self.logger,
-            error=error,
-            request=request,
-            response=response,
-            next_keys_required=False,
-        )
-        returned_response = self.func(**kwargs)
-        if returned_response is not None and isinstance(returned_response, BoltResponse):
-            assert response is not None, "response must be provided when returning a BoltResponse from an error handler"
-            response.status = returned_response.status
-            response.headers = returned_response.headers
-            response.body = returned_response.body
-
-
-

Ancestors

- -

Inherited members

- -
-
-class DefaultMiddlewareErrorHandler -(logger: logging.Logger) -
-
-
- -Expand source code - -
class DefaultMiddlewareErrorHandler(MiddlewareErrorHandler):
-    def __init__(self, logger: Logger):
-        self.logger = logger
-
-    def handle(
-        self,
-        error: Exception,
-        request: BoltRequest,
-        response: Optional[BoltResponse],
-    ):
-        message = f"Failed to run a middleware (error: {error})"
-        self.logger.exception(message)
-
-
-

Ancestors

- -

Inherited members

- -
-
-class MiddlewareErrorHandler -
-
-
- -Expand source code - -
class MiddlewareErrorHandler(metaclass=ABCMeta):
-    @abstractmethod
-    def handle(
-        self,
-        error: Exception,
-        request: BoltRequest,
-        response: Optional[BoltResponse],  # TODO: why is this optional
-    ) -> None:
-        """Handles an unhandled exception.
-
-        Args:
-            error: The raised exception.
-            request: The request.
-            response: The response.
-        """
-        raise NotImplementedError()
-
-
-

Subclasses

- -

Methods

-
-
-def handle(self,
error: Exception,
request: BoltRequest,
response: BoltResponse | None) ‑> None
-
-
-
- -Expand source code - -
@abstractmethod
-def handle(
-    self,
-    error: Exception,
-    request: BoltRequest,
-    response: Optional[BoltResponse],  # TODO: why is this optional
-) -> None:
-    """Handles an unhandled exception.
-
-    Args:
-        error: The raised exception.
-        request: The request.
-        response: The response.
-    """
-    raise NotImplementedError()
-
-

Handles an unhandled exception.

-

Args

-
-
error
-
The raised exception.
-
request
-
The request.
-
response
-
The response.
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/middleware/request_verification/async_request_verification.html b/docs/reference/middleware/request_verification/async_request_verification.html deleted file mode 100644 index 192f77933..000000000 --- a/docs/reference/middleware/request_verification/async_request_verification.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - -slack_bolt.middleware.request_verification.async_request_verification API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.request_verification.async_request_verification

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncRequestVerification -(signing_secret: str, base_logger: logging.Logger | None = None) -
-
-
- -Expand source code - -
class AsyncRequestVerification(RequestVerification, AsyncMiddleware):
-    """Verifies an incoming request by checking the validity of
-    `x-slack-signature`, `x-slack-request-timestamp`, and its body data.
-
-    Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details.
-    """
-
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        if self._can_skip(req.mode, req.body):
-            return await next()
-
-        body = req.raw_body
-        timestamp = req.headers.get("x-slack-request-timestamp", ["0"])[0]
-        signature = req.headers.get("x-slack-signature", [""])[0]
-        if self.verifier.is_valid(body, timestamp, signature):
-            return await next()
-        else:
-            self._debug_log_error(signature, timestamp, body)
-            return self._build_error_response()
-
-

Verifies an incoming request by checking the validity of -x-slack-signature, x-slack-request-timestamp, and its body data.

-

Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details.

-

Verifies an incoming request by checking the validity of -x-slack-signature, x-slack-request-timestamp, and its body data.

-

Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details.

-

Args

-
-
signing_secret
-
The signing secret
-
base_logger
-
The base logger
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/request_verification/index.html b/docs/reference/middleware/request_verification/index.html deleted file mode 100644 index 50a8676b5..000000000 --- a/docs/reference/middleware/request_verification/index.html +++ /dev/null @@ -1,211 +0,0 @@ - - - - - - -slack_bolt.middleware.request_verification API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.request_verification

-
-
-
-
-

Sub-modules

-
-
slack_bolt.middleware.request_verification.async_request_verification
-
-
-
-
slack_bolt.middleware.request_verification.request_verification
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class RequestVerification -(signing_secret: str, base_logger: logging.Logger | None = None) -
-
-
- -Expand source code - -
class RequestVerification(Middleware):
-    def __init__(self, signing_secret: str, base_logger: Optional[Logger] = None):
-        """Verifies an incoming request by checking the validity of
-        `x-slack-signature`, `x-slack-request-timestamp`, and its body data.
-
-        Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details.
-
-        Args:
-            signing_secret: The signing secret
-            base_logger: The base logger
-        """
-        self._signing_secret = signing_secret
-        self._verifier: Optional[SignatureVerifier] = None
-        self.logger = get_bolt_logger(RequestVerification, base_logger=base_logger)
-
-    @property
-    def verifier(self) -> SignatureVerifier:
-        # Defer initialization to avoid errors during start up
-        if self._verifier is None:
-            self._verifier = SignatureVerifier(signing_secret=self._signing_secret)
-        return self._verifier
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        if self._can_skip(req.mode, req.body):
-            return next()
-
-        body = req.raw_body
-        timestamp = req.headers.get("x-slack-request-timestamp", ["0"])[0]
-        signature = req.headers.get("x-slack-signature", [""])[0]
-        if self.verifier.is_valid(body, timestamp, signature):
-            return next()
-        else:
-            self._debug_log_error(signature, timestamp, body)
-            return self._build_error_response()
-
-    # -----------------------------------------
-
-    @staticmethod
-    def _can_skip(mode: str, body: Dict[str, Any]) -> bool:
-        return mode == "socket_mode"
-
-    @staticmethod
-    def _build_error_response() -> BoltResponse:
-        return BoltResponse(status=401, body={"error": "invalid request"})
-
-    def _debug_log_error(self, signature, timestamp, body) -> None:
-        self.logger.info(
-            "Invalid request signature detected " f"(signature: {signature}, timestamp: {timestamp}, body: {body})"
-        )
-
-

A middleware can process request data before other middleware and listener functions.

-

Verifies an incoming request by checking the validity of -x-slack-signature, x-slack-request-timestamp, and its body data.

-

Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details.

-

Args

-
-
signing_secret
-
The signing secret
-
base_logger
-
The base logger
-
-

Ancestors

- -

Subclasses

- -

Instance variables

-
-
prop verifier : slack_sdk.signature.SignatureVerifier
-
-
- -Expand source code - -
@property
-def verifier(self) -> SignatureVerifier:
-    # Defer initialization to avoid errors during start up
-    if self._verifier is None:
-        self._verifier = SignatureVerifier(signing_secret=self._signing_secret)
-    return self._verifier
-
-
-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/request_verification/request_verification.html b/docs/reference/middleware/request_verification/request_verification.html deleted file mode 100644 index 4ee2ed1b1..000000000 --- a/docs/reference/middleware/request_verification/request_verification.html +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - -slack_bolt.middleware.request_verification.request_verification API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.request_verification.request_verification

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class RequestVerification -(signing_secret: str, base_logger: logging.Logger | None = None) -
-
-
- -Expand source code - -
class RequestVerification(Middleware):
-    def __init__(self, signing_secret: str, base_logger: Optional[Logger] = None):
-        """Verifies an incoming request by checking the validity of
-        `x-slack-signature`, `x-slack-request-timestamp`, and its body data.
-
-        Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details.
-
-        Args:
-            signing_secret: The signing secret
-            base_logger: The base logger
-        """
-        self._signing_secret = signing_secret
-        self._verifier: Optional[SignatureVerifier] = None
-        self.logger = get_bolt_logger(RequestVerification, base_logger=base_logger)
-
-    @property
-    def verifier(self) -> SignatureVerifier:
-        # Defer initialization to avoid errors during start up
-        if self._verifier is None:
-            self._verifier = SignatureVerifier(signing_secret=self._signing_secret)
-        return self._verifier
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        if self._can_skip(req.mode, req.body):
-            return next()
-
-        body = req.raw_body
-        timestamp = req.headers.get("x-slack-request-timestamp", ["0"])[0]
-        signature = req.headers.get("x-slack-signature", [""])[0]
-        if self.verifier.is_valid(body, timestamp, signature):
-            return next()
-        else:
-            self._debug_log_error(signature, timestamp, body)
-            return self._build_error_response()
-
-    # -----------------------------------------
-
-    @staticmethod
-    def _can_skip(mode: str, body: Dict[str, Any]) -> bool:
-        return mode == "socket_mode"
-
-    @staticmethod
-    def _build_error_response() -> BoltResponse:
-        return BoltResponse(status=401, body={"error": "invalid request"})
-
-    def _debug_log_error(self, signature, timestamp, body) -> None:
-        self.logger.info(
-            "Invalid request signature detected " f"(signature: {signature}, timestamp: {timestamp}, body: {body})"
-        )
-
-

A middleware can process request data before other middleware and listener functions.

-

Verifies an incoming request by checking the validity of -x-slack-signature, x-slack-request-timestamp, and its body data.

-

Refer to https://docs.slack.dev/authentication/verifying-requests-from-slack/ for details.

-

Args

-
-
signing_secret
-
The signing secret
-
base_logger
-
The base logger
-
-

Ancestors

- -

Subclasses

- -

Instance variables

-
-
prop verifier : slack_sdk.signature.SignatureVerifier
-
-
- -Expand source code - -
@property
-def verifier(self) -> SignatureVerifier:
-    # Defer initialization to avoid errors during start up
-    if self._verifier is None:
-        self._verifier = SignatureVerifier(signing_secret=self._signing_secret)
-    return self._verifier
-
-
-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/ssl_check/async_ssl_check.html b/docs/reference/middleware/ssl_check/async_ssl_check.html deleted file mode 100644 index 48c4bb599..000000000 --- a/docs/reference/middleware/ssl_check/async_ssl_check.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - -slack_bolt.middleware.ssl_check.async_ssl_check API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.ssl_check.async_ssl_check

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncSslCheck -(verification_token: str | None = None,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncSslCheck(SslCheck, AsyncMiddleware):
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        if self._is_ssl_check_request(req.body):
-            if self._verify_token_if_needed(req.body):
-                return self._build_error_response()
-            return self._build_success_response()
-        else:
-            return await next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Handles ssl_check requests. -Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details.

-

Args

-
-
verification_token
-
The verification token to check -(optional as it's already deprecated - https://docs.slack.dev/authentication/verifying-requests-from-slack/#deprecation)
-
base_logger
-
The base logger
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/ssl_check/index.html b/docs/reference/middleware/ssl_check/index.html deleted file mode 100644 index 6c1e4725e..000000000 --- a/docs/reference/middleware/ssl_check/index.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - -slack_bolt.middleware.ssl_check API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.ssl_check

-
-
-
-
-

Sub-modules

-
-
slack_bolt.middleware.ssl_check.async_ssl_check
-
-
-
-
slack_bolt.middleware.ssl_check.ssl_check
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SslCheck -(verification_token: str | None = None,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class SslCheck(Middleware):
-    verification_token: Optional[str]
-    logger: Logger
-
-    def __init__(
-        self,
-        verification_token: Optional[str] = None,
-        base_logger: Optional[Logger] = None,
-    ):
-        """Handles `ssl_check` requests.
-        Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details.
-
-        Args:
-            verification_token: The verification token to check
-                (optional as it's already deprecated - https://docs.slack.dev/authentication/verifying-requests-from-slack/#deprecation)
-            base_logger: The base logger
-        """  # noqa: E501
-        self.verification_token = verification_token
-        self.logger = get_bolt_logger(SslCheck, base_logger=base_logger)
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        if self._is_ssl_check_request(req.body):
-            if self._verify_token_if_needed(req.body):
-                return self._build_error_response()
-            return self._build_success_response()
-        else:
-            return next()
-
-    # -----------------------------------------
-
-    @staticmethod
-    def _is_ssl_check_request(body: dict):
-        return "ssl_check" in body and body["ssl_check"] == "1"
-
-    def _verify_token_if_needed(self, body: dict):
-        return self.verification_token and self.verification_token == body["token"]
-
-    @staticmethod
-    def _build_success_response() -> BoltResponse:
-        return BoltResponse(status=200, body="")
-
-    @staticmethod
-    def _build_error_response() -> BoltResponse:
-        return BoltResponse(status=401, body={"error": "invalid verification token"})
-
-

A middleware can process request data before other middleware and listener functions.

-

Handles slack_bolt.middleware.ssl_check.ssl_check requests. -Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details.

-

Args

-
-
verification_token
-
The verification token to check -(optional as it's already deprecated - https://docs.slack.dev/authentication/verifying-requests-from-slack/#deprecation)
-
base_logger
-
The base logger
-
-

Ancestors

- -

Subclasses

- -

Class variables

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
var verification_token : str | None
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/ssl_check/ssl_check.html b/docs/reference/middleware/ssl_check/ssl_check.html deleted file mode 100644 index f90ad4d87..000000000 --- a/docs/reference/middleware/ssl_check/ssl_check.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - -slack_bolt.middleware.ssl_check.ssl_check API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.ssl_check.ssl_check

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class SslCheck -(verification_token: str | None = None,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class SslCheck(Middleware):
-    verification_token: Optional[str]
-    logger: Logger
-
-    def __init__(
-        self,
-        verification_token: Optional[str] = None,
-        base_logger: Optional[Logger] = None,
-    ):
-        """Handles `ssl_check` requests.
-        Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details.
-
-        Args:
-            verification_token: The verification token to check
-                (optional as it's already deprecated - https://docs.slack.dev/authentication/verifying-requests-from-slack/#deprecation)
-            base_logger: The base logger
-        """  # noqa: E501
-        self.verification_token = verification_token
-        self.logger = get_bolt_logger(SslCheck, base_logger=base_logger)
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        if self._is_ssl_check_request(req.body):
-            if self._verify_token_if_needed(req.body):
-                return self._build_error_response()
-            return self._build_success_response()
-        else:
-            return next()
-
-    # -----------------------------------------
-
-    @staticmethod
-    def _is_ssl_check_request(body: dict):
-        return "ssl_check" in body and body["ssl_check"] == "1"
-
-    def _verify_token_if_needed(self, body: dict):
-        return self.verification_token and self.verification_token == body["token"]
-
-    @staticmethod
-    def _build_success_response() -> BoltResponse:
-        return BoltResponse(status=200, body="")
-
-    @staticmethod
-    def _build_error_response() -> BoltResponse:
-        return BoltResponse(status=401, body={"error": "invalid verification token"})
-
-

A middleware can process request data before other middleware and listener functions.

-

Handles ssl_check requests. -Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details.

-

Args

-
-
verification_token
-
The verification token to check -(optional as it's already deprecated - https://docs.slack.dev/authentication/verifying-requests-from-slack/#deprecation)
-
base_logger
-
The base logger
-
-

Ancestors

- -

Subclasses

- -

Class variables

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
var verification_token : str | None
-
-

The type of the None singleton.

-
-
-

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/url_verification/async_url_verification.html b/docs/reference/middleware/url_verification/async_url_verification.html deleted file mode 100644 index d1408052d..000000000 --- a/docs/reference/middleware/url_verification/async_url_verification.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - -slack_bolt.middleware.url_verification.async_url_verification API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.url_verification.async_url_verification

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncUrlVerification -(base_logger: logging.Logger | None = None) -
-
-
- -Expand source code - -
class AsyncUrlVerification(UrlVerification, AsyncMiddleware):
-    def __init__(self, base_logger: Optional[Logger] = None):
-        self.logger = get_bolt_logger(AsyncUrlVerification, base_logger=base_logger)
-
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-        if self._is_url_verification_request(req.body):
-            return self._build_success_response(req.body)
-        else:
-            return await next()
-
-

A middleware can process request data before other middleware and listener functions.

-

Handles url_verification requests.

-

Refer to https://docs.slack.dev/reference/events/url_verification/ for details.

-

Args

-
-
base_logger
-
The base logger
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/url_verification/index.html b/docs/reference/middleware/url_verification/index.html deleted file mode 100644 index 480c861d6..000000000 --- a/docs/reference/middleware/url_verification/index.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - -slack_bolt.middleware.url_verification API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.url_verification

-
-
-
-
-

Sub-modules

-
-
slack_bolt.middleware.url_verification.async_url_verification
-
-
-
-
slack_bolt.middleware.url_verification.url_verification
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class UrlVerification -(base_logger: logging.Logger | None = None) -
-
-
- -Expand source code - -
class UrlVerification(Middleware):
-    def __init__(self, base_logger: Optional[Logger] = None):
-        """Handles url_verification requests.
-
-        Refer to https://docs.slack.dev/reference/events/url_verification/ for details.
-
-        Args:
-            base_logger: The base logger
-        """
-        self.logger = get_bolt_logger(UrlVerification, base_logger=base_logger)
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        if self._is_url_verification_request(req.body):
-            return self._build_success_response(req.body)
-        else:
-            return next()
-
-    # -----------------------------------------
-
-    @staticmethod
-    def _is_url_verification_request(body: dict) -> bool:
-        return body is not None and body.get("type") == "url_verification"
-
-    @staticmethod
-    def _build_success_response(body: dict) -> BoltResponse:
-        return BoltResponse(status=200, body={"challenge": body.get("challenge")})
-
-

A middleware can process request data before other middleware and listener functions.

-

Handles url_verification requests.

-

Refer to https://docs.slack.dev/reference/events/url_verification/ for details.

-

Args

-
-
base_logger
-
The base logger
-
-

Ancestors

- -

Subclasses

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/middleware/url_verification/url_verification.html b/docs/reference/middleware/url_verification/url_verification.html deleted file mode 100644 index ff22c2986..000000000 --- a/docs/reference/middleware/url_verification/url_verification.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - -slack_bolt.middleware.url_verification.url_verification API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.middleware.url_verification.url_verification

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class UrlVerification -(base_logger: logging.Logger | None = None) -
-
-
- -Expand source code - -
class UrlVerification(Middleware):
-    def __init__(self, base_logger: Optional[Logger] = None):
-        """Handles url_verification requests.
-
-        Refer to https://docs.slack.dev/reference/events/url_verification/ for details.
-
-        Args:
-            base_logger: The base logger
-        """
-        self.logger = get_bolt_logger(UrlVerification, base_logger=base_logger)
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> BoltResponse:
-        if self._is_url_verification_request(req.body):
-            return self._build_success_response(req.body)
-        else:
-            return next()
-
-    # -----------------------------------------
-
-    @staticmethod
-    def _is_url_verification_request(body: dict) -> bool:
-        return body is not None and body.get("type") == "url_verification"
-
-    @staticmethod
-    def _build_success_response(body: dict) -> BoltResponse:
-        return BoltResponse(status=200, body={"challenge": body.get("challenge")})
-
-

A middleware can process request data before other middleware and listener functions.

-

Handles url_verification requests.

-

Refer to https://docs.slack.dev/reference/events/url_verification/ for details.

-

Args

-
-
base_logger
-
The base logger
-
-

Ancestors

- -

Subclasses

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/oauth/async_callback_options.html b/docs/reference/oauth/async_callback_options.html deleted file mode 100644 index d07f1aee5..000000000 --- a/docs/reference/oauth/async_callback_options.html +++ /dev/null @@ -1,285 +0,0 @@ - - - - - - -slack_bolt.oauth.async_callback_options API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.oauth.async_callback_options

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncCallbackOptions -(success: Callable[[AsyncSuccessArgs], Awaitable[BoltResponse]],
failure: Callable[[AsyncFailureArgs], Awaitable[BoltResponse]])
-
-
-
- -Expand source code - -
class AsyncCallbackOptions:
-    success: Callable[[AsyncSuccessArgs], Awaitable[BoltResponse]]
-    failure: Callable[[AsyncFailureArgs], Awaitable[BoltResponse]]
-
-    def __init__(
-        self,
-        success: Callable[[AsyncSuccessArgs], Awaitable[BoltResponse]],
-        failure: Callable[[AsyncFailureArgs], Awaitable[BoltResponse]],
-    ):
-        self.success = success
-        self.failure = failure
-
-
-

Subclasses

- -

Class variables

-
-
var failure : Callable[[AsyncFailureArgs], Awaitable[BoltResponse]]
-
-

The type of the None singleton.

-
-
var success : Callable[[AsyncSuccessArgs], Awaitable[BoltResponse]]
-
-

The type of the None singleton.

-
-
-
-
-class AsyncFailureArgs -(*,
request: AsyncBoltRequest,
reason: str,
error: Exception | None = None,
suggested_status_code: int,
settings: AsyncOAuthSettings,
default: AsyncCallbackOptions)
-
-
-
- -Expand source code - -
class AsyncFailureArgs:
-    def __init__(
-        self,
-        *,
-        request: AsyncBoltRequest,
-        reason: str,
-        error: Optional[Exception] = None,
-        suggested_status_code: int,
-        settings: "AsyncOAuthSettings",
-        default: "AsyncCallbackOptions",
-    ):
-        """The arguments for a failure function.
-
-        Args:
-            request: The request.
-            reason: The response.
-            error: An exception if exists.
-            suggested_status_code: The recommended HTTP status code for the failure.
-            settings: The settings for Slack OAuth flow.
-            default: The default `AsyncCallbackOptions`.
-        """
-        self.request = request
-        self.reason = reason
-        self.error = error
-        self.suggested_status_code = suggested_status_code
-        self.settings = settings
-        self.default = default
-
-

The arguments for a failure function.

-

Args

-
-
request
-
The request.
-
reason
-
The response.
-
error
-
An exception if exists.
-
suggested_status_code
-
The recommended HTTP status code for the failure.
-
settings
-
The settings for Slack OAuth flow.
-
default
-
The default AsyncCallbackOptions.
-
-
-
-class AsyncSuccessArgs -(*,
request: AsyncBoltRequest,
installation: slack_sdk.oauth.installation_store.models.installation.Installation,
settings: AsyncOAuthSettings,
default: AsyncCallbackOptions)
-
-
-
- -Expand source code - -
class AsyncSuccessArgs:
-    def __init__(
-        self,
-        *,
-        request: AsyncBoltRequest,
-        installation: Installation,
-        settings: "AsyncOAuthSettings",
-        default: "AsyncCallbackOptions",
-    ):
-        """The arguments for a success function.
-
-        Args:
-            request: The request.
-            installation: The installation data.
-            settings: The settings for Slack OAuth flow.
-            default: The default `AsyncCallbackOptions`.
-        """
-        self.request = request
-        self.installation = installation
-        self.settings = settings
-        self.default = default
-
-

The arguments for a success function.

-

Args

-
-
request
-
The request.
-
installation
-
The installation data.
-
settings
-
The settings for Slack OAuth flow.
-
default
-
The default AsyncCallbackOptions.
-
-
-
-class DefaultAsyncCallbackOptions -(*,
logger: logging.Logger,
state_utils: slack_sdk.oauth.state_utils.OAuthStateUtils,
redirect_uri_page_renderer: slack_sdk.oauth.redirect_uri_page_renderer.RedirectUriPageRenderer)
-
-
-
- -Expand source code - -
class DefaultAsyncCallbackOptions(AsyncCallbackOptions):
-    success: Callable[[AsyncSuccessArgs], Awaitable[BoltResponse]]
-    failure: Callable[[AsyncFailureArgs], Awaitable[BoltResponse]]
-
-    def __init__(
-        self,
-        *,
-        logger: Logger,
-        state_utils: OAuthStateUtils,
-        redirect_uri_page_renderer: RedirectUriPageRenderer,
-    ):
-        self._response_builder = CallbackResponseBuilder(
-            logger=logger or logging.getLogger(__name__),
-            state_utils=state_utils,
-            redirect_uri_page_renderer=redirect_uri_page_renderer,
-        )
-        self.success = self._success_handler
-        self.failure = self._failure_handler
-
-    # --------------------------
-    # Internal methods
-    # --------------------------
-
-    async def _success_handler(self, args: AsyncSuccessArgs) -> BoltResponse:
-        return self._response_builder._build_callback_success_response(
-            request=args.request,
-            installation=args.installation,
-        )
-
-    async def _failure_handler(self, args: AsyncFailureArgs) -> BoltResponse:
-        return self._response_builder._build_callback_failure_response(
-            request=args.request,
-            reason=args.reason,
-            status=args.suggested_status_code,
-        )
-
-
-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/oauth/async_internals.html b/docs/reference/oauth/async_internals.html deleted file mode 100644 index 2b35a69c9..000000000 --- a/docs/reference/oauth/async_internals.html +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - -slack_bolt.oauth.async_internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.oauth.async_internals

-
-
-
-
-
-
-
-
-

Functions

-
-
-def get_or_create_default_installation_store(client_id: str) ‑> slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore -
-
-
- -Expand source code - -
def get_or_create_default_installation_store(client_id: str) -> AsyncInstallationStore:
-    store = default_installation_stores.get(client_id)
-    if store is None:
-        store = FileInstallationStore(client_id=client_id)
-        default_installation_stores[client_id] = store
-    return store
-
-
-
-
-def select_consistent_installation_store(client_id: str,
app_store: slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore | None,
oauth_flow_store: slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore | None,
logger: logging.Logger) ‑> slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore | None
-
-
-
- -Expand source code - -
def select_consistent_installation_store(
-    client_id: str,
-    app_store: Optional[AsyncInstallationStore],
-    oauth_flow_store: Optional[AsyncInstallationStore],
-    logger: Logger,
-) -> Optional[AsyncInstallationStore]:
-    default = get_or_create_default_installation_store(client_id)
-    if app_store is not None:
-        if oauth_flow_store is not None:
-            if oauth_flow_store is default:
-                # only app_store is intentionally set in this case
-                return app_store
-
-            # if both are intentionally set, prioritize app_store
-            if oauth_flow_store is not app_store:
-                logger.warning(warning_installation_store_conflicts())
-            return oauth_flow_store
-        else:
-            # only app_store is available
-            return app_store
-    else:
-        # only oauth_flow_store is available
-        return oauth_flow_store
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/oauth/async_oauth_flow.html b/docs/reference/oauth/async_oauth_flow.html deleted file mode 100644 index 3ccdfd6f0..000000000 --- a/docs/reference/oauth/async_oauth_flow.html +++ /dev/null @@ -1,809 +0,0 @@ - - - - - - -slack_bolt.oauth.async_oauth_flow API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.oauth.async_oauth_flow

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncOAuthFlow -(*,
client: slack_sdk.web.async_client.AsyncWebClient | None = None,
logger: logging.Logger | None = None,
settings: AsyncOAuthSettings)
-
-
-
- -Expand source code - -
class AsyncOAuthFlow:
-    settings: AsyncOAuthSettings
-    client_id: str
-    redirect_uri: Optional[str]
-    install_path: str
-    redirect_uri_path: str
-
-    success_handler: Callable[[AsyncSuccessArgs], Awaitable[BoltResponse]]
-    failure_handler: Callable[[AsyncFailureArgs], Awaitable[BoltResponse]]
-
-    def __init__(
-        self,
-        *,
-        client: Optional[AsyncWebClient] = None,
-        logger: Optional[Logger] = None,
-        settings: AsyncOAuthSettings,
-    ):
-        """The module to run the Slack app installation flow (OAuth flow).
-
-        Args:
-            client: The `slack_sdk.web.async_client.AsyncWebClient` instance.
-            logger: The logger.
-            settings: OAuth settings to configure this module.
-        """
-        self._async_client = client
-        self._logger = logger
-
-        if not isinstance(settings, AsyncOAuthSettings):
-            raise BoltError(error_oauth_settings_invalid_type_async())
-        self.settings = settings
-
-        if self._logger is not None:
-            self.settings.logger = self._logger
-
-        self.client_id = self.settings.client_id
-        self.redirect_uri = self.settings.redirect_uri
-        self.install_path = self.settings.install_path
-        self.redirect_uri_path = self.settings.redirect_uri_path
-
-        self.default_callback_options = DefaultAsyncCallbackOptions(
-            logger=logger,  # type: ignore[arg-type]
-            state_utils=self.settings.state_utils,
-            redirect_uri_page_renderer=self.settings.redirect_uri_page_renderer,
-        )
-        if settings.callback_options is None:
-            settings.callback_options = self.default_callback_options
-        self.success_handler = settings.callback_options.success
-        self.failure_handler = settings.callback_options.failure
-
-    @property
-    def client(self) -> AsyncWebClient:
-        if self._async_client is None:
-            self._async_client = create_async_web_client(logger=self.logger)
-        return self._async_client
-
-    @property
-    def logger(self) -> Logger:
-        if self._logger is None:
-            self._logger = logging.getLogger(__name__)
-        return self._logger
-
-    # -----------------------------
-    # Factory Methods
-    # -----------------------------
-
-    @classmethod
-    def sqlite3(
-        cls,
-        database: str,
-        # OAuth flow parameters/credentials
-        authorization_url: Optional[str] = None,
-        client_id: Optional[str] = None,  # required
-        client_secret: Optional[str] = None,  # required
-        scopes: Optional[Sequence[str]] = None,
-        user_scopes: Optional[Sequence[str]] = None,
-        redirect_uri: Optional[str] = None,
-        # Handler configuration
-        install_path: Optional[str] = None,
-        redirect_uri_path: Optional[str] = None,
-        callback_options: Optional[AsyncCallbackOptions] = None,
-        success_url: Optional[str] = None,
-        failure_url: Optional[str] = None,
-        # Installation Management
-        # state parameter related configurations
-        state_cookie_name: str = OAuthStateUtils.default_cookie_name,
-        state_expiration_seconds: int = OAuthStateUtils.default_expiration_seconds,
-        installation_store_bot_only: bool = False,
-        client: Optional[AsyncWebClient] = None,
-        logger: Optional[Logger] = None,
-    ) -> "AsyncOAuthFlow":
-
-        client_id = client_id or os.environ["SLACK_CLIENT_ID"]  # required
-        client_secret = client_secret or os.environ["SLACK_CLIENT_SECRET"]  # required
-        scopes = scopes or os.environ.get("SLACK_SCOPES", "").split(",")
-        user_scopes = user_scopes or os.environ.get("SLACK_USER_SCOPES", "").split(",")
-        redirect_uri = redirect_uri or os.environ.get("SLACK_REDIRECT_URI")
-        installation_store = (
-            SQLite3InstallationStore(database=database, client_id=client_id)
-            if logger is None
-            else SQLite3InstallationStore(database=database, client_id=client_id, logger=logger)
-        )
-        state_store = (
-            SQLite3OAuthStateStore(database=database, expiration_seconds=state_expiration_seconds)
-            if logger is None
-            else SQLite3OAuthStateStore(database=database, expiration_seconds=state_expiration_seconds, logger=logger)
-        )
-        return AsyncOAuthFlow(
-            client=client or AsyncWebClient(),
-            logger=logger,
-            settings=AsyncOAuthSettings(
-                # OAuth flow parameters/credentials
-                authorization_url=authorization_url,
-                client_id=client_id,
-                client_secret=client_secret,
-                scopes=scopes,
-                user_scopes=user_scopes,
-                redirect_uri=redirect_uri,
-                # Handler configuration
-                install_path=install_path,  # type: ignore[arg-type]
-                redirect_uri_path=redirect_uri_path,  # type: ignore[arg-type]
-                callback_options=callback_options,
-                success_url=success_url,
-                failure_url=failure_url,
-                # Installation Management
-                installation_store=installation_store,
-                installation_store_bot_only=installation_store_bot_only,
-                # state parameter related configurations
-                state_store=state_store,
-                state_cookie_name=state_cookie_name,
-                state_expiration_seconds=state_expiration_seconds,
-            ),
-        )
-
-    # -----------------------------
-    # Installation
-    # -----------------------------
-
-    async def handle_installation(self, request: AsyncBoltRequest) -> BoltResponse:
-        set_cookie_value: Optional[str] = None
-        url = await self.build_authorize_url("", request)
-        if self.settings.state_validation_enabled is True:
-            state = await self.issue_new_state(request)
-            url = await self.build_authorize_url(state, request)
-            set_cookie_value = self.settings.state_utils.build_set_cookie_for_new_state(state)
-        if self.settings.install_page_rendering_enabled:
-            html = await self.build_install_page_html(url, request)
-            return BoltResponse(
-                status=200,
-                body=html,
-                headers=await self.append_set_cookie_headers(
-                    {"Content-Type": "text/html; charset=utf-8"},
-                    set_cookie_value,
-                ),
-            )
-        else:
-            return BoltResponse(
-                status=302,
-                body="",
-                headers=await self.append_set_cookie_headers(
-                    {"Content-Type": "text/html; charset=utf-8", "Location": url},
-                    set_cookie_value,
-                ),
-            )
-
-    # ----------------------
-    # Internal methods for Installation
-
-    async def issue_new_state(self, request: AsyncBoltRequest) -> str:
-        return await self.settings.state_store.async_issue()
-
-    async def build_authorize_url(self, state: str, request: AsyncBoltRequest) -> str:
-        team_ids: Optional[Sequence[str]] = request.query.get("team")
-        return self.settings.authorize_url_generator.generate(
-            state=state,
-            team=team_ids[0] if team_ids is not None else None,
-        )
-
-    async def build_install_page_html(self, url: str, request: AsyncBoltRequest) -> str:
-        return _build_default_install_page_html(url)
-
-    async def append_set_cookie_headers(self, headers: dict, set_cookie_value: Optional[str]):
-        if set_cookie_value is not None:
-            headers["Set-Cookie"] = [set_cookie_value]
-        return headers
-
-    # -----------------------------
-    # Callback
-    # -----------------------------
-
-    async def handle_callback(self, request: AsyncBoltRequest) -> BoltResponse:
-
-        # failure due to end-user's cancellation or invalid redirection to slack.com
-        error = request.query.get("error", [None])[0]
-        if error is not None:
-            return await self.failure_handler(
-                AsyncFailureArgs(
-                    request=request,
-                    reason=error,
-                    suggested_status_code=200,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        # state parameter verification
-        if self.settings.state_validation_enabled is True:
-            state: Optional[str] = request.query.get("state", [None])[0]
-            if not self.settings.state_utils.is_valid_browser(state, request.headers):
-                return await self.failure_handler(
-                    AsyncFailureArgs(
-                        request=request,
-                        reason="invalid_browser",
-                        suggested_status_code=400,
-                        settings=self.settings,
-                        default=self.default_callback_options,
-                    )
-                )
-
-            valid_state_consumed = await self.settings.state_store.async_consume(state)  # type: ignore[arg-type]
-            if not valid_state_consumed:
-                return await self.failure_handler(
-                    AsyncFailureArgs(
-                        request=request,
-                        reason="invalid_state",
-                        suggested_status_code=401,
-                        settings=self.settings,
-                        default=self.default_callback_options,
-                    )
-                )
-
-        # run installation
-        code = request.query.get("code", [None])[0]
-        if code is None:
-            return await self.failure_handler(
-                AsyncFailureArgs(
-                    request=request,
-                    reason="missing_code",
-                    suggested_status_code=401,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        installation = await self.run_installation(code)
-        if installation is None:
-            # failed to run installation with the code
-            return await self.failure_handler(
-                AsyncFailureArgs(
-                    request=request,
-                    reason="invalid_code",
-                    suggested_status_code=401,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        # persist the installation
-        try:
-            await self.store_installation(request, installation)
-        except BoltError as err:
-            return await self.failure_handler(
-                AsyncFailureArgs(
-                    request=request,
-                    reason="storage_error",
-                    error=err,
-                    suggested_status_code=500,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        # display a successful completion page to the end-user
-        return await self.success_handler(
-            AsyncSuccessArgs(
-                request=request,
-                installation=installation,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    # ----------------------
-    # Internal methods for Callback
-
-    async def run_installation(self, code: str) -> Optional[Installation]:
-        try:
-            oauth_response: AsyncSlackResponse = await self.client.oauth_v2_access(
-                code=code,
-                client_id=self.settings.client_id,
-                client_secret=self.settings.client_secret,
-                redirect_uri=self.settings.redirect_uri,  # can be None
-            )
-            installed_enterprise: Dict[str, str] = oauth_response.get("enterprise") or {}
-            is_enterprise_install: bool = oauth_response.get("is_enterprise_install") or False
-            installed_team: Dict[str, str] = oauth_response.get("team") or {}
-            installer: Dict[str, str] = oauth_response.get("authed_user") or {}
-            incoming_webhook: Dict[str, str] = oauth_response.get("incoming_webhook") or {}
-
-            bot_token: Optional[str] = oauth_response.get("access_token")
-            # NOTE: oauth.v2.access doesn't include bot_id in response
-            bot_id: Optional[str] = None
-            enterprise_url: Optional[str] = None
-            if bot_token is not None:
-                auth_test = await self.client.auth_test(token=bot_token)
-                bot_id = auth_test["bot_id"]
-            if is_enterprise_install is True:
-                enterprise_url = auth_test.get("url")
-
-            return Installation(
-                app_id=oauth_response.get("app_id"),
-                enterprise_id=installed_enterprise.get("id"),
-                enterprise_name=installed_enterprise.get("name"),
-                enterprise_url=enterprise_url,
-                team_id=installed_team.get("id"),
-                team_name=installed_team.get("name"),
-                bot_token=bot_token,
-                bot_id=bot_id,
-                bot_user_id=oauth_response.get("bot_user_id"),
-                bot_scopes=oauth_response.get("scope"),  # type: ignore[arg-type] # comma-separated string
-                bot_refresh_token=oauth_response.get("refresh_token"),  # since v1.7
-                bot_token_expires_in=oauth_response.get("expires_in"),  # since v1.7
-                user_id=installer.get("id"),  # type: ignore[arg-type]
-                user_token=installer.get("access_token"),
-                user_scopes=installer.get("scope"),  # type: ignore[arg-type]# comma-separated string
-                user_refresh_token=installer.get("refresh_token"),  # since v1.7
-                user_token_expires_in=installer.get("expires_in"),  # type: ignore[arg-type] # since v1.7
-                incoming_webhook_url=incoming_webhook.get("url"),
-                incoming_webhook_channel=incoming_webhook.get("channel"),
-                incoming_webhook_channel_id=incoming_webhook.get("channel_id"),
-                incoming_webhook_configuration_url=incoming_webhook.get("configuration_url"),
-                is_enterprise_install=is_enterprise_install,
-                token_type=oauth_response.get("token_type"),
-            )
-
-        except SlackApiError as e:
-            message = f"Failed to fetch oauth.v2.access result with code: {code} - error: {e}"
-            self.logger.warning(message)
-            return None
-
-    async def store_installation(self, request: AsyncBoltRequest, installation: Installation):
-        # may raise BoltError
-        await self.settings.installation_store.async_save(installation)
-
-

The module to run the Slack app installation flow (OAuth flow).

-

Args

-
-
client
-
The slack_sdk.web.async_client.AsyncWebClient instance.
-
logger
-
The logger.
-
settings
-
OAuth settings to configure this module.
-
-

Class variables

-
-
var client_id : str
-
-

The type of the None singleton.

-
-
var failure_handler : Callable[[AsyncFailureArgs], Awaitable[BoltResponse]]
-
-

The type of the None singleton.

-
-
var install_path : str
-
-

The type of the None singleton.

-
-
var redirect_uri : str | None
-
-

The type of the None singleton.

-
-
var redirect_uri_path : str
-
-

The type of the None singleton.

-
-
var settingsAsyncOAuthSettings
-
-

The type of the None singleton.

-
-
var success_handler : Callable[[AsyncSuccessArgs], Awaitable[BoltResponse]]
-
-

The type of the None singleton.

-
-
-

Static methods

-
-
-def sqlite3(database: str,
authorization_url: str | None = None,
client_id: str | None = None,
client_secret: str | None = None,
scopes: Sequence[str] | None = None,
user_scopes: Sequence[str] | None = None,
redirect_uri: str | None = None,
install_path: str | None = None,
redirect_uri_path: str | None = None,
callback_options: AsyncCallbackOptions | None = None,
success_url: str | None = None,
failure_url: str | None = None,
state_cookie_name: str = 'slack-app-oauth-state',
state_expiration_seconds: int = 600,
installation_store_bot_only: bool = False,
client: slack_sdk.web.async_client.AsyncWebClient | None = None,
logger: logging.Logger | None = None) ‑> AsyncOAuthFlow
-
-
-
-
-
-

Instance variables

-
-
prop client : slack_sdk.web.async_client.AsyncWebClient
-
-
- -Expand source code - -
@property
-def client(self) -> AsyncWebClient:
-    if self._async_client is None:
-        self._async_client = create_async_web_client(logger=self.logger)
-    return self._async_client
-
-
-
-
prop logger : logging.Logger
-
-
- -Expand source code - -
@property
-def logger(self) -> Logger:
-    if self._logger is None:
-        self._logger = logging.getLogger(__name__)
-    return self._logger
-
-
-
-
-

Methods

-
- -
-
- -Expand source code - -
async def append_set_cookie_headers(self, headers: dict, set_cookie_value: Optional[str]):
-    if set_cookie_value is not None:
-        headers["Set-Cookie"] = [set_cookie_value]
-    return headers
-
-
-
-
-async def build_authorize_url(self,
state: str,
request: AsyncBoltRequest) ‑> str
-
-
-
- -Expand source code - -
async def build_authorize_url(self, state: str, request: AsyncBoltRequest) -> str:
-    team_ids: Optional[Sequence[str]] = request.query.get("team")
-    return self.settings.authorize_url_generator.generate(
-        state=state,
-        team=team_ids[0] if team_ids is not None else None,
-    )
-
-
-
-
-async def build_install_page_html(self,
url: str,
request: AsyncBoltRequest) ‑> str
-
-
-
- -Expand source code - -
async def build_install_page_html(self, url: str, request: AsyncBoltRequest) -> str:
-    return _build_default_install_page_html(url)
-
-
-
-
-async def handle_callback(self,
request: AsyncBoltRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
async def handle_callback(self, request: AsyncBoltRequest) -> BoltResponse:
-
-    # failure due to end-user's cancellation or invalid redirection to slack.com
-    error = request.query.get("error", [None])[0]
-    if error is not None:
-        return await self.failure_handler(
-            AsyncFailureArgs(
-                request=request,
-                reason=error,
-                suggested_status_code=200,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    # state parameter verification
-    if self.settings.state_validation_enabled is True:
-        state: Optional[str] = request.query.get("state", [None])[0]
-        if not self.settings.state_utils.is_valid_browser(state, request.headers):
-            return await self.failure_handler(
-                AsyncFailureArgs(
-                    request=request,
-                    reason="invalid_browser",
-                    suggested_status_code=400,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        valid_state_consumed = await self.settings.state_store.async_consume(state)  # type: ignore[arg-type]
-        if not valid_state_consumed:
-            return await self.failure_handler(
-                AsyncFailureArgs(
-                    request=request,
-                    reason="invalid_state",
-                    suggested_status_code=401,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-    # run installation
-    code = request.query.get("code", [None])[0]
-    if code is None:
-        return await self.failure_handler(
-            AsyncFailureArgs(
-                request=request,
-                reason="missing_code",
-                suggested_status_code=401,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    installation = await self.run_installation(code)
-    if installation is None:
-        # failed to run installation with the code
-        return await self.failure_handler(
-            AsyncFailureArgs(
-                request=request,
-                reason="invalid_code",
-                suggested_status_code=401,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    # persist the installation
-    try:
-        await self.store_installation(request, installation)
-    except BoltError as err:
-        return await self.failure_handler(
-            AsyncFailureArgs(
-                request=request,
-                reason="storage_error",
-                error=err,
-                suggested_status_code=500,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    # display a successful completion page to the end-user
-    return await self.success_handler(
-        AsyncSuccessArgs(
-            request=request,
-            installation=installation,
-            settings=self.settings,
-            default=self.default_callback_options,
-        )
-    )
-
-
-
-
-async def handle_installation(self,
request: AsyncBoltRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
async def handle_installation(self, request: AsyncBoltRequest) -> BoltResponse:
-    set_cookie_value: Optional[str] = None
-    url = await self.build_authorize_url("", request)
-    if self.settings.state_validation_enabled is True:
-        state = await self.issue_new_state(request)
-        url = await self.build_authorize_url(state, request)
-        set_cookie_value = self.settings.state_utils.build_set_cookie_for_new_state(state)
-    if self.settings.install_page_rendering_enabled:
-        html = await self.build_install_page_html(url, request)
-        return BoltResponse(
-            status=200,
-            body=html,
-            headers=await self.append_set_cookie_headers(
-                {"Content-Type": "text/html; charset=utf-8"},
-                set_cookie_value,
-            ),
-        )
-    else:
-        return BoltResponse(
-            status=302,
-            body="",
-            headers=await self.append_set_cookie_headers(
-                {"Content-Type": "text/html; charset=utf-8", "Location": url},
-                set_cookie_value,
-            ),
-        )
-
-
-
-
-async def issue_new_state(self,
request: AsyncBoltRequest) ‑> str
-
-
-
- -Expand source code - -
async def issue_new_state(self, request: AsyncBoltRequest) -> str:
-    return await self.settings.state_store.async_issue()
-
-
-
-
-async def run_installation(self, code: str) ‑> slack_sdk.oauth.installation_store.models.installation.Installation | None -
-
-
- -Expand source code - -
async def run_installation(self, code: str) -> Optional[Installation]:
-    try:
-        oauth_response: AsyncSlackResponse = await self.client.oauth_v2_access(
-            code=code,
-            client_id=self.settings.client_id,
-            client_secret=self.settings.client_secret,
-            redirect_uri=self.settings.redirect_uri,  # can be None
-        )
-        installed_enterprise: Dict[str, str] = oauth_response.get("enterprise") or {}
-        is_enterprise_install: bool = oauth_response.get("is_enterprise_install") or False
-        installed_team: Dict[str, str] = oauth_response.get("team") or {}
-        installer: Dict[str, str] = oauth_response.get("authed_user") or {}
-        incoming_webhook: Dict[str, str] = oauth_response.get("incoming_webhook") or {}
-
-        bot_token: Optional[str] = oauth_response.get("access_token")
-        # NOTE: oauth.v2.access doesn't include bot_id in response
-        bot_id: Optional[str] = None
-        enterprise_url: Optional[str] = None
-        if bot_token is not None:
-            auth_test = await self.client.auth_test(token=bot_token)
-            bot_id = auth_test["bot_id"]
-        if is_enterprise_install is True:
-            enterprise_url = auth_test.get("url")
-
-        return Installation(
-            app_id=oauth_response.get("app_id"),
-            enterprise_id=installed_enterprise.get("id"),
-            enterprise_name=installed_enterprise.get("name"),
-            enterprise_url=enterprise_url,
-            team_id=installed_team.get("id"),
-            team_name=installed_team.get("name"),
-            bot_token=bot_token,
-            bot_id=bot_id,
-            bot_user_id=oauth_response.get("bot_user_id"),
-            bot_scopes=oauth_response.get("scope"),  # type: ignore[arg-type] # comma-separated string
-            bot_refresh_token=oauth_response.get("refresh_token"),  # since v1.7
-            bot_token_expires_in=oauth_response.get("expires_in"),  # since v1.7
-            user_id=installer.get("id"),  # type: ignore[arg-type]
-            user_token=installer.get("access_token"),
-            user_scopes=installer.get("scope"),  # type: ignore[arg-type]# comma-separated string
-            user_refresh_token=installer.get("refresh_token"),  # since v1.7
-            user_token_expires_in=installer.get("expires_in"),  # type: ignore[arg-type] # since v1.7
-            incoming_webhook_url=incoming_webhook.get("url"),
-            incoming_webhook_channel=incoming_webhook.get("channel"),
-            incoming_webhook_channel_id=incoming_webhook.get("channel_id"),
-            incoming_webhook_configuration_url=incoming_webhook.get("configuration_url"),
-            is_enterprise_install=is_enterprise_install,
-            token_type=oauth_response.get("token_type"),
-        )
-
-    except SlackApiError as e:
-        message = f"Failed to fetch oauth.v2.access result with code: {code} - error: {e}"
-        self.logger.warning(message)
-        return None
-
-
-
-
-async def store_installation(self,
request: AsyncBoltRequest,
installation: slack_sdk.oauth.installation_store.models.installation.Installation)
-
-
-
- -Expand source code - -
async def store_installation(self, request: AsyncBoltRequest, installation: Installation):
-    # may raise BoltError
-    await self.settings.installation_store.async_save(installation)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/oauth/async_oauth_settings.html b/docs/reference/oauth/async_oauth_settings.html deleted file mode 100644 index 3b8c04edb..000000000 --- a/docs/reference/oauth/async_oauth_settings.html +++ /dev/null @@ -1,423 +0,0 @@ - - - - - - -slack_bolt.oauth.async_oauth_settings API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.oauth.async_oauth_settings

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncOAuthSettings -(*,
client_id: str | None = None,
client_secret: str | None = None,
scopes: Sequence[str] | str | None = None,
user_scopes: Sequence[str] | str | None = None,
redirect_uri: str | None = None,
install_path: str = '/slack/install',
install_page_rendering_enabled: bool = True,
redirect_uri_path: str = '/slack/oauth_redirect',
callback_options: AsyncCallbackOptions | None = None,
success_url: str | None = None,
failure_url: str | None = None,
authorization_url: str | None = None,
installation_store: slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore | None = None,
installation_store_bot_only: bool = False,
token_rotation_expiration_minutes: int = 120,
user_token_resolution: str = 'authed_user',
state_validation_enabled: bool = True,
state_store: slack_sdk.oauth.state_store.async_state_store.AsyncOAuthStateStore | None = None,
state_cookie_name: str = 'slack-app-oauth-state',
state_expiration_seconds: int = 600,
logger: logging.Logger = <Logger slack_bolt.oauth.async_oauth_settings (WARNING)>)
-
-
-
- -Expand source code - -
class AsyncOAuthSettings:
-    # OAuth flow parameters/credentials
-    client_id: str
-    client_secret: str
-    scopes: Optional[Sequence[str]]
-    user_scopes: Optional[Sequence[str]]
-    redirect_uri: Optional[str]
-    # Handler configuration
-    install_path: str
-    install_page_rendering_enabled: bool
-    redirect_uri_path: str
-    callback_options: Optional[AsyncCallbackOptions] = None
-    success_url: Optional[str]
-    failure_url: Optional[str]
-    authorization_url: str  # default: https://slack.com/oauth/v2/authorize
-    # Installation Management
-    installation_store: AsyncInstallationStore
-    installation_store_bot_only: bool
-    token_rotation_expiration_minutes: int
-    user_token_resolution: str
-    authorize: AsyncAuthorize
-    # state parameter related configurations
-    state_validation_enabled: bool
-    state_store: AsyncOAuthStateStore
-    state_cookie_name: str
-    state_expiration_seconds: int
-    # Customizable utilities
-    state_utils: OAuthStateUtils
-    authorize_url_generator: AuthorizeUrlGenerator
-    redirect_uri_page_renderer: RedirectUriPageRenderer
-    # Others
-    logger: Logger
-
-    def __init__(
-        self,
-        *,
-        # OAuth flow parameters/credentials
-        client_id: Optional[str] = None,  # required
-        client_secret: Optional[str] = None,  # required
-        scopes: Optional[Union[Sequence[str], str]] = None,
-        user_scopes: Optional[Union[Sequence[str], str]] = None,
-        redirect_uri: Optional[str] = None,
-        # Handler configuration
-        install_path: str = "/slack/install",
-        install_page_rendering_enabled: bool = True,
-        redirect_uri_path: str = "/slack/oauth_redirect",
-        callback_options: Optional[AsyncCallbackOptions] = None,
-        success_url: Optional[str] = None,
-        failure_url: Optional[str] = None,
-        authorization_url: Optional[str] = None,
-        # Installation Management
-        installation_store: Optional[AsyncInstallationStore] = None,
-        installation_store_bot_only: bool = False,
-        token_rotation_expiration_minutes: int = 120,
-        user_token_resolution: str = "authed_user",
-        # state parameter related configurations
-        state_validation_enabled: bool = True,
-        state_store: Optional[AsyncOAuthStateStore] = None,
-        state_cookie_name: str = OAuthStateUtils.default_cookie_name,
-        state_expiration_seconds: int = OAuthStateUtils.default_expiration_seconds,
-        # Others
-        logger: Logger = logging.getLogger(__name__),
-    ):
-        """The settings for Slack App installation (OAuth flow).
-
-        Args:
-            client_id: Check the value in Settings > Basic Information > App Credentials
-            client_secret: Check the value in Settings > Basic Information > App Credentials
-            scopes: Check the value in Settings > Manage Distribution
-            user_scopes: Check the value in Settings > Manage Distribution
-            redirect_uri: Check the value in Features > OAuth & Permissions > Redirect URLs
-            install_path: The endpoint to start an OAuth flow (Default: `/slack/install`)
-            install_page_rendering_enabled: Renders a web page for install_path access if True
-            redirect_uri_path: The path of Redirect URL (Default: `/slack/oauth_redirect`)
-            callback_options: Give success/failure functions f you want to customize callback functions.
-            success_url: Set a complete URL if you want to redirect end-users when an installation completes.
-            failure_url: Set a complete URL if you want to redirect end-users when an installation fails.
-            authorization_url: Set a URL if you want to customize the URL `https://slack.com/oauth/v2/authorize`
-            installation_store: Specify the instance of `InstallationStore` (Default: `FileInstallationStore`)
-            installation_store_bot_only: Use `InstallationStore#find_bot()` if True (Default: False)
-            token_rotation_expiration_minutes: Minutes before refreshing tokens (Default: 2 hours)
-            user_token_resolution: The option to pick up a user token per request (Default: authed_user)
-                The available values are "authed_user" and "actor". When you want to resolve the user token per request
-                using the event's actor IDs, you can set "actor" instead. With this option, bolt-python tries to resolve
-                a user token for context.actor_enterprise/team/user_id. This can be useful for events in Slack Connect
-                channels. Note that actor IDs can be absent in some scenarios.
-            state_validation_enabled: Set False if your OAuth flow omits the state parameter validation (Default: True)
-            state_store: Specify the instance of `InstallationStore` (Default: `FileOAuthStateStore`)
-            state_cookie_name: The cookie name that is set for installers' browser. (Default: "slack-app-oauth-state")
-            state_expiration_seconds: The seconds that the state value is alive (Default: 600 seconds)
-            logger: The logger that will be used internally
-        """
-        # OAuth flow parameters/credentials
-        client_id = client_id or os.environ.get("SLACK_CLIENT_ID")
-        client_secret = client_secret or os.environ.get("SLACK_CLIENT_SECRET")
-        if client_id is None or client_secret is None:
-            raise BoltError("Both client_id and client_secret are required")
-        self.client_id = client_id
-        self.client_secret = client_secret
-
-        self.scopes = scopes if scopes is not None else os.environ.get("SLACK_SCOPES", "").split(",")
-        if isinstance(self.scopes, str):
-            self.scopes = self.scopes.split(",")
-        self.user_scopes = user_scopes if user_scopes is not None else os.environ.get("SLACK_USER_SCOPES", "").split(",")
-        if isinstance(self.user_scopes, str):
-            self.user_scopes = self.user_scopes.split(",")
-
-        self.redirect_uri = redirect_uri or os.environ.get("SLACK_REDIRECT_URI")
-        # Handler configuration
-        self.install_path = install_path or os.environ.get("SLACK_INSTALL_PATH", "/slack/install")
-        self.install_page_rendering_enabled = install_page_rendering_enabled
-        self.redirect_uri_path = redirect_uri_path or os.environ.get("SLACK_REDIRECT_URI_PATH", "/slack/oauth_redirect")
-        self.callback_options = callback_options
-        self.success_url = success_url
-        self.failure_url = failure_url
-        self.authorization_url = authorization_url or "https://slack.com/oauth/v2/authorize"
-        # Installation Management
-        self.installation_store = installation_store or get_or_create_default_installation_store(client_id)
-        self.user_token_resolution = user_token_resolution or "authed_user"
-        self.installation_store_bot_only = installation_store_bot_only
-        self.token_rotation_expiration_minutes = token_rotation_expiration_minutes
-        self.authorize = AsyncInstallationStoreAuthorize(
-            logger=logger,
-            client_id=self.client_id,
-            client_secret=self.client_secret,
-            token_rotation_expiration_minutes=self.token_rotation_expiration_minutes,
-            installation_store=self.installation_store,
-            bot_only=self.installation_store_bot_only,
-            user_token_resolution=user_token_resolution,
-        )
-        # state parameter related configurations
-        self.state_validation_enabled = state_validation_enabled
-        self.state_store = state_store or FileOAuthStateStore(
-            expiration_seconds=state_expiration_seconds,
-            client_id=client_id,
-        )
-        self.state_cookie_name = state_cookie_name
-        self.state_expiration_seconds = state_expiration_seconds
-
-        self.state_utils = OAuthStateUtils(
-            cookie_name=self.state_cookie_name,
-            expiration_seconds=self.state_expiration_seconds,
-        )
-        self.authorize_url_generator = AuthorizeUrlGenerator(
-            client_id=self.client_id,
-            redirect_uri=self.redirect_uri,
-            scopes=self.scopes,
-            user_scopes=self.user_scopes,
-            authorization_url=self.authorization_url,
-        )
-        self.redirect_uri_page_renderer = RedirectUriPageRenderer(
-            install_path=self.install_path,
-            redirect_uri_path=self.redirect_uri_path,
-            success_url=self.success_url,
-            failure_url=self.failure_url,
-        )
-
-

The settings for Slack App installation (OAuth flow).

-

Args

-
-
client_id
-
Check the value in Settings > Basic Information > App Credentials
-
client_secret
-
Check the value in Settings > Basic Information > App Credentials
-
scopes
-
Check the value in Settings > Manage Distribution
-
user_scopes
-
Check the value in Settings > Manage Distribution
-
redirect_uri
-
Check the value in Features > OAuth & Permissions > Redirect URLs
-
install_path
-
The endpoint to start an OAuth flow (Default: /slack/install)
-
install_page_rendering_enabled
-
Renders a web page for install_path access if True
-
redirect_uri_path
-
The path of Redirect URL (Default: /slack/oauth_redirect)
-
callback_options
-
Give success/failure functions f you want to customize callback functions.
-
success_url
-
Set a complete URL if you want to redirect end-users when an installation completes.
-
failure_url
-
Set a complete URL if you want to redirect end-users when an installation fails.
-
authorization_url
-
Set a URL if you want to customize the URL https://slack.com/oauth/v2/authorize
-
installation_store
-
Specify the instance of InstallationStore (Default: FileInstallationStore)
-
installation_store_bot_only
-
Use InstallationStore#find_bot() if True (Default: False)
-
token_rotation_expiration_minutes
-
Minutes before refreshing tokens (Default: 2 hours)
-
user_token_resolution
-
The option to pick up a user token per request (Default: authed_user) -The available values are "authed_user" and "actor". When you want to resolve the user token per request -using the event's actor IDs, you can set "actor" instead. With this option, bolt-python tries to resolve -a user token for context.actor_enterprise/team/user_id. This can be useful for events in Slack Connect -channels. Note that actor IDs can be absent in some scenarios.
-
state_validation_enabled
-
Set False if your OAuth flow omits the state parameter validation (Default: True)
-
state_store
-
Specify the instance of InstallationStore (Default: FileOAuthStateStore)
-
state_cookie_name
-
The cookie name that is set for installers' browser. (Default: "slack-app-oauth-state")
-
state_expiration_seconds
-
The seconds that the state value is alive (Default: 600 seconds)
-
logger
-
The logger that will be used internally
-
-

Class variables

-
-
var authorization_url : str
-
-

The type of the None singleton.

-
-
var authorizeAsyncAuthorize
-
-

The type of the None singleton.

-
-
var authorize_url_generator : slack_sdk.oauth.authorize_url_generator.AuthorizeUrlGenerator
-
-

The type of the None singleton.

-
-
var callback_optionsAsyncCallbackOptions | None
-
-

The type of the None singleton.

-
-
var client_id : str
-
-

The type of the None singleton.

-
-
var client_secret : str
-
-

The type of the None singleton.

-
-
var failure_url : str | None
-
-

The type of the None singleton.

-
-
var install_page_rendering_enabled : bool
-
-

The type of the None singleton.

-
-
var install_path : str
-
-

The type of the None singleton.

-
-
var installation_store : slack_sdk.oauth.installation_store.async_installation_store.AsyncInstallationStore
-
-

The type of the None singleton.

-
-
var installation_store_bot_only : bool
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
var redirect_uri : str | None
-
-

The type of the None singleton.

-
-
var redirect_uri_page_renderer : slack_sdk.oauth.redirect_uri_page_renderer.RedirectUriPageRenderer
-
-

The type of the None singleton.

-
-
var redirect_uri_path : str
-
-

The type of the None singleton.

-
-
var scopes : Sequence[str] | None
-
-

The type of the None singleton.

-
- -
-

The type of the None singleton.

-
-
var state_expiration_seconds : int
-
-

The type of the None singleton.

-
-
var state_store : slack_sdk.oauth.state_store.async_state_store.AsyncOAuthStateStore
-
-

The type of the None singleton.

-
-
var state_utils : slack_sdk.oauth.state_utils.OAuthStateUtils
-
-

The type of the None singleton.

-
-
var state_validation_enabled : bool
-
-

The type of the None singleton.

-
-
var success_url : str | None
-
-

The type of the None singleton.

-
-
var token_rotation_expiration_minutes : int
-
-

The type of the None singleton.

-
-
var user_scopes : Sequence[str] | None
-
-

The type of the None singleton.

-
-
var user_token_resolution : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/oauth/callback_options.html b/docs/reference/oauth/callback_options.html deleted file mode 100644 index c6fc81286..000000000 --- a/docs/reference/oauth/callback_options.html +++ /dev/null @@ -1,305 +0,0 @@ - - - - - - -slack_bolt.oauth.callback_options API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.oauth.callback_options

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class CallbackOptions -(success: Callable[[SuccessArgs], BoltResponse],
failure: Callable[[FailureArgs], BoltResponse])
-
-
-
- -Expand source code - -
class CallbackOptions:
-    success: Callable[[SuccessArgs], BoltResponse]
-    failure: Callable[[FailureArgs], BoltResponse]
-
-    def __init__(
-        self,
-        success: Callable[[SuccessArgs], BoltResponse],
-        failure: Callable[[FailureArgs], BoltResponse],
-    ):
-        """The configurations for OAuth flow.
-
-        Args:
-            success: A handler for successful installation.
-            failure: A handler for any types of installation failures.
-        """
-        self.success = success
-        self.failure = failure
-
-

The configurations for OAuth flow.

-

Args

-
-
success
-
A handler for successful installation.
-
failure
-
A handler for any types of installation failures.
-
-

Subclasses

- -

Class variables

-
-
var failure : Callable[[FailureArgs], BoltResponse]
-
-

The type of the None singleton.

-
-
var success : Callable[[SuccessArgs], BoltResponse]
-
-

The type of the None singleton.

-
-
-
-
-class DefaultCallbackOptions -(*,
logger: logging.Logger,
state_utils: slack_sdk.oauth.state_utils.OAuthStateUtils,
redirect_uri_page_renderer: slack_sdk.oauth.redirect_uri_page_renderer.RedirectUriPageRenderer)
-
-
-
- -Expand source code - -
class DefaultCallbackOptions(CallbackOptions):
-    success: Callable[[SuccessArgs], BoltResponse]
-    failure: Callable[[FailureArgs], BoltResponse]
-
-    def __init__(
-        self,
-        *,
-        logger: Logger,
-        state_utils: OAuthStateUtils,
-        redirect_uri_page_renderer: RedirectUriPageRenderer,
-    ):
-        self._response_builder = CallbackResponseBuilder(
-            logger=logger or logging.getLogger(__name__),
-            state_utils=state_utils,
-            redirect_uri_page_renderer=redirect_uri_page_renderer,
-        )
-        self.success = self._success_handler
-        self.failure = self._failure_handler
-
-    # --------------------------
-    # Internal methods
-    # --------------------------
-
-    def _success_handler(self, args: SuccessArgs) -> BoltResponse:
-        return self._response_builder._build_callback_success_response(
-            request=args.request,
-            installation=args.installation,
-        )
-
-    def _failure_handler(self, args: FailureArgs) -> BoltResponse:
-        return self._response_builder._build_callback_failure_response(
-            request=args.request,
-            reason=args.reason,
-            status=args.suggested_status_code,
-        )
-
-

The configurations for OAuth flow.

-

Args

-
-
success
-
A handler for successful installation.
-
failure
-
A handler for any types of installation failures.
-
-

Ancestors

- -

Inherited members

- -
-
-class FailureArgs -(*,
request: BoltRequest,
reason: str,
error: Exception | None = None,
suggested_status_code: int,
settings: OAuthSettings,
default: CallbackOptions)
-
-
-
- -Expand source code - -
class FailureArgs:
-    def __init__(
-        self,
-        *,
-        request: BoltRequest,
-        reason: str,
-        error: Optional[Exception] = None,
-        suggested_status_code: int,
-        settings: "OAuthSettings",
-        default: "CallbackOptions",
-    ):
-        """The arguments for a failure function.
-
-        Args:
-            request: The request.
-            reason: The response.
-            error: An exception if exists.
-            suggested_status_code: The recommended HTTP status code for the failure.
-            settings: The settings for Slack OAuth flow.
-            default: The default `CallbackOptions`.
-        """
-        self.request = request
-        self.reason = reason
-        self.error = error
-        self.suggested_status_code = suggested_status_code
-        self.settings = settings
-        self.default = default
-
-

The arguments for a failure function.

-

Args

-
-
request
-
The request.
-
reason
-
The response.
-
error
-
An exception if exists.
-
suggested_status_code
-
The recommended HTTP status code for the failure.
-
settings
-
The settings for Slack OAuth flow.
-
default
-
The default CallbackOptions.
-
-
-
-class SuccessArgs -(*,
request: BoltRequest,
installation: slack_sdk.oauth.installation_store.models.installation.Installation,
settings: OAuthSettings,
default: CallbackOptions)
-
-
-
- -Expand source code - -
class SuccessArgs:
-    def __init__(
-        self,
-        *,
-        request: BoltRequest,
-        installation: Installation,
-        settings: "OAuthSettings",
-        default: "CallbackOptions",
-    ):
-        """The arguments for a success function.
-
-        Args:
-            request: The request.
-            installation: The installation data.
-            settings: The settings for Slack OAuth flow.
-            default: The default `CallbackOptions`
-        """
-        self.request = request
-        self.installation = installation
-        self.settings = settings
-        self.default = default
-
-

The arguments for a success function.

-

Args

-
-
request
-
The request.
-
installation
-
The installation data.
-
settings
-
The settings for Slack OAuth flow.
-
default
-
The default CallbackOptions
-
-
-
-
-
- -
- - - diff --git a/docs/reference/oauth/index.html b/docs/reference/oauth/index.html deleted file mode 100644 index d53dc6a41..000000000 --- a/docs/reference/oauth/index.html +++ /dev/null @@ -1,862 +0,0 @@ - - - - - - -slack_bolt.oauth API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.oauth

-
-
-

Slack OAuth flow support for building an app that is installable in any workspaces.

-

Refer to https://docs.slack.dev/tools/bolt-python/concepts/authenticating-oauth for details.

-
-
-

Sub-modules

-
-
slack_bolt.oauth.async_callback_options
-
-
-
-
slack_bolt.oauth.async_internals
-
-
-
-
slack_bolt.oauth.async_oauth_flow
-
-
-
-
slack_bolt.oauth.async_oauth_settings
-
-
-
-
slack_bolt.oauth.callback_options
-
-
-
-
slack_bolt.oauth.internals
-
-
-
-
slack_bolt.oauth.oauth_flow
-
-
-
-
slack_bolt.oauth.oauth_settings
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class OAuthFlow -(*,
client: slack_sdk.web.client.WebClient | None = None,
logger: logging.Logger | None = None,
settings: OAuthSettings)
-
-
-
- -Expand source code - -
class OAuthFlow:
-    settings: OAuthSettings
-    client_id: str
-    redirect_uri: Optional[str]
-    install_path: str
-    redirect_uri_path: str
-
-    success_handler: Callable[[SuccessArgs], BoltResponse]
-    failure_handler: Callable[[FailureArgs], BoltResponse]
-
-    def __init__(
-        self,
-        *,
-        client: Optional[WebClient] = None,
-        logger: Optional[Logger] = None,
-        settings: OAuthSettings,
-    ):
-        """The module to run the Slack app installation flow (OAuth flow).
-
-        Args:
-            client: The `slack_sdk.web.WebClient` instance.
-            logger: The logger.
-            settings: OAuth settings to configure this module.
-        """
-        self._client = client
-        self._logger = logger
-        self.settings = settings
-        if self._logger is not None:
-            self.settings.logger = self._logger
-
-        self.client_id = self.settings.client_id
-        self.redirect_uri = self.settings.redirect_uri
-        self.install_path = self.settings.install_path
-        self.redirect_uri_path = self.settings.redirect_uri_path
-
-        self.default_callback_options = DefaultCallbackOptions(
-            logger=logger,  # type: ignore[arg-type]
-            state_utils=self.settings.state_utils,
-            redirect_uri_page_renderer=self.settings.redirect_uri_page_renderer,
-        )
-        if settings.callback_options is None:
-            settings.callback_options = self.default_callback_options
-        self.success_handler = settings.callback_options.success
-        self.failure_handler = settings.callback_options.failure
-
-    @property
-    def client(self) -> WebClient:
-        if self._client is None:
-            self._client = create_web_client(logger=self.logger)
-        return self._client
-
-    @property
-    def logger(self) -> Logger:
-        if self._logger is None:
-            self._logger = logging.getLogger(__name__)
-        return self._logger
-
-    # -----------------------------
-    # Factory Methods
-    # -----------------------------
-
-    @classmethod
-    def sqlite3(
-        cls,
-        database: str,
-        # OAuth flow parameters/credentials
-        client_id: Optional[str] = None,  # required
-        client_secret: Optional[str] = None,  # required
-        scopes: Optional[Sequence[str]] = None,
-        user_scopes: Optional[Sequence[str]] = None,
-        redirect_uri: Optional[str] = None,
-        # Handler configuration
-        install_path: Optional[str] = None,
-        redirect_uri_path: Optional[str] = None,
-        callback_options: Optional[CallbackOptions] = None,
-        success_url: Optional[str] = None,
-        failure_url: Optional[str] = None,
-        authorization_url: Optional[str] = None,
-        # Installation Management
-        # state parameter related configurations
-        state_cookie_name: str = OAuthStateUtils.default_cookie_name,
-        state_expiration_seconds: int = OAuthStateUtils.default_expiration_seconds,
-        installation_store_bot_only: bool = False,
-        token_rotation_expiration_minutes: int = 120,
-        client: Optional[WebClient] = None,
-        logger: Optional[Logger] = None,
-    ) -> "OAuthFlow":
-
-        client_id = client_id or os.environ["SLACK_CLIENT_ID"]  # required
-        client_secret = client_secret or os.environ["SLACK_CLIENT_SECRET"]  # required
-        scopes = scopes or os.environ.get("SLACK_SCOPES", "").split(",")
-        user_scopes = user_scopes or os.environ.get("SLACK_USER_SCOPES", "").split(",")
-        redirect_uri = redirect_uri or os.environ.get("SLACK_REDIRECT_URI")
-        installation_store = (
-            SQLite3InstallationStore(database=database, client_id=client_id)
-            if logger is None
-            else SQLite3InstallationStore(database=database, client_id=client_id, logger=logger)
-        )
-        state_store = (
-            SQLite3OAuthStateStore(database=database, expiration_seconds=state_expiration_seconds)
-            if logger is None
-            else SQLite3OAuthStateStore(database=database, expiration_seconds=state_expiration_seconds, logger=logger)
-        )
-        return OAuthFlow(
-            client=client or WebClient(),
-            logger=logger,
-            settings=OAuthSettings(
-                # OAuth flow parameters/credentials
-                client_id=client_id,
-                client_secret=client_secret,
-                scopes=scopes,
-                user_scopes=user_scopes,
-                redirect_uri=redirect_uri,
-                # Handler configuration
-                install_path=install_path,  # type: ignore[arg-type]
-                redirect_uri_path=redirect_uri_path,  # type: ignore[arg-type]
-                callback_options=callback_options,
-                success_url=success_url,
-                failure_url=failure_url,
-                authorization_url=authorization_url,
-                # Installation Management
-                installation_store=installation_store,
-                installation_store_bot_only=installation_store_bot_only,
-                token_rotation_expiration_minutes=token_rotation_expiration_minutes,
-                # state parameter related configurations
-                state_store=state_store,
-                state_cookie_name=state_cookie_name,
-                state_expiration_seconds=state_expiration_seconds,
-            ),
-        )
-
-    # -----------------------------
-    # Installation
-    # -----------------------------
-
-    def handle_installation(self, request: BoltRequest) -> BoltResponse:
-        set_cookie_value: Optional[str] = None
-        url = self.build_authorize_url("", request)
-        if self.settings.state_validation_enabled is True:
-            state = self.issue_new_state(request)
-            url = self.build_authorize_url(state, request)
-            set_cookie_value = self.settings.state_utils.build_set_cookie_for_new_state(state)
-
-        if self.settings.install_page_rendering_enabled:
-            html = self.build_install_page_html(url, request)
-            return BoltResponse(
-                status=200,
-                body=html,
-                headers=self.append_set_cookie_headers(
-                    {"Content-Type": "text/html; charset=utf-8"},
-                    set_cookie_value,
-                ),
-            )
-        else:
-            return BoltResponse(
-                status=302,
-                body="",
-                headers=self.append_set_cookie_headers(
-                    {"Content-Type": "text/html; charset=utf-8", "Location": url},
-                    set_cookie_value,
-                ),
-            )
-
-    # ----------------------
-    # Internal methods for Installation
-
-    def issue_new_state(self, request: BoltRequest) -> str:
-        return self.settings.state_store.issue()
-
-    def build_authorize_url(self, state: str, request: BoltRequest) -> str:
-        team_ids: Optional[Sequence[str]] = request.query.get("team")
-        return self.settings.authorize_url_generator.generate(
-            state=state,
-            team=team_ids[0] if team_ids is not None else None,
-        )
-
-    def build_install_page_html(self, url: str, request: BoltRequest) -> str:
-        return _build_default_install_page_html(url)
-
-    def append_set_cookie_headers(self, headers: dict, set_cookie_value: Optional[str]):
-        if set_cookie_value is not None:
-            headers["Set-Cookie"] = [set_cookie_value]
-        return headers
-
-    # -----------------------------
-    # Callback
-    # -----------------------------
-
-    def handle_callback(self, request: BoltRequest) -> BoltResponse:
-
-        # failure due to end-user's cancellation or invalid redirection to slack.com
-        error = request.query.get("error", [None])[0]
-        if error is not None:
-            return self.failure_handler(
-                FailureArgs(
-                    request=request,
-                    reason=error,
-                    suggested_status_code=200,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        # state parameter verification
-        if self.settings.state_validation_enabled is True:
-            state = request.query.get("state", [None])[0]
-            if not self.settings.state_utils.is_valid_browser(state, request.headers):
-                return self.failure_handler(
-                    FailureArgs(
-                        request=request,
-                        reason="invalid_browser",
-                        suggested_status_code=400,
-                        settings=self.settings,
-                        default=self.default_callback_options,
-                    )
-                )
-
-            valid_state_consumed = self.settings.state_store.consume(state)  # type: ignore[arg-type]
-            if not valid_state_consumed:
-                return self.failure_handler(
-                    FailureArgs(
-                        request=request,
-                        reason="invalid_state",
-                        suggested_status_code=401,
-                        settings=self.settings,
-                        default=self.default_callback_options,
-                    )
-                )
-
-        # run installation
-        code = request.query.get("code", [None])[0]
-        if code is None:
-            return self.failure_handler(
-                FailureArgs(
-                    request=request,
-                    reason="missing_code",
-                    suggested_status_code=401,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        installation = self.run_installation(code)
-        if installation is None:
-            # failed to run installation with the code
-            return self.failure_handler(
-                FailureArgs(
-                    request=request,
-                    reason="invalid_code",
-                    suggested_status_code=401,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        # persist the installation
-        try:
-            self.store_installation(request, installation)
-        except BoltError as err:
-            return self.failure_handler(
-                FailureArgs(
-                    request=request,
-                    reason="storage_error",
-                    error=err,
-                    suggested_status_code=500,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        # display a successful completion page to the end-user
-        return self.success_handler(
-            SuccessArgs(
-                request=request,
-                installation=installation,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    # ----------------------
-    # Internal methods for Callback
-
-    def run_installation(self, code: str) -> Optional[Installation]:
-        try:
-            oauth_response: SlackResponse = self.client.oauth_v2_access(
-                code=code,
-                client_id=self.settings.client_id,
-                client_secret=self.settings.client_secret,
-                redirect_uri=self.settings.redirect_uri,  # can be None
-            )
-            installed_enterprise: Dict[str, str] = oauth_response.get("enterprise") or {}
-            is_enterprise_install: bool = oauth_response.get("is_enterprise_install") or False
-            installed_team: Dict[str, str] = oauth_response.get("team") or {}
-            installer: Dict[str, str] = oauth_response.get("authed_user") or {}
-            incoming_webhook: Dict[str, str] = oauth_response.get("incoming_webhook") or {}
-
-            bot_token: Optional[str] = oauth_response.get("access_token")
-            # NOTE: oauth.v2.access doesn't include bot_id in response
-            bot_id: Optional[str] = None
-            enterprise_url: Optional[str] = None
-            if bot_token is not None:
-                auth_test = self.client.auth_test(token=bot_token)
-                bot_id = auth_test["bot_id"]
-                if is_enterprise_install is True:
-                    enterprise_url = auth_test.get("url")
-
-            return Installation(
-                app_id=oauth_response.get("app_id"),
-                enterprise_id=installed_enterprise.get("id"),
-                enterprise_name=installed_enterprise.get("name"),
-                enterprise_url=enterprise_url,
-                team_id=installed_team.get("id"),
-                team_name=installed_team.get("name"),
-                bot_token=bot_token,
-                bot_id=bot_id,
-                bot_user_id=oauth_response.get("bot_user_id"),
-                bot_scopes=oauth_response.get("scope"),  # type: ignore[arg-type] # comma-separated string
-                bot_refresh_token=oauth_response.get("refresh_token"),  # since v1.7
-                bot_token_expires_in=oauth_response.get("expires_in"),  # since v1.7
-                user_id=installer.get("id"),  # type: ignore[arg-type]
-                user_token=installer.get("access_token"),
-                user_scopes=installer.get("scope"),  # type: ignore[arg-type] # comma-separated string
-                user_refresh_token=installer.get("refresh_token"),  # since v1.7
-                user_token_expires_in=installer.get("expires_in"),  # type: ignore[arg-type] # since v1.7
-                incoming_webhook_url=incoming_webhook.get("url"),
-                incoming_webhook_channel=incoming_webhook.get("channel"),
-                incoming_webhook_channel_id=incoming_webhook.get("channel_id"),
-                incoming_webhook_configuration_url=incoming_webhook.get("configuration_url"),
-                is_enterprise_install=is_enterprise_install,
-                token_type=oauth_response.get("token_type"),
-            )
-
-        except SlackApiError as e:
-            message = f"Failed to fetch oauth.v2.access result with code: {code} - error: {e}"
-            self.logger.warning(message)
-            return None
-
-    def store_installation(self, request: BoltRequest, installation: Installation):
-        # may raise BoltError
-        self.settings.installation_store.save(installation)
-
-

The module to run the Slack app installation flow (OAuth flow).

-

Args

-
-
client
-
The slack_sdk.web.WebClient instance.
-
logger
-
The logger.
-
settings
-
OAuth settings to configure this module.
-
-

Subclasses

- -

Class variables

-
-
var client_id : str
-
-

The type of the None singleton.

-
-
var failure_handler : Callable[[FailureArgs], BoltResponse]
-
-

The type of the None singleton.

-
-
var install_path : str
-
-

The type of the None singleton.

-
-
var redirect_uri : str | None
-
-

The type of the None singleton.

-
-
var redirect_uri_path : str
-
-

The type of the None singleton.

-
-
var settingsOAuthSettings
-
-

The type of the None singleton.

-
-
var success_handler : Callable[[SuccessArgs], BoltResponse]
-
-

The type of the None singleton.

-
-
-

Static methods

-
-
-def sqlite3(database: str,
client_id: str | None = None,
client_secret: str | None = None,
scopes: Sequence[str] | None = None,
user_scopes: Sequence[str] | None = None,
redirect_uri: str | None = None,
install_path: str | None = None,
redirect_uri_path: str | None = None,
callback_options: CallbackOptions | None = None,
success_url: str | None = None,
failure_url: str | None = None,
authorization_url: str | None = None,
state_cookie_name: str = 'slack-app-oauth-state',
state_expiration_seconds: int = 600,
installation_store_bot_only: bool = False,
token_rotation_expiration_minutes: int = 120,
client: slack_sdk.web.client.WebClient | None = None,
logger: logging.Logger | None = None) ‑> OAuthFlow
-
-
-
-
-
-

Instance variables

-
-
prop client : slack_sdk.web.client.WebClient
-
-
- -Expand source code - -
@property
-def client(self) -> WebClient:
-    if self._client is None:
-        self._client = create_web_client(logger=self.logger)
-    return self._client
-
-
-
-
prop logger : logging.Logger
-
-
- -Expand source code - -
@property
-def logger(self) -> Logger:
-    if self._logger is None:
-        self._logger = logging.getLogger(__name__)
-    return self._logger
-
-
-
-
-

Methods

-
- -
-
- -Expand source code - -
def append_set_cookie_headers(self, headers: dict, set_cookie_value: Optional[str]):
-    if set_cookie_value is not None:
-        headers["Set-Cookie"] = [set_cookie_value]
-    return headers
-
-
-
-
-def build_authorize_url(self,
state: str,
request: BoltRequest) ‑> str
-
-
-
- -Expand source code - -
def build_authorize_url(self, state: str, request: BoltRequest) -> str:
-    team_ids: Optional[Sequence[str]] = request.query.get("team")
-    return self.settings.authorize_url_generator.generate(
-        state=state,
-        team=team_ids[0] if team_ids is not None else None,
-    )
-
-
-
-
-def build_install_page_html(self,
url: str,
request: BoltRequest) ‑> str
-
-
-
- -Expand source code - -
def build_install_page_html(self, url: str, request: BoltRequest) -> str:
-    return _build_default_install_page_html(url)
-
-
-
-
-def handle_callback(self,
request: BoltRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def handle_callback(self, request: BoltRequest) -> BoltResponse:
-
-    # failure due to end-user's cancellation or invalid redirection to slack.com
-    error = request.query.get("error", [None])[0]
-    if error is not None:
-        return self.failure_handler(
-            FailureArgs(
-                request=request,
-                reason=error,
-                suggested_status_code=200,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    # state parameter verification
-    if self.settings.state_validation_enabled is True:
-        state = request.query.get("state", [None])[0]
-        if not self.settings.state_utils.is_valid_browser(state, request.headers):
-            return self.failure_handler(
-                FailureArgs(
-                    request=request,
-                    reason="invalid_browser",
-                    suggested_status_code=400,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        valid_state_consumed = self.settings.state_store.consume(state)  # type: ignore[arg-type]
-        if not valid_state_consumed:
-            return self.failure_handler(
-                FailureArgs(
-                    request=request,
-                    reason="invalid_state",
-                    suggested_status_code=401,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-    # run installation
-    code = request.query.get("code", [None])[0]
-    if code is None:
-        return self.failure_handler(
-            FailureArgs(
-                request=request,
-                reason="missing_code",
-                suggested_status_code=401,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    installation = self.run_installation(code)
-    if installation is None:
-        # failed to run installation with the code
-        return self.failure_handler(
-            FailureArgs(
-                request=request,
-                reason="invalid_code",
-                suggested_status_code=401,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    # persist the installation
-    try:
-        self.store_installation(request, installation)
-    except BoltError as err:
-        return self.failure_handler(
-            FailureArgs(
-                request=request,
-                reason="storage_error",
-                error=err,
-                suggested_status_code=500,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    # display a successful completion page to the end-user
-    return self.success_handler(
-        SuccessArgs(
-            request=request,
-            installation=installation,
-            settings=self.settings,
-            default=self.default_callback_options,
-        )
-    )
-
-
-
-
-def handle_installation(self,
request: BoltRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def handle_installation(self, request: BoltRequest) -> BoltResponse:
-    set_cookie_value: Optional[str] = None
-    url = self.build_authorize_url("", request)
-    if self.settings.state_validation_enabled is True:
-        state = self.issue_new_state(request)
-        url = self.build_authorize_url(state, request)
-        set_cookie_value = self.settings.state_utils.build_set_cookie_for_new_state(state)
-
-    if self.settings.install_page_rendering_enabled:
-        html = self.build_install_page_html(url, request)
-        return BoltResponse(
-            status=200,
-            body=html,
-            headers=self.append_set_cookie_headers(
-                {"Content-Type": "text/html; charset=utf-8"},
-                set_cookie_value,
-            ),
-        )
-    else:
-        return BoltResponse(
-            status=302,
-            body="",
-            headers=self.append_set_cookie_headers(
-                {"Content-Type": "text/html; charset=utf-8", "Location": url},
-                set_cookie_value,
-            ),
-        )
-
-
-
-
-def issue_new_state(self,
request: BoltRequest) ‑> str
-
-
-
- -Expand source code - -
def issue_new_state(self, request: BoltRequest) -> str:
-    return self.settings.state_store.issue()
-
-
-
-
-def run_installation(self, code: str) ‑> slack_sdk.oauth.installation_store.models.installation.Installation | None -
-
-
- -Expand source code - -
def run_installation(self, code: str) -> Optional[Installation]:
-    try:
-        oauth_response: SlackResponse = self.client.oauth_v2_access(
-            code=code,
-            client_id=self.settings.client_id,
-            client_secret=self.settings.client_secret,
-            redirect_uri=self.settings.redirect_uri,  # can be None
-        )
-        installed_enterprise: Dict[str, str] = oauth_response.get("enterprise") or {}
-        is_enterprise_install: bool = oauth_response.get("is_enterprise_install") or False
-        installed_team: Dict[str, str] = oauth_response.get("team") or {}
-        installer: Dict[str, str] = oauth_response.get("authed_user") or {}
-        incoming_webhook: Dict[str, str] = oauth_response.get("incoming_webhook") or {}
-
-        bot_token: Optional[str] = oauth_response.get("access_token")
-        # NOTE: oauth.v2.access doesn't include bot_id in response
-        bot_id: Optional[str] = None
-        enterprise_url: Optional[str] = None
-        if bot_token is not None:
-            auth_test = self.client.auth_test(token=bot_token)
-            bot_id = auth_test["bot_id"]
-            if is_enterprise_install is True:
-                enterprise_url = auth_test.get("url")
-
-        return Installation(
-            app_id=oauth_response.get("app_id"),
-            enterprise_id=installed_enterprise.get("id"),
-            enterprise_name=installed_enterprise.get("name"),
-            enterprise_url=enterprise_url,
-            team_id=installed_team.get("id"),
-            team_name=installed_team.get("name"),
-            bot_token=bot_token,
-            bot_id=bot_id,
-            bot_user_id=oauth_response.get("bot_user_id"),
-            bot_scopes=oauth_response.get("scope"),  # type: ignore[arg-type] # comma-separated string
-            bot_refresh_token=oauth_response.get("refresh_token"),  # since v1.7
-            bot_token_expires_in=oauth_response.get("expires_in"),  # since v1.7
-            user_id=installer.get("id"),  # type: ignore[arg-type]
-            user_token=installer.get("access_token"),
-            user_scopes=installer.get("scope"),  # type: ignore[arg-type] # comma-separated string
-            user_refresh_token=installer.get("refresh_token"),  # since v1.7
-            user_token_expires_in=installer.get("expires_in"),  # type: ignore[arg-type] # since v1.7
-            incoming_webhook_url=incoming_webhook.get("url"),
-            incoming_webhook_channel=incoming_webhook.get("channel"),
-            incoming_webhook_channel_id=incoming_webhook.get("channel_id"),
-            incoming_webhook_configuration_url=incoming_webhook.get("configuration_url"),
-            is_enterprise_install=is_enterprise_install,
-            token_type=oauth_response.get("token_type"),
-        )
-
-    except SlackApiError as e:
-        message = f"Failed to fetch oauth.v2.access result with code: {code} - error: {e}"
-        self.logger.warning(message)
-        return None
-
-
-
-
-def store_installation(self,
request: BoltRequest,
installation: slack_sdk.oauth.installation_store.models.installation.Installation)
-
-
-
- -Expand source code - -
def store_installation(self, request: BoltRequest, installation: Installation):
-    # may raise BoltError
-    self.settings.installation_store.save(installation)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/oauth/internals.html b/docs/reference/oauth/internals.html deleted file mode 100644 index 3f1b43a7e..000000000 --- a/docs/reference/oauth/internals.html +++ /dev/null @@ -1,231 +0,0 @@ - - - - - - -slack_bolt.oauth.internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.oauth.internals

-
-
-
-
-
-
-
-
-

Functions

-
-
-def build_detailed_error(reason: str) ‑> str -
-
-
- -Expand source code - -
def build_detailed_error(reason: str) -> str:
-    if reason == "invalid_browser":
-        return (
-            f"{reason}: This can occur due to page reload, "
-            "not beginning the OAuth flow from the valid starting URL, or "
-            "the /slack/install URL not using https://"
-        )
-    elif reason == "invalid_state":
-        return f"{reason}: The state parameter is no longer valid."
-    elif reason == "missing_code":
-        return f"{reason}: The code parameter is missing in this redirection."
-    elif reason == "storage_error":
-        return f"{reason}: The app's server encountered an issue. Contact the app developer."
-    else:
-        return f"{html.escape(reason)}: This error code is returned from Slack. Refer to the documents for details."
-
-
-
-
-def get_or_create_default_installation_store(client_id: str) ‑> slack_sdk.oauth.installation_store.installation_store.InstallationStore -
-
-
- -Expand source code - -
def get_or_create_default_installation_store(client_id: str) -> InstallationStore:
-    store = default_installation_stores.get(client_id)
-    if store is None:
-        store = FileInstallationStore(client_id=client_id)
-        default_installation_stores[client_id] = store
-    return store
-
-
-
-
-def select_consistent_installation_store(client_id: str,
app_store: slack_sdk.oauth.installation_store.installation_store.InstallationStore | None,
oauth_flow_store: slack_sdk.oauth.installation_store.installation_store.InstallationStore | None,
logger: logging.Logger) ‑> slack_sdk.oauth.installation_store.installation_store.InstallationStore | None
-
-
-
- -Expand source code - -
def select_consistent_installation_store(
-    client_id: str,
-    app_store: Optional[InstallationStore],
-    oauth_flow_store: Optional[InstallationStore],
-    logger: Logger,
-) -> Optional[InstallationStore]:
-    default = get_or_create_default_installation_store(client_id)
-    if app_store is not None:
-        if oauth_flow_store is not None:
-            if oauth_flow_store is default:
-                # only app_store is intentionally set in this case
-                return app_store
-
-            # if both are intentionally set, prioritize app_store
-            if oauth_flow_store is not app_store:
-                logger.warning(warning_installation_store_conflicts())
-            return oauth_flow_store
-        else:
-            # only app_store is available
-            return app_store
-    else:
-        # only oauth_flow_store is available
-        return oauth_flow_store
-
-
-
-
-
-
-

Classes

-
-
-class CallbackResponseBuilder -(*,
logger: logging.Logger,
state_utils: slack_sdk.oauth.state_utils.OAuthStateUtils,
redirect_uri_page_renderer: slack_sdk.oauth.redirect_uri_page_renderer.RedirectUriPageRenderer)
-
-
-
- -Expand source code - -
class CallbackResponseBuilder:
-    def __init__(
-        self,
-        *,
-        logger: Logger,
-        state_utils: OAuthStateUtils,
-        redirect_uri_page_renderer: RedirectUriPageRenderer,
-    ):
-        self._logger = logger
-        self._state_utils = state_utils
-        self._redirect_uri_page_renderer = redirect_uri_page_renderer
-
-    def _build_callback_success_response(
-        self,
-        request: Union[BoltRequest, "AsyncBoltRequest"],  # type: ignore[name-defined]
-        installation: Installation,
-    ) -> BoltResponse:
-        debug_message = f"Handling an OAuth callback success (request: {request.query})"
-        self._logger.debug(debug_message)
-
-        page_content = self._redirect_uri_page_renderer.render_success_page(
-            app_id=installation.app_id,  # type: ignore[arg-type]
-            team_id=installation.team_id,
-            is_enterprise_install=installation.is_enterprise_install,
-            enterprise_url=installation.enterprise_url,
-        )
-        return BoltResponse(
-            status=200,
-            headers={
-                "Content-Type": "text/html; charset=utf-8",
-                "Set-Cookie": self._state_utils.build_set_cookie_for_deletion(),
-            },
-            body=page_content,
-        )
-
-    def _build_callback_failure_response(
-        self,
-        request: Union[BoltRequest, "AsyncBoltRequest"],  # type: ignore[name-defined]
-        reason: str,
-        status: int = 500,
-        error: Optional[Exception] = None,
-    ) -> BoltResponse:
-        debug_message = "Handling an OAuth callback failure " f"(reason: {reason}, error: {error}, request: {request.query})"
-        self._logger.debug(debug_message)
-
-        # Adding a bit more details to the error code to help installers understand what's happening.
-        # This modification in the HTML page works only when developers use this built-in failure handler.
-        detailed_error = build_detailed_error(reason)
-        return BoltResponse(
-            status=status,
-            headers={
-                "Content-Type": "text/html; charset=utf-8",
-                "Set-Cookie": self._state_utils.build_set_cookie_for_deletion(),
-            },
-            body=self._redirect_uri_page_renderer.render_failure_page(detailed_error),
-        )
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/oauth/oauth_flow.html b/docs/reference/oauth/oauth_flow.html deleted file mode 100644 index 75aa3cb88..000000000 --- a/docs/reference/oauth/oauth_flow.html +++ /dev/null @@ -1,813 +0,0 @@ - - - - - - -slack_bolt.oauth.oauth_flow API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.oauth.oauth_flow

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class OAuthFlow -(*,
client: slack_sdk.web.client.WebClient | None = None,
logger: logging.Logger | None = None,
settings: OAuthSettings)
-
-
-
- -Expand source code - -
class OAuthFlow:
-    settings: OAuthSettings
-    client_id: str
-    redirect_uri: Optional[str]
-    install_path: str
-    redirect_uri_path: str
-
-    success_handler: Callable[[SuccessArgs], BoltResponse]
-    failure_handler: Callable[[FailureArgs], BoltResponse]
-
-    def __init__(
-        self,
-        *,
-        client: Optional[WebClient] = None,
-        logger: Optional[Logger] = None,
-        settings: OAuthSettings,
-    ):
-        """The module to run the Slack app installation flow (OAuth flow).
-
-        Args:
-            client: The `slack_sdk.web.WebClient` instance.
-            logger: The logger.
-            settings: OAuth settings to configure this module.
-        """
-        self._client = client
-        self._logger = logger
-        self.settings = settings
-        if self._logger is not None:
-            self.settings.logger = self._logger
-
-        self.client_id = self.settings.client_id
-        self.redirect_uri = self.settings.redirect_uri
-        self.install_path = self.settings.install_path
-        self.redirect_uri_path = self.settings.redirect_uri_path
-
-        self.default_callback_options = DefaultCallbackOptions(
-            logger=logger,  # type: ignore[arg-type]
-            state_utils=self.settings.state_utils,
-            redirect_uri_page_renderer=self.settings.redirect_uri_page_renderer,
-        )
-        if settings.callback_options is None:
-            settings.callback_options = self.default_callback_options
-        self.success_handler = settings.callback_options.success
-        self.failure_handler = settings.callback_options.failure
-
-    @property
-    def client(self) -> WebClient:
-        if self._client is None:
-            self._client = create_web_client(logger=self.logger)
-        return self._client
-
-    @property
-    def logger(self) -> Logger:
-        if self._logger is None:
-            self._logger = logging.getLogger(__name__)
-        return self._logger
-
-    # -----------------------------
-    # Factory Methods
-    # -----------------------------
-
-    @classmethod
-    def sqlite3(
-        cls,
-        database: str,
-        # OAuth flow parameters/credentials
-        client_id: Optional[str] = None,  # required
-        client_secret: Optional[str] = None,  # required
-        scopes: Optional[Sequence[str]] = None,
-        user_scopes: Optional[Sequence[str]] = None,
-        redirect_uri: Optional[str] = None,
-        # Handler configuration
-        install_path: Optional[str] = None,
-        redirect_uri_path: Optional[str] = None,
-        callback_options: Optional[CallbackOptions] = None,
-        success_url: Optional[str] = None,
-        failure_url: Optional[str] = None,
-        authorization_url: Optional[str] = None,
-        # Installation Management
-        # state parameter related configurations
-        state_cookie_name: str = OAuthStateUtils.default_cookie_name,
-        state_expiration_seconds: int = OAuthStateUtils.default_expiration_seconds,
-        installation_store_bot_only: bool = False,
-        token_rotation_expiration_minutes: int = 120,
-        client: Optional[WebClient] = None,
-        logger: Optional[Logger] = None,
-    ) -> "OAuthFlow":
-
-        client_id = client_id or os.environ["SLACK_CLIENT_ID"]  # required
-        client_secret = client_secret or os.environ["SLACK_CLIENT_SECRET"]  # required
-        scopes = scopes or os.environ.get("SLACK_SCOPES", "").split(",")
-        user_scopes = user_scopes or os.environ.get("SLACK_USER_SCOPES", "").split(",")
-        redirect_uri = redirect_uri or os.environ.get("SLACK_REDIRECT_URI")
-        installation_store = (
-            SQLite3InstallationStore(database=database, client_id=client_id)
-            if logger is None
-            else SQLite3InstallationStore(database=database, client_id=client_id, logger=logger)
-        )
-        state_store = (
-            SQLite3OAuthStateStore(database=database, expiration_seconds=state_expiration_seconds)
-            if logger is None
-            else SQLite3OAuthStateStore(database=database, expiration_seconds=state_expiration_seconds, logger=logger)
-        )
-        return OAuthFlow(
-            client=client or WebClient(),
-            logger=logger,
-            settings=OAuthSettings(
-                # OAuth flow parameters/credentials
-                client_id=client_id,
-                client_secret=client_secret,
-                scopes=scopes,
-                user_scopes=user_scopes,
-                redirect_uri=redirect_uri,
-                # Handler configuration
-                install_path=install_path,  # type: ignore[arg-type]
-                redirect_uri_path=redirect_uri_path,  # type: ignore[arg-type]
-                callback_options=callback_options,
-                success_url=success_url,
-                failure_url=failure_url,
-                authorization_url=authorization_url,
-                # Installation Management
-                installation_store=installation_store,
-                installation_store_bot_only=installation_store_bot_only,
-                token_rotation_expiration_minutes=token_rotation_expiration_minutes,
-                # state parameter related configurations
-                state_store=state_store,
-                state_cookie_name=state_cookie_name,
-                state_expiration_seconds=state_expiration_seconds,
-            ),
-        )
-
-    # -----------------------------
-    # Installation
-    # -----------------------------
-
-    def handle_installation(self, request: BoltRequest) -> BoltResponse:
-        set_cookie_value: Optional[str] = None
-        url = self.build_authorize_url("", request)
-        if self.settings.state_validation_enabled is True:
-            state = self.issue_new_state(request)
-            url = self.build_authorize_url(state, request)
-            set_cookie_value = self.settings.state_utils.build_set_cookie_for_new_state(state)
-
-        if self.settings.install_page_rendering_enabled:
-            html = self.build_install_page_html(url, request)
-            return BoltResponse(
-                status=200,
-                body=html,
-                headers=self.append_set_cookie_headers(
-                    {"Content-Type": "text/html; charset=utf-8"},
-                    set_cookie_value,
-                ),
-            )
-        else:
-            return BoltResponse(
-                status=302,
-                body="",
-                headers=self.append_set_cookie_headers(
-                    {"Content-Type": "text/html; charset=utf-8", "Location": url},
-                    set_cookie_value,
-                ),
-            )
-
-    # ----------------------
-    # Internal methods for Installation
-
-    def issue_new_state(self, request: BoltRequest) -> str:
-        return self.settings.state_store.issue()
-
-    def build_authorize_url(self, state: str, request: BoltRequest) -> str:
-        team_ids: Optional[Sequence[str]] = request.query.get("team")
-        return self.settings.authorize_url_generator.generate(
-            state=state,
-            team=team_ids[0] if team_ids is not None else None,
-        )
-
-    def build_install_page_html(self, url: str, request: BoltRequest) -> str:
-        return _build_default_install_page_html(url)
-
-    def append_set_cookie_headers(self, headers: dict, set_cookie_value: Optional[str]):
-        if set_cookie_value is not None:
-            headers["Set-Cookie"] = [set_cookie_value]
-        return headers
-
-    # -----------------------------
-    # Callback
-    # -----------------------------
-
-    def handle_callback(self, request: BoltRequest) -> BoltResponse:
-
-        # failure due to end-user's cancellation or invalid redirection to slack.com
-        error = request.query.get("error", [None])[0]
-        if error is not None:
-            return self.failure_handler(
-                FailureArgs(
-                    request=request,
-                    reason=error,
-                    suggested_status_code=200,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        # state parameter verification
-        if self.settings.state_validation_enabled is True:
-            state = request.query.get("state", [None])[0]
-            if not self.settings.state_utils.is_valid_browser(state, request.headers):
-                return self.failure_handler(
-                    FailureArgs(
-                        request=request,
-                        reason="invalid_browser",
-                        suggested_status_code=400,
-                        settings=self.settings,
-                        default=self.default_callback_options,
-                    )
-                )
-
-            valid_state_consumed = self.settings.state_store.consume(state)  # type: ignore[arg-type]
-            if not valid_state_consumed:
-                return self.failure_handler(
-                    FailureArgs(
-                        request=request,
-                        reason="invalid_state",
-                        suggested_status_code=401,
-                        settings=self.settings,
-                        default=self.default_callback_options,
-                    )
-                )
-
-        # run installation
-        code = request.query.get("code", [None])[0]
-        if code is None:
-            return self.failure_handler(
-                FailureArgs(
-                    request=request,
-                    reason="missing_code",
-                    suggested_status_code=401,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        installation = self.run_installation(code)
-        if installation is None:
-            # failed to run installation with the code
-            return self.failure_handler(
-                FailureArgs(
-                    request=request,
-                    reason="invalid_code",
-                    suggested_status_code=401,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        # persist the installation
-        try:
-            self.store_installation(request, installation)
-        except BoltError as err:
-            return self.failure_handler(
-                FailureArgs(
-                    request=request,
-                    reason="storage_error",
-                    error=err,
-                    suggested_status_code=500,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        # display a successful completion page to the end-user
-        return self.success_handler(
-            SuccessArgs(
-                request=request,
-                installation=installation,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    # ----------------------
-    # Internal methods for Callback
-
-    def run_installation(self, code: str) -> Optional[Installation]:
-        try:
-            oauth_response: SlackResponse = self.client.oauth_v2_access(
-                code=code,
-                client_id=self.settings.client_id,
-                client_secret=self.settings.client_secret,
-                redirect_uri=self.settings.redirect_uri,  # can be None
-            )
-            installed_enterprise: Dict[str, str] = oauth_response.get("enterprise") or {}
-            is_enterprise_install: bool = oauth_response.get("is_enterprise_install") or False
-            installed_team: Dict[str, str] = oauth_response.get("team") or {}
-            installer: Dict[str, str] = oauth_response.get("authed_user") or {}
-            incoming_webhook: Dict[str, str] = oauth_response.get("incoming_webhook") or {}
-
-            bot_token: Optional[str] = oauth_response.get("access_token")
-            # NOTE: oauth.v2.access doesn't include bot_id in response
-            bot_id: Optional[str] = None
-            enterprise_url: Optional[str] = None
-            if bot_token is not None:
-                auth_test = self.client.auth_test(token=bot_token)
-                bot_id = auth_test["bot_id"]
-                if is_enterprise_install is True:
-                    enterprise_url = auth_test.get("url")
-
-            return Installation(
-                app_id=oauth_response.get("app_id"),
-                enterprise_id=installed_enterprise.get("id"),
-                enterprise_name=installed_enterprise.get("name"),
-                enterprise_url=enterprise_url,
-                team_id=installed_team.get("id"),
-                team_name=installed_team.get("name"),
-                bot_token=bot_token,
-                bot_id=bot_id,
-                bot_user_id=oauth_response.get("bot_user_id"),
-                bot_scopes=oauth_response.get("scope"),  # type: ignore[arg-type] # comma-separated string
-                bot_refresh_token=oauth_response.get("refresh_token"),  # since v1.7
-                bot_token_expires_in=oauth_response.get("expires_in"),  # since v1.7
-                user_id=installer.get("id"),  # type: ignore[arg-type]
-                user_token=installer.get("access_token"),
-                user_scopes=installer.get("scope"),  # type: ignore[arg-type] # comma-separated string
-                user_refresh_token=installer.get("refresh_token"),  # since v1.7
-                user_token_expires_in=installer.get("expires_in"),  # type: ignore[arg-type] # since v1.7
-                incoming_webhook_url=incoming_webhook.get("url"),
-                incoming_webhook_channel=incoming_webhook.get("channel"),
-                incoming_webhook_channel_id=incoming_webhook.get("channel_id"),
-                incoming_webhook_configuration_url=incoming_webhook.get("configuration_url"),
-                is_enterprise_install=is_enterprise_install,
-                token_type=oauth_response.get("token_type"),
-            )
-
-        except SlackApiError as e:
-            message = f"Failed to fetch oauth.v2.access result with code: {code} - error: {e}"
-            self.logger.warning(message)
-            return None
-
-    def store_installation(self, request: BoltRequest, installation: Installation):
-        # may raise BoltError
-        self.settings.installation_store.save(installation)
-
-

The module to run the Slack app installation flow (OAuth flow).

-

Args

-
-
client
-
The slack_sdk.web.WebClient instance.
-
logger
-
The logger.
-
settings
-
OAuth settings to configure this module.
-
-

Subclasses

- -

Class variables

-
-
var client_id : str
-
-

The type of the None singleton.

-
-
var failure_handler : Callable[[FailureArgs], BoltResponse]
-
-

The type of the None singleton.

-
-
var install_path : str
-
-

The type of the None singleton.

-
-
var redirect_uri : str | None
-
-

The type of the None singleton.

-
-
var redirect_uri_path : str
-
-

The type of the None singleton.

-
-
var settingsOAuthSettings
-
-

The type of the None singleton.

-
-
var success_handler : Callable[[SuccessArgs], BoltResponse]
-
-

The type of the None singleton.

-
-
-

Static methods

-
-
-def sqlite3(database: str,
client_id: str | None = None,
client_secret: str | None = None,
scopes: Sequence[str] | None = None,
user_scopes: Sequence[str] | None = None,
redirect_uri: str | None = None,
install_path: str | None = None,
redirect_uri_path: str | None = None,
callback_options: CallbackOptions | None = None,
success_url: str | None = None,
failure_url: str | None = None,
authorization_url: str | None = None,
state_cookie_name: str = 'slack-app-oauth-state',
state_expiration_seconds: int = 600,
installation_store_bot_only: bool = False,
token_rotation_expiration_minutes: int = 120,
client: slack_sdk.web.client.WebClient | None = None,
logger: logging.Logger | None = None) ‑> OAuthFlow
-
-
-
-
-
-

Instance variables

-
-
prop client : slack_sdk.web.client.WebClient
-
-
- -Expand source code - -
@property
-def client(self) -> WebClient:
-    if self._client is None:
-        self._client = create_web_client(logger=self.logger)
-    return self._client
-
-
-
-
prop logger : logging.Logger
-
-
- -Expand source code - -
@property
-def logger(self) -> Logger:
-    if self._logger is None:
-        self._logger = logging.getLogger(__name__)
-    return self._logger
-
-
-
-
-

Methods

-
- -
-
- -Expand source code - -
def append_set_cookie_headers(self, headers: dict, set_cookie_value: Optional[str]):
-    if set_cookie_value is not None:
-        headers["Set-Cookie"] = [set_cookie_value]
-    return headers
-
-
-
-
-def build_authorize_url(self,
state: str,
request: BoltRequest) ‑> str
-
-
-
- -Expand source code - -
def build_authorize_url(self, state: str, request: BoltRequest) -> str:
-    team_ids: Optional[Sequence[str]] = request.query.get("team")
-    return self.settings.authorize_url_generator.generate(
-        state=state,
-        team=team_ids[0] if team_ids is not None else None,
-    )
-
-
-
-
-def build_install_page_html(self,
url: str,
request: BoltRequest) ‑> str
-
-
-
- -Expand source code - -
def build_install_page_html(self, url: str, request: BoltRequest) -> str:
-    return _build_default_install_page_html(url)
-
-
-
-
-def handle_callback(self,
request: BoltRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def handle_callback(self, request: BoltRequest) -> BoltResponse:
-
-    # failure due to end-user's cancellation or invalid redirection to slack.com
-    error = request.query.get("error", [None])[0]
-    if error is not None:
-        return self.failure_handler(
-            FailureArgs(
-                request=request,
-                reason=error,
-                suggested_status_code=200,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    # state parameter verification
-    if self.settings.state_validation_enabled is True:
-        state = request.query.get("state", [None])[0]
-        if not self.settings.state_utils.is_valid_browser(state, request.headers):
-            return self.failure_handler(
-                FailureArgs(
-                    request=request,
-                    reason="invalid_browser",
-                    suggested_status_code=400,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-        valid_state_consumed = self.settings.state_store.consume(state)  # type: ignore[arg-type]
-        if not valid_state_consumed:
-            return self.failure_handler(
-                FailureArgs(
-                    request=request,
-                    reason="invalid_state",
-                    suggested_status_code=401,
-                    settings=self.settings,
-                    default=self.default_callback_options,
-                )
-            )
-
-    # run installation
-    code = request.query.get("code", [None])[0]
-    if code is None:
-        return self.failure_handler(
-            FailureArgs(
-                request=request,
-                reason="missing_code",
-                suggested_status_code=401,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    installation = self.run_installation(code)
-    if installation is None:
-        # failed to run installation with the code
-        return self.failure_handler(
-            FailureArgs(
-                request=request,
-                reason="invalid_code",
-                suggested_status_code=401,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    # persist the installation
-    try:
-        self.store_installation(request, installation)
-    except BoltError as err:
-        return self.failure_handler(
-            FailureArgs(
-                request=request,
-                reason="storage_error",
-                error=err,
-                suggested_status_code=500,
-                settings=self.settings,
-                default=self.default_callback_options,
-            )
-        )
-
-    # display a successful completion page to the end-user
-    return self.success_handler(
-        SuccessArgs(
-            request=request,
-            installation=installation,
-            settings=self.settings,
-            default=self.default_callback_options,
-        )
-    )
-
-
-
-
-def handle_installation(self,
request: BoltRequest) ‑> BoltResponse
-
-
-
- -Expand source code - -
def handle_installation(self, request: BoltRequest) -> BoltResponse:
-    set_cookie_value: Optional[str] = None
-    url = self.build_authorize_url("", request)
-    if self.settings.state_validation_enabled is True:
-        state = self.issue_new_state(request)
-        url = self.build_authorize_url(state, request)
-        set_cookie_value = self.settings.state_utils.build_set_cookie_for_new_state(state)
-
-    if self.settings.install_page_rendering_enabled:
-        html = self.build_install_page_html(url, request)
-        return BoltResponse(
-            status=200,
-            body=html,
-            headers=self.append_set_cookie_headers(
-                {"Content-Type": "text/html; charset=utf-8"},
-                set_cookie_value,
-            ),
-        )
-    else:
-        return BoltResponse(
-            status=302,
-            body="",
-            headers=self.append_set_cookie_headers(
-                {"Content-Type": "text/html; charset=utf-8", "Location": url},
-                set_cookie_value,
-            ),
-        )
-
-
-
-
-def issue_new_state(self,
request: BoltRequest) ‑> str
-
-
-
- -Expand source code - -
def issue_new_state(self, request: BoltRequest) -> str:
-    return self.settings.state_store.issue()
-
-
-
-
-def run_installation(self, code: str) ‑> slack_sdk.oauth.installation_store.models.installation.Installation | None -
-
-
- -Expand source code - -
def run_installation(self, code: str) -> Optional[Installation]:
-    try:
-        oauth_response: SlackResponse = self.client.oauth_v2_access(
-            code=code,
-            client_id=self.settings.client_id,
-            client_secret=self.settings.client_secret,
-            redirect_uri=self.settings.redirect_uri,  # can be None
-        )
-        installed_enterprise: Dict[str, str] = oauth_response.get("enterprise") or {}
-        is_enterprise_install: bool = oauth_response.get("is_enterprise_install") or False
-        installed_team: Dict[str, str] = oauth_response.get("team") or {}
-        installer: Dict[str, str] = oauth_response.get("authed_user") or {}
-        incoming_webhook: Dict[str, str] = oauth_response.get("incoming_webhook") or {}
-
-        bot_token: Optional[str] = oauth_response.get("access_token")
-        # NOTE: oauth.v2.access doesn't include bot_id in response
-        bot_id: Optional[str] = None
-        enterprise_url: Optional[str] = None
-        if bot_token is not None:
-            auth_test = self.client.auth_test(token=bot_token)
-            bot_id = auth_test["bot_id"]
-            if is_enterprise_install is True:
-                enterprise_url = auth_test.get("url")
-
-        return Installation(
-            app_id=oauth_response.get("app_id"),
-            enterprise_id=installed_enterprise.get("id"),
-            enterprise_name=installed_enterprise.get("name"),
-            enterprise_url=enterprise_url,
-            team_id=installed_team.get("id"),
-            team_name=installed_team.get("name"),
-            bot_token=bot_token,
-            bot_id=bot_id,
-            bot_user_id=oauth_response.get("bot_user_id"),
-            bot_scopes=oauth_response.get("scope"),  # type: ignore[arg-type] # comma-separated string
-            bot_refresh_token=oauth_response.get("refresh_token"),  # since v1.7
-            bot_token_expires_in=oauth_response.get("expires_in"),  # since v1.7
-            user_id=installer.get("id"),  # type: ignore[arg-type]
-            user_token=installer.get("access_token"),
-            user_scopes=installer.get("scope"),  # type: ignore[arg-type] # comma-separated string
-            user_refresh_token=installer.get("refresh_token"),  # since v1.7
-            user_token_expires_in=installer.get("expires_in"),  # type: ignore[arg-type] # since v1.7
-            incoming_webhook_url=incoming_webhook.get("url"),
-            incoming_webhook_channel=incoming_webhook.get("channel"),
-            incoming_webhook_channel_id=incoming_webhook.get("channel_id"),
-            incoming_webhook_configuration_url=incoming_webhook.get("configuration_url"),
-            is_enterprise_install=is_enterprise_install,
-            token_type=oauth_response.get("token_type"),
-        )
-
-    except SlackApiError as e:
-        message = f"Failed to fetch oauth.v2.access result with code: {code} - error: {e}"
-        self.logger.warning(message)
-        return None
-
-
-
-
-def store_installation(self,
request: BoltRequest,
installation: slack_sdk.oauth.installation_store.models.installation.Installation)
-
-
-
- -Expand source code - -
def store_installation(self, request: BoltRequest, installation: Installation):
-    # may raise BoltError
-    self.settings.installation_store.save(installation)
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/oauth/oauth_settings.html b/docs/reference/oauth/oauth_settings.html deleted file mode 100644 index cd8def497..000000000 --- a/docs/reference/oauth/oauth_settings.html +++ /dev/null @@ -1,421 +0,0 @@ - - - - - - -slack_bolt.oauth.oauth_settings API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.oauth.oauth_settings

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class OAuthSettings -(*,
client_id: str | None = None,
client_secret: str | None = None,
scopes: Sequence[str] | str | None = None,
user_scopes: Sequence[str] | str | None = None,
redirect_uri: str | None = None,
install_path: str = '/slack/install',
install_page_rendering_enabled: bool = True,
redirect_uri_path: str = '/slack/oauth_redirect',
callback_options: CallbackOptions | None = None,
success_url: str | None = None,
failure_url: str | None = None,
authorization_url: str | None = None,
installation_store: slack_sdk.oauth.installation_store.installation_store.InstallationStore | None = None,
installation_store_bot_only: bool = False,
token_rotation_expiration_minutes: int = 120,
user_token_resolution: str = 'authed_user',
state_validation_enabled: bool = True,
state_store: slack_sdk.oauth.state_store.state_store.OAuthStateStore | None = None,
state_cookie_name: str = 'slack-app-oauth-state',
state_expiration_seconds: int = 600,
logger: logging.Logger = <Logger slack_bolt.oauth.oauth_settings (WARNING)>)
-
-
-
- -Expand source code - -
class OAuthSettings:
-    # OAuth flow parameters/credentials
-    client_id: str
-    client_secret: str
-    scopes: Optional[Sequence[str]]
-    user_scopes: Optional[Sequence[str]]
-    redirect_uri: Optional[str]
-    # Handler configuration
-    install_path: str
-    install_page_rendering_enabled: bool
-    redirect_uri_path: str
-    callback_options: Optional[CallbackOptions] = None
-    success_url: Optional[str]
-    failure_url: Optional[str]
-    authorization_url: str  # default: https://slack.com/oauth/v2/authorize
-    # Installation Management
-    installation_store: InstallationStore
-    installation_store_bot_only: bool
-    token_rotation_expiration_minutes: int
-    authorize: Authorize
-    user_token_resolution: str  # default: "authed_user"
-    # state parameter related configurations
-    state_validation_enabled: bool
-    state_store: OAuthStateStore
-    state_cookie_name: str
-    state_expiration_seconds: int
-    # Customizable utilities
-    state_utils: OAuthStateUtils
-    authorize_url_generator: AuthorizeUrlGenerator
-    redirect_uri_page_renderer: RedirectUriPageRenderer
-    # Others
-    logger: Logger
-
-    def __init__(
-        self,
-        *,
-        # OAuth flow parameters/credentials
-        client_id: Optional[str] = None,  # required
-        client_secret: Optional[str] = None,  # required
-        scopes: Optional[Union[Sequence[str], str]] = None,
-        user_scopes: Optional[Union[Sequence[str], str]] = None,
-        redirect_uri: Optional[str] = None,
-        # Handler configuration
-        install_path: str = "/slack/install",
-        install_page_rendering_enabled: bool = True,
-        redirect_uri_path: str = "/slack/oauth_redirect",
-        callback_options: Optional[CallbackOptions] = None,
-        success_url: Optional[str] = None,
-        failure_url: Optional[str] = None,
-        authorization_url: Optional[str] = None,
-        # Installation Management
-        installation_store: Optional[InstallationStore] = None,
-        installation_store_bot_only: bool = False,
-        token_rotation_expiration_minutes: int = 120,
-        user_token_resolution: str = "authed_user",
-        # state parameter related configurations
-        state_validation_enabled: bool = True,
-        state_store: Optional[OAuthStateStore] = None,
-        state_cookie_name: str = OAuthStateUtils.default_cookie_name,
-        state_expiration_seconds: int = OAuthStateUtils.default_expiration_seconds,
-        # Others
-        logger: Logger = logging.getLogger(__name__),
-    ):
-        """The settings for Slack App installation (OAuth flow).
-
-        Args:
-            client_id: Check the value in Settings > Basic Information > App Credentials
-            client_secret: Check the value in Settings > Basic Information > App Credentials
-            scopes: Check the value in Settings > Manage Distribution
-            user_scopes: Check the value in Settings > Manage Distribution
-            redirect_uri: Check the value in Features > OAuth & Permissions > Redirect URLs
-            install_path: The endpoint to start an OAuth flow (Default: `/slack/install`)
-            install_page_rendering_enabled: Renders a web page for install_path access if True
-            redirect_uri_path: The path of Redirect URL (Default: `/slack/oauth_redirect`)
-            callback_options: Give success/failure functions f you want to customize callback functions.
-            success_url: Set a complete URL if you want to redirect end-users when an installation completes.
-            failure_url: Set a complete URL if you want to redirect end-users when an installation fails.
-            authorization_url: Set a URL if you want to customize the URL `https://slack.com/oauth/v2/authorize`
-            installation_store: Specify the instance of `InstallationStore` (Default: `FileInstallationStore`)
-            installation_store_bot_only: Use `InstallationStore#find_bot()` if True (Default: False)
-            token_rotation_expiration_minutes: Minutes before refreshing tokens (Default: 2 hours)
-            user_token_resolution: The option to pick up a user token per request (Default: authed_user)
-                The available values are "authed_user" and "actor". When you want to resolve the user token per request
-                using the event's actor IDs, you can set "actor" instead. With this option, bolt-python tries to resolve
-                a user token for context.actor_enterprise/team/user_id. This can be useful for events in Slack Connect
-                channels. Note that actor IDs can be absent in some scenarios.
-            state_validation_enabled: Set False if your OAuth flow omits the state parameter validation (Default: True)
-            state_store: Specify the instance of `InstallationStore` (Default: `FileOAuthStateStore`)
-            state_cookie_name: The cookie name that is set for installers' browser. (Default: "slack-app-oauth-state")
-            state_expiration_seconds: The seconds that the state value is alive (Default: 600 seconds)
-            logger: The logger that will be used internally
-        """
-        client_id = client_id or os.environ.get("SLACK_CLIENT_ID")
-        client_secret = client_secret or os.environ.get("SLACK_CLIENT_SECRET")
-        if client_id is None or client_secret is None:
-            raise BoltError("Both client_id and client_secret are required")
-        self.client_id = client_id
-        self.client_secret = client_secret
-
-        self.scopes = scopes if scopes is not None else os.environ.get("SLACK_SCOPES", "").split(",")
-        if isinstance(self.scopes, str):
-            self.scopes = self.scopes.split(",")
-        self.user_scopes = user_scopes if user_scopes is not None else os.environ.get("SLACK_USER_SCOPES", "").split(",")
-        if isinstance(self.user_scopes, str):
-            self.user_scopes = self.user_scopes.split(",")
-        self.redirect_uri = redirect_uri or os.environ.get("SLACK_REDIRECT_URI")
-        # Handler configuration
-        self.install_path = install_path or os.environ.get("SLACK_INSTALL_PATH", "/slack/install")
-        self.install_page_rendering_enabled = install_page_rendering_enabled
-        self.redirect_uri_path = redirect_uri_path or os.environ.get("SLACK_REDIRECT_URI_PATH", "/slack/oauth_redirect")
-        self.callback_options = callback_options
-        self.success_url = success_url
-        self.failure_url = failure_url
-        self.authorization_url = authorization_url or "https://slack.com/oauth/v2/authorize"
-        # Installation Management
-        self.installation_store = installation_store or get_or_create_default_installation_store(client_id)
-        self.user_token_resolution = user_token_resolution or "authed_user"
-        self.installation_store_bot_only = installation_store_bot_only
-        self.token_rotation_expiration_minutes = token_rotation_expiration_minutes
-        self.authorize = InstallationStoreAuthorize(
-            logger=logger,
-            client_id=self.client_id,
-            client_secret=self.client_secret,
-            token_rotation_expiration_minutes=self.token_rotation_expiration_minutes,
-            installation_store=self.installation_store,
-            bot_only=self.installation_store_bot_only,
-            user_token_resolution=user_token_resolution,
-        )
-        # state parameter related configurations
-        self.state_validation_enabled = state_validation_enabled
-        self.state_store = state_store or FileOAuthStateStore(
-            expiration_seconds=state_expiration_seconds,
-            client_id=client_id,
-        )
-        self.state_cookie_name = state_cookie_name
-        self.state_expiration_seconds = state_expiration_seconds
-
-        self.state_utils = OAuthStateUtils(
-            cookie_name=self.state_cookie_name,
-            expiration_seconds=self.state_expiration_seconds,
-        )
-        self.authorize_url_generator = AuthorizeUrlGenerator(
-            client_id=self.client_id,
-            redirect_uri=self.redirect_uri,
-            scopes=self.scopes,
-            user_scopes=self.user_scopes,
-            authorization_url=self.authorization_url,
-        )
-        self.redirect_uri_page_renderer = RedirectUriPageRenderer(
-            install_path=self.install_path,
-            redirect_uri_path=self.redirect_uri_path,
-            success_url=self.success_url,
-            failure_url=self.failure_url,
-        )
-
-

The settings for Slack App installation (OAuth flow).

-

Args

-
-
client_id
-
Check the value in Settings > Basic Information > App Credentials
-
client_secret
-
Check the value in Settings > Basic Information > App Credentials
-
scopes
-
Check the value in Settings > Manage Distribution
-
user_scopes
-
Check the value in Settings > Manage Distribution
-
redirect_uri
-
Check the value in Features > OAuth & Permissions > Redirect URLs
-
install_path
-
The endpoint to start an OAuth flow (Default: /slack/install)
-
install_page_rendering_enabled
-
Renders a web page for install_path access if True
-
redirect_uri_path
-
The path of Redirect URL (Default: /slack/oauth_redirect)
-
callback_options
-
Give success/failure functions f you want to customize callback functions.
-
success_url
-
Set a complete URL if you want to redirect end-users when an installation completes.
-
failure_url
-
Set a complete URL if you want to redirect end-users when an installation fails.
-
authorization_url
-
Set a URL if you want to customize the URL https://slack.com/oauth/v2/authorize
-
installation_store
-
Specify the instance of InstallationStore (Default: FileInstallationStore)
-
installation_store_bot_only
-
Use InstallationStore#find_bot() if True (Default: False)
-
token_rotation_expiration_minutes
-
Minutes before refreshing tokens (Default: 2 hours)
-
user_token_resolution
-
The option to pick up a user token per request (Default: authed_user) -The available values are "authed_user" and "actor". When you want to resolve the user token per request -using the event's actor IDs, you can set "actor" instead. With this option, bolt-python tries to resolve -a user token for context.actor_enterprise/team/user_id. This can be useful for events in Slack Connect -channels. Note that actor IDs can be absent in some scenarios.
-
state_validation_enabled
-
Set False if your OAuth flow omits the state parameter validation (Default: True)
-
state_store
-
Specify the instance of InstallationStore (Default: FileOAuthStateStore)
-
state_cookie_name
-
The cookie name that is set for installers' browser. (Default: "slack-app-oauth-state")
-
state_expiration_seconds
-
The seconds that the state value is alive (Default: 600 seconds)
-
logger
-
The logger that will be used internally
-
-

Class variables

-
-
var authorization_url : str
-
-

The type of the None singleton.

-
-
var authorizeAuthorize
-
-

The type of the None singleton.

-
-
var authorize_url_generator : slack_sdk.oauth.authorize_url_generator.AuthorizeUrlGenerator
-
-

The type of the None singleton.

-
-
var callback_optionsCallbackOptions | None
-
-

The type of the None singleton.

-
-
var client_id : str
-
-

The type of the None singleton.

-
-
var client_secret : str
-
-

The type of the None singleton.

-
-
var failure_url : str | None
-
-

The type of the None singleton.

-
-
var install_page_rendering_enabled : bool
-
-

The type of the None singleton.

-
-
var install_path : str
-
-

The type of the None singleton.

-
-
var installation_store : slack_sdk.oauth.installation_store.installation_store.InstallationStore
-
-

The type of the None singleton.

-
-
var installation_store_bot_only : bool
-
-

The type of the None singleton.

-
-
var logger : logging.Logger
-
-

The type of the None singleton.

-
-
var redirect_uri : str | None
-
-

The type of the None singleton.

-
-
var redirect_uri_page_renderer : slack_sdk.oauth.redirect_uri_page_renderer.RedirectUriPageRenderer
-
-

The type of the None singleton.

-
-
var redirect_uri_path : str
-
-

The type of the None singleton.

-
-
var scopes : Sequence[str] | None
-
-

The type of the None singleton.

-
- -
-

The type of the None singleton.

-
-
var state_expiration_seconds : int
-
-

The type of the None singleton.

-
-
var state_store : slack_sdk.oauth.state_store.state_store.OAuthStateStore
-
-

The type of the None singleton.

-
-
var state_utils : slack_sdk.oauth.state_utils.OAuthStateUtils
-
-

The type of the None singleton.

-
-
var state_validation_enabled : bool
-
-

The type of the None singleton.

-
-
var success_url : str | None
-
-

The type of the None singleton.

-
-
var token_rotation_expiration_minutes : int
-
-

The type of the None singleton.

-
-
var user_scopes : Sequence[str] | None
-
-

The type of the None singleton.

-
-
var user_token_resolution : str
-
-

The type of the None singleton.

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/request/async_internals.html b/docs/reference/request/async_internals.html deleted file mode 100644 index 35a250c8d..000000000 --- a/docs/reference/request/async_internals.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - -slack_bolt.request.async_internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.request.async_internals

-
-
-
-
-
-
-
-
-

Functions

-
-
-def build_async_context(context: AsyncBoltContext,
body: Dict[str, Any]) ‑> AsyncBoltContext
-
-
-
- -Expand source code - -
def build_async_context(
-    context: AsyncBoltContext,
-    body: Dict[str, Any],
-) -> AsyncBoltContext:
-    context["is_enterprise_install"] = extract_is_enterprise_install(body)
-    enterprise_id = extract_enterprise_id(body)
-    if enterprise_id:
-        context["enterprise_id"] = enterprise_id
-    team_id = extract_team_id(body)
-    if team_id:
-        context["team_id"] = team_id
-    user_id = extract_user_id(body)
-    if user_id:
-        context["user_id"] = user_id
-    # Actor IDs are useful for Events API on a Slack Connect channel
-    actor_enterprise_id = extract_actor_enterprise_id(body)
-    if actor_enterprise_id:
-        context["actor_enterprise_id"] = actor_enterprise_id
-    actor_team_id = extract_actor_team_id(body)
-    if actor_team_id:
-        context["actor_team_id"] = actor_team_id
-    actor_user_id = extract_actor_user_id(body)
-    if actor_user_id:
-        context["actor_user_id"] = actor_user_id
-    channel_id = extract_channel_id(body)
-    if channel_id:
-        context["channel_id"] = channel_id
-    thread_ts = extract_thread_ts(body)
-    if thread_ts:
-        context["thread_ts"] = thread_ts
-    function_execution_id = extract_function_execution_id(body)
-    if function_execution_id:
-        context["function_execution_id"] = function_execution_id
-        function_bot_access_token = extract_function_bot_access_token(body)
-        if function_bot_access_token is not None:
-            context["function_bot_access_token"] = function_bot_access_token
-        function_inputs = extract_function_inputs(body)
-        if function_inputs is not None:
-            context["inputs"] = function_inputs
-    if "response_url" in body:
-        context["response_url"] = body["response_url"]
-    elif "response_urls" in body:
-        # In the case where response_url_enabled: true in a modal exists
-        response_urls = body["response_urls"]
-        if len(response_urls) >= 1:
-            if len(response_urls) > 1:
-                context.logger.debug(debug_multiple_response_urls_detected())
-            response_url = response_urls[0].get("response_url")
-            context["response_url"] = response_url
-    return context
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/request/async_request.html b/docs/reference/request/async_request.html deleted file mode 100644 index a3658710a..000000000 --- a/docs/reference/request/async_request.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - -slack_bolt.request.async_request API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.request.async_request

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncBoltRequest -(*,
body: str | dict,
query: str | Dict[str, str] | Dict[str, Sequence[str]] | None = None,
headers: Dict[str, str | Sequence[str]] | None = None,
context: Dict[str, Any] | None = None,
mode: str = 'http')
-
-
-
- -Expand source code - -
class AsyncBoltRequest:
-    raw_body: str
-    body: Dict[str, Any]
-    query: Dict[str, Sequence[str]]
-    headers: Dict[str, Sequence[str]]
-    content_type: Optional[str]
-    context: AsyncBoltContext
-    lazy_only: bool
-    lazy_function_name: Optional[str]
-    mode: str  # either "http" or "socket_mode"
-
-    def __init__(
-        self,
-        *,
-        body: Union[str, dict],
-        query: Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]] = None,
-        headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None,
-        context: Optional[Dict[str, Any]] = None,
-        mode: str = "http",  # either "http" or "socket_mode"
-    ):
-        """Request to a Bolt app.
-
-        Args:
-            body: The raw request body (only plain text is supported for "http" mode)
-            query: The query string data in any data format.
-            headers: The request headers.
-            context: The context in this request.
-            mode: The mode used for this request. (either "http" or "socket_mode")
-        """
-
-        if mode == "http":
-            # HTTP Mode
-            if body is not None and not isinstance(body, str):
-                raise BoltError(error_message_raw_body_required_in_http_mode())
-            self.raw_body = body if body is not None else ""
-        else:
-            # Socket Mode
-            if body is not None and isinstance(body, str):
-                self.raw_body = body
-            else:
-                # We don't convert the dict value to str
-                # as doing so does not guarantee to keep the original structure/format.
-                self.raw_body = ""
-
-        self.query = parse_query(query)
-        self.headers = build_normalized_headers(headers)
-        self.content_type = extract_content_type(self.headers)
-
-        if isinstance(body, str):
-            self.body = parse_body(self.raw_body, self.content_type)
-        elif isinstance(body, dict):
-            self.body = body
-        else:
-            self.body = {}
-
-        self.context = build_async_context(AsyncBoltContext(context if context else {}), self.body)
-        self.lazy_only = bool(self.headers.get("x-slack-bolt-lazy-only", [False])[0])
-        self.lazy_function_name = self.headers.get("x-slack-bolt-lazy-function-name", [None])[0]
-        self.mode = mode
-
-    def to_copyable(self) -> "AsyncBoltRequest":
-        body: Union[str, dict] = self.raw_body if self.mode == "http" else self.body
-        return AsyncBoltRequest(
-            body=body,
-            query=self.query,
-            headers=self.headers,
-            context=self.context.to_copyable(),
-            mode=self.mode,
-        )
-
-

Request to a Bolt app.

-

Args

-
-
body
-
The raw request body (only plain text is supported for "http" mode)
-
query
-
The query string data in any data format.
-
headers
-
The request headers.
-
context
-
The context in this request.
-
mode
-
The mode used for this request. (either "http" or "socket_mode")
-
-

Class variables

-
-
var body : Dict[str, Any]
-
-

The type of the None singleton.

-
-
var content_type : str | None
-
-

The type of the None singleton.

-
-
var contextAsyncBoltContext
-
-

The type of the None singleton.

-
-
var headers : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var lazy_function_name : str | None
-
-

The type of the None singleton.

-
-
var lazy_only : bool
-
-

The type of the None singleton.

-
-
var mode : str
-
-

The type of the None singleton.

-
-
var query : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var raw_body : str
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def to_copyable(self) ‑> AsyncBoltRequest -
-
-
- -Expand source code - -
def to_copyable(self) -> "AsyncBoltRequest":
-    body: Union[str, dict] = self.raw_body if self.mode == "http" else self.body
-    return AsyncBoltRequest(
-        body=body,
-        query=self.query,
-        headers=self.headers,
-        context=self.context.to_copyable(),
-        mode=self.mode,
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/request/index.html b/docs/reference/request/index.html deleted file mode 100644 index 84cd15050..000000000 --- a/docs/reference/request/index.html +++ /dev/null @@ -1,278 +0,0 @@ - - - - - - -slack_bolt.request API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.request

-
-
-

Incoming request from Slack through either HTTP request or Socket Mode connection.

-

Refer to https://docs.slack.dev/apis/events-api/ for the two types of connections. -This interface encapsulates the difference between the two.

-
-
-

Sub-modules

-
-
slack_bolt.request.async_internals
-
-
-
-
slack_bolt.request.async_request
-
-
-
-
slack_bolt.request.internals
-
-
-
-
slack_bolt.request.payload_utils
-
-
-
-
slack_bolt.request.request
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class BoltRequest -(*,
body: str | dict,
query: str | Dict[str, str] | Dict[str, Sequence[str]] | None = None,
headers: Dict[str, str | Sequence[str]] | None = None,
context: Dict[str, Any] | None = None,
mode: str = 'http')
-
-
-
- -Expand source code - -
class BoltRequest:
-    raw_body: str
-    query: Dict[str, Sequence[str]]
-    headers: Dict[str, Sequence[str]]
-    content_type: Optional[str]
-    body: Dict[str, Any]
-    context: BoltContext
-    lazy_only: bool
-    lazy_function_name: Optional[str]
-    mode: str  # either "http" or "socket_mode"
-
-    def __init__(
-        self,
-        *,
-        body: Union[str, dict],
-        query: Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]] = None,
-        headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None,
-        context: Optional[Dict[str, Any]] = None,
-        mode: str = "http",  # either "http" or "socket_mode"
-    ):
-        """Request to a Bolt app.
-
-        Args:
-            body: The raw request body (only plain text is supported for "http" mode)
-            query: The query string data in any data format.
-            headers: The request headers.
-            context: The context in this request.
-            mode: The mode used for this request. (either "http" or "socket_mode")
-        """
-        if mode == "http":
-            # HTTP Mode
-            if body is not None and not isinstance(body, str):
-                raise BoltError(error_message_raw_body_required_in_http_mode())
-            self.raw_body = body if body is not None else ""
-        else:
-            # Socket Mode
-            if body is not None and isinstance(body, str):
-                self.raw_body = body
-            else:
-                # We don't convert the dict value to str
-                # as doing so does not guarantee to keep the original structure/format.
-                self.raw_body = ""
-
-        self.query = parse_query(query)
-        self.headers = build_normalized_headers(headers)
-        self.content_type = extract_content_type(self.headers)
-
-        if isinstance(body, str):
-            self.body = parse_body(self.raw_body, self.content_type)
-        elif isinstance(body, dict):
-            self.body = body
-        else:
-            self.body = {}
-
-        self.context = build_context(BoltContext(context if context else {}), self.body)
-        self.lazy_only = bool(self.headers.get("x-slack-bolt-lazy-only", [False])[0])
-        self.lazy_function_name = self.headers.get("x-slack-bolt-lazy-function-name", [None])[0]
-        self.mode = mode
-
-    def to_copyable(self) -> "BoltRequest":
-        body: Union[str, dict] = self.raw_body if self.mode == "http" else self.body
-        return BoltRequest(
-            body=body,
-            query=self.query,
-            headers=self.headers,
-            context=self.context.to_copyable(),
-            mode=self.mode,
-        )
-
-

Request to a Bolt app.

-

Args

-
-
body
-
The raw request body (only plain text is supported for "http" mode)
-
query
-
The query string data in any data format.
-
headers
-
The request headers.
-
context
-
The context in this request.
-
mode
-
The mode used for this request. (either "http" or "socket_mode")
-
-

Class variables

-
-
var body : Dict[str, Any]
-
-

The type of the None singleton.

-
-
var content_type : str | None
-
-

The type of the None singleton.

-
-
var contextBoltContext
-
-

The type of the None singleton.

-
-
var headers : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var lazy_function_name : str | None
-
-

The type of the None singleton.

-
-
var lazy_only : bool
-
-

The type of the None singleton.

-
-
var mode : str
-
-

The type of the None singleton.

-
-
var query : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var raw_body : str
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def to_copyable(self) ‑> BoltRequest -
-
-
- -Expand source code - -
def to_copyable(self) -> "BoltRequest":
-    body: Union[str, dict] = self.raw_body if self.mode == "http" else self.body
-    return BoltRequest(
-        body=body,
-        query=self.query,
-        headers=self.headers,
-        context=self.context.to_copyable(),
-        mode=self.mode,
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/request/internals.html b/docs/reference/request/internals.html deleted file mode 100644 index d25880135..000000000 --- a/docs/reference/request/internals.html +++ /dev/null @@ -1,594 +0,0 @@ - - - - - - -slack_bolt.request.internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.request.internals

-
-
-
-
-
-
-
-
-

Functions

-
-
-def build_context(context: BoltContext,
body: Dict[str, Any]) ‑> BoltContext
-
-
-
- -Expand source code - -
def build_context(context: BoltContext, body: Dict[str, Any]) -> BoltContext:
-    context["is_enterprise_install"] = extract_is_enterprise_install(body)
-    enterprise_id = extract_enterprise_id(body)
-    if enterprise_id:
-        context["enterprise_id"] = enterprise_id
-    team_id = extract_team_id(body)
-    if team_id:
-        context["team_id"] = team_id
-    user_id = extract_user_id(body)
-    if user_id:
-        context["user_id"] = user_id
-    # Actor IDs are useful for Events API on a Slack Connect channel
-    actor_enterprise_id = extract_actor_enterprise_id(body)
-    if actor_enterprise_id:
-        context["actor_enterprise_id"] = actor_enterprise_id
-    actor_team_id = extract_actor_team_id(body)
-    if actor_team_id:
-        context["actor_team_id"] = actor_team_id
-    actor_user_id = extract_actor_user_id(body)
-    if actor_user_id:
-        context["actor_user_id"] = actor_user_id
-    channel_id = extract_channel_id(body)
-    if channel_id:
-        context["channel_id"] = channel_id
-    thread_ts = extract_thread_ts(body)
-    if thread_ts:
-        context["thread_ts"] = thread_ts
-    function_execution_id = extract_function_execution_id(body)
-    if function_execution_id is not None:
-        context["function_execution_id"] = function_execution_id
-        function_bot_access_token = extract_function_bot_access_token(body)
-        if function_bot_access_token is not None:
-            context["function_bot_access_token"] = function_bot_access_token
-        inputs = extract_function_inputs(body)
-        if inputs is not None:
-            context["inputs"] = inputs
-    if "response_url" in body:
-        context["response_url"] = body["response_url"]
-    elif "response_urls" in body:
-        # In the case where response_url_enabled: true in a modal exists
-        response_urls = body["response_urls"]
-        if len(response_urls) >= 1:
-            if len(response_urls) > 1:
-                context.logger.debug(debug_multiple_response_urls_detected())
-            response_url = response_urls[0].get("response_url")
-            context["response_url"] = response_url
-    return context
-
-
-
-
-def build_normalized_headers(headers: Dict[str, str | Sequence[str]] | None) ‑> Dict[str, Sequence[str]] -
-
-
- -Expand source code - -
def build_normalized_headers(headers: Optional[Dict[str, Union[str, Sequence[str]]]]) -> Dict[str, Sequence[str]]:
-    normalized_headers: Dict[str, Sequence[str]] = {}
-    if headers is not None:
-        for key, value in headers.items():
-            normalized_name = key.lower()
-            if isinstance(value, list):
-                normalized_headers[normalized_name] = value
-            elif isinstance(value, str):
-                normalized_headers[normalized_name] = [value]
-            else:
-                raise ValueError(f"Unsupported type ({type(value)}) of element in headers ({headers})")
-    return normalized_headers
-
-
-
-
-def debug_multiple_response_urls_detected() ‑> str -
-
-
- -Expand source code - -
def debug_multiple_response_urls_detected() -> str:
-    return (
-        "`response_urls` in the body has multiple URLs in it. "
-        "If you would like to use non-primary one, "
-        "please manually extract the one from body['response_urls']."
-    )
-
-
-
-
-def error_message_raw_body_required_in_http_mode() ‑> str -
-
-
- -Expand source code - -
def error_message_raw_body_required_in_http_mode() -> str:
-    return "`body` must be a raw string data when running in the HTTP server mode"
-
-
-
-
-def extract_actor_enterprise_id(payload: Dict[str, Any]) ‑> str | None -
-
-
- -Expand source code - -
def extract_actor_enterprise_id(payload: Dict[str, Any]) -> Optional[str]:
-    if payload.get("is_ext_shared_channel") is True:
-        if payload.get("type") == "event_callback":
-            # For safety, we don't set actor IDs for the events like "file_shared",
-            # which do not provide any team ID in $.event data. In the case, the IDs cannot be correct.
-            event_team_id = payload.get("event", {}).get("user_team") or payload.get("event", {}).get("team")
-            if event_team_id is not None and str(event_team_id).startswith("E"):
-                return event_team_id
-            if event_team_id == payload.get("team_id"):
-                return payload.get("enterprise_id")
-            return None
-    return extract_enterprise_id(payload)
-
-
-
-
-def extract_actor_team_id(payload: Dict[str, Any]) ‑> str | None -
-
-
- -Expand source code - -
def extract_actor_team_id(payload: Dict[str, Any]) -> Optional[str]:
-    if payload.get("is_ext_shared_channel") is True:
-        if payload.get("type") == "event_callback":
-            event_type = payload.get("event", {}).get("type")
-            if event_type == "app_mention":
-                # The $.event.user_team can be an enterprise_id in app_mention events.
-                # In the scenario, there is no way to retrieve actor_team_id as of March 2023
-                user_team = payload.get("event", {}).get("user_team")
-                if user_team is None:
-                    # working with an app installed in this user's org/workspace side
-                    return payload.get("event", {}).get("team")
-                if str(user_team).startswith("T"):
-                    # interacting from a connected non-grid workspace
-                    return user_team
-                # Interacting from a connected grid workspace; in this case, team_id cannot be resolved as of March 2023
-                return None
-            # For safety, we don't set actor IDs for the events like "file_shared",
-            # which do not provide any team ID in $.event data. In the case, the IDs cannot be correct.
-            event_user_team = payload.get("event", {}).get("user_team")
-            if event_user_team is not None:
-                if str(event_user_team).startswith("T"):
-                    return event_user_team
-                elif str(event_user_team).startswith("E"):
-                    if event_user_team == payload.get("enterprise_id"):
-                        return payload.get("team_id")
-                    elif event_user_team == payload.get("context_enterprise_id"):
-                        return payload.get("context_team_id")
-
-            event_team = payload.get("event", {}).get("team")
-            if event_team is not None:
-                if str(event_team).startswith("T"):
-                    return event_team
-                elif str(event_team).startswith("E"):
-                    if event_team == payload.get("enterprise_id"):
-                        return payload.get("team_id")
-                    elif event_team == payload.get("context_enterprise_id"):
-                        return payload.get("context_team_id")
-            return None
-
-    return extract_team_id(payload)
-
-
-
-
-def extract_actor_user_id(payload: Dict[str, Any]) ‑> str | None -
-
-
- -Expand source code - -
def extract_actor_user_id(payload: Dict[str, Any]) -> Optional[str]:
-    if payload.get("is_ext_shared_channel") is True:
-        if payload.get("type") == "event_callback":
-            event = payload.get("event")
-            if event is None:
-                return None
-            if extract_actor_enterprise_id(payload) is None and extract_actor_team_id(payload) is None:
-                # When both enterprise_id and team_id are not identified, we skip returning user_id too for safety
-                return None
-            return event.get("user") or event.get("user_id")
-    return extract_user_id(payload)
-
-
-
-
-def extract_channel_id(payload: Dict[str, Any]) ‑> str | None -
-
-
- -Expand source code - -
def extract_channel_id(payload: Dict[str, Any]) -> Optional[str]:
-    channel = payload.get("channel")
-    if channel is not None:
-        if isinstance(channel, str):
-            return channel
-        elif "id" in channel:
-            return channel.get("id")
-    if "channel_id" in payload:
-        return payload.get("channel_id")
-    if isinstance(payload.get("event"), dict):
-        return extract_channel_id(payload["event"])
-    if isinstance(payload.get("item"), dict):
-        # reaction_added: body["event"]["item"]
-        return extract_channel_id(payload["item"])
-    if isinstance(payload.get("assistant_thread"), dict):
-        # assistant_thread_started
-        return extract_channel_id(payload["assistant_thread"])
-    return None
-
-
-
-
-def extract_content_type(headers: Dict[str, Sequence[str]]) ‑> str | None -
-
-
- -Expand source code - -
def extract_content_type(headers: Dict[str, Sequence[str]]) -> Optional[str]:
-    content_type: Optional[str] = headers.get("content-type", [None])[0]
-    if content_type:
-        return content_type.split(";")[0]
-    return None
-
-
-
-
-def extract_enterprise_id(payload: Dict[str, Any]) ‑> str | None -
-
-
- -Expand source code - -
def extract_enterprise_id(payload: Dict[str, Any]) -> Optional[str]:
-    org = payload.get("enterprise")
-    if org is not None:
-        if isinstance(org, str):
-            return org
-        elif "id" in org:
-            return org.get("id")
-    if payload.get("authorizations") is not None and len(payload["authorizations"]) > 0:
-        # To make Events API handling functioning also for shared channels,
-        # we should use .authorizations[0].enterprise_id over .enterprise_id
-        return extract_enterprise_id(payload["authorizations"][0])
-    if "enterprise_id" in payload:
-        return payload.get("enterprise_id")
-    if isinstance(payload.get("team"), dict) and "enterprise_id" in payload["team"]:
-        # In the case where the type is view_submission
-        return payload["team"].get("enterprise_id")
-    if isinstance(payload.get("event"), dict):
-        return extract_enterprise_id(payload["event"])
-    return None
-
-
-
-
-def extract_function_bot_access_token(payload: Dict[str, Any]) ‑> str | None -
-
-
- -Expand source code - -
def extract_function_bot_access_token(payload: Dict[str, Any]) -> Optional[str]:
-    if payload.get("bot_access_token") is not None:
-        return payload.get("bot_access_token")
-    if isinstance(payload.get("event"), dict):
-        return payload["event"].get("bot_access_token")
-    return None
-
-
-
-
-def extract_function_execution_id(payload: Dict[str, Any]) ‑> str | None -
-
-
- -Expand source code - -
def extract_function_execution_id(payload: Dict[str, Any]) -> Optional[str]:
-    if payload.get("function_execution_id") is not None:
-        return payload.get("function_execution_id")
-    if isinstance(payload.get("event"), dict):
-        return extract_function_execution_id(payload["event"])
-    if isinstance(payload.get("function_data"), dict):
-        return payload["function_data"].get("execution_id")
-    return None
-
-
-
-
-def extract_function_inputs(payload: Dict[str, Any]) ‑> Dict[str, Any] | None -
-
-
- -Expand source code - -
def extract_function_inputs(payload: Dict[str, Any]) -> Optional[Dict[str, Any]]:
-    if isinstance(payload.get("event"), dict):
-        return payload["event"].get("inputs")
-    if isinstance(payload.get("function_data"), dict):
-        return payload["function_data"].get("inputs")
-    return None
-
-
-
-
-def extract_is_enterprise_install(payload: Dict[str, Any]) ‑> bool | None -
-
-
- -Expand source code - -
def extract_is_enterprise_install(payload: Dict[str, Any]) -> Optional[bool]:
-    if payload.get("authorizations") is not None and len(payload["authorizations"]) > 0:
-        # To make Events API handling functioning also for shared channels,
-        # we should use .authorizations[0].is_enterprise_install over .is_enterprise_install
-        return extract_is_enterprise_install(payload["authorizations"][0])
-    if "is_enterprise_install" in payload:
-        is_enterprise_install = payload.get("is_enterprise_install")
-        return is_enterprise_install is not None and (is_enterprise_install is True or is_enterprise_install == "true")
-    return False
-
-
-
-
-def extract_team_id(payload: Dict[str, Any]) ‑> str | None -
-
-
- -Expand source code - -
def extract_team_id(payload: Dict[str, Any]) -> Optional[str]:
-    view = payload.get("view")
-    if isinstance(view, dict) and view.get("app_installed_team_id") is not None:
-        # view_submission payloads can have `view.app_installed_team_id` when a modal view that was opened
-        # in a different workspace via some operations inside a Slack Connect channel.
-        # Note that the same for enterprise_id does not exist. When you need to know the enterprise_id as well,
-        # you have to run some query toward your InstallationStore to know the org where the team_id belongs to.
-        return view["app_installed_team_id"]
-    if payload.get("team") is not None:
-        # With org-wide installations, payload.team in interactivity payloads can be None
-        # You need to extract either payload.user.team_id or payload.view.team_id as below
-        team = payload.get("team")
-        if isinstance(team, str):
-            return team
-        elif team and "id" in team:
-            return team.get("id")
-    if payload.get("authorizations") is not None and len(payload["authorizations"]) > 0:
-        # To make Events API handling functioning also for shared channels,
-        # we should use .authorizations[0].team_id over .team_id
-        return extract_team_id(payload["authorizations"][0])
-    if "team_id" in payload:
-        return payload.get("team_id")
-    if isinstance(payload.get("event"), dict):
-        return extract_team_id(payload["event"])
-    if isinstance(payload.get("user"), dict):
-        return payload["user"].get("team_id")
-    if isinstance(payload.get("view"), dict):
-        return payload["view"].get("team_id")
-    return None
-
-
-
-
-def extract_thread_ts(payload: Dict[str, Any]) ‑> str | None -
-
-
- -Expand source code - -
def extract_thread_ts(payload: Dict[str, Any]) -> Optional[str]:
-    thread_ts = payload.get("thread_ts")
-    if thread_ts is not None:
-        return thread_ts
-    if isinstance(payload.get("event"), dict):
-        return extract_thread_ts(payload["event"])
-    if isinstance(payload.get("assistant_thread"), dict):
-        return extract_thread_ts(payload["assistant_thread"])
-    if isinstance(payload.get("message"), dict):
-        return extract_thread_ts(payload["message"])
-    if isinstance(payload.get("previous_message"), dict):
-        return extract_thread_ts(payload["previous_message"])
-    return None
-
-
-
-
-def extract_user_id(payload: Dict[str, Any]) ‑> str | None -
-
-
- -Expand source code - -
def extract_user_id(payload: Dict[str, Any]) -> Optional[str]:
-    user = payload.get("user")
-    if user is not None:
-        if isinstance(user, str):
-            return user
-        elif "id" in user:
-            return user.get("id")
-    if "user_id" in payload:
-        return payload.get("user_id")
-    if isinstance(payload.get("event"), dict):
-        return extract_user_id(payload["event"])
-    if isinstance(payload.get("message"), dict):
-        # message_changed: body["event"]["message"]
-        return extract_user_id(payload["message"])
-    if isinstance(payload.get("previous_message"), dict):
-        # message_deleted: body["event"]["previous_message"]
-        return extract_user_id(payload["previous_message"])
-    return None
-
-
-
-
-def parse_body(body: str, content_type: str | None) ‑> Dict[str, Any] -
-
-
- -Expand source code - -
def parse_body(body: str, content_type: Optional[str]) -> Dict[str, Any]:
-    if not body:
-        return {}
-    if (content_type is not None and content_type == "application/json") or body.startswith("{"):
-        return json.loads(body)
-    else:
-        if "payload" in body:  # This is not JSON format yet
-            params = dict(parse_qsl(body, keep_blank_values=True))
-            payload = params.get("payload")
-            if payload is not None:
-                return json.loads(payload)
-            else:
-                return {}
-        else:
-            return dict(parse_qsl(body, keep_blank_values=True))
-
-
-
-
-def parse_query(query: str | Dict[str, str] | Dict[str, Sequence[str]] | None) ‑> Dict[str, Sequence[str]] -
-
-
- -Expand source code - -
def parse_query(query: Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]]) -> Dict[str, Sequence[str]]:
-    if query is None:
-        return {}
-    elif isinstance(query, str):
-        return dict(parse_qs(query, keep_blank_values=True))
-    elif isinstance(query, dict) or hasattr(query, "items"):
-        result: Dict[str, Sequence[str]] = {}
-        for name, value in query.items():
-            if isinstance(value, list):
-                result[name] = value
-            elif isinstance(value, str):
-                result[name] = [value]
-            else:
-                raise ValueError(f"Unsupported type ({type(value)}) of element in headers ({query})")
-        return result
-    else:
-        raise ValueError(f"Unsupported type of query detected ({type(query)})")
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/request/payload_utils.html b/docs/reference/request/payload_utils.html deleted file mode 100644 index b583c3a51..000000000 --- a/docs/reference/request/payload_utils.html +++ /dev/null @@ -1,669 +0,0 @@ - - - - - - -slack_bolt.request.payload_utils API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.request.payload_utils

-
-
-
-
-
-
-
-
-

Functions

-
-
-def is_action(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_action(body: Dict[str, Any]) -> bool:
-    return (
-        is_attachment_action(body)
-        or is_block_actions(body)
-        or is_dialog_submission(body)
-        or is_dialog_cancellation(body)
-        or is_workflow_step_edit(body)
-    )
-
-
-
-
-def is_any_im_message_event(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_any_im_message_event(body: Dict[str, Any]) -> bool:
-    if is_message_event(body):
-        # Any message event with no subtype or any subtype (message_changed, message_deleted, etc.)
-        return body["event"].get("channel_type") == "im"
-    return False
-
-
-
-
-def is_app_home_opened_event(body: Dict[str, Any], tab: str | None = None) ‑> bool -
-
-
- -Expand source code - -
def is_app_home_opened_event(body: Dict[str, Any], tab: Optional[str] = None) -> bool:
-    if is_event(body) and body["event"]["type"] == "app_home_opened":
-        if tab is not None:
-            return body["event"].get("tab") == tab
-        return True
-    return False
-
-
-
-
-def is_assistant_event(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_assistant_event(body: Dict[str, Any]) -> bool:
-    return is_event(body) and (
-        is_assistant_thread_started_event(body)
-        or is_assistant_thread_context_changed_event(body)
-        or is_user_message_event_in_assistant_thread(body)
-        or is_bot_message_event_in_assistant_thread(body)
-    )
-
-
-
-
-def is_assistant_thread_context_changed_event(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_assistant_thread_context_changed_event(body: Dict[str, Any]) -> bool:
-    if is_event(body):
-        return body["event"]["type"] == "assistant_thread_context_changed"
-    return False
-
-
-
-
-def is_assistant_thread_started_event(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_assistant_thread_started_event(body: Dict[str, Any]) -> bool:
-    if is_event(body):
-        return body["event"]["type"] == "assistant_thread_started"
-    return False
-
-
-
-
-def is_attachment_action(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_attachment_action(body: Dict[str, Any]) -> bool:
-    return body is not None and _is_expected_type(body, "interactive_message") and "callback_id" in body
-
-
-
-
-def is_block_actions(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_block_actions(body: Dict[str, Any]) -> bool:
-    return body is not None and _is_expected_type(body, "block_actions") and "actions" in body
-
-
-
-
-def is_block_suggestion(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_block_suggestion(body: Dict[str, Any]) -> bool:
-    return body is not None and _is_expected_type(body, "block_suggestion") and "action_id" in body
-
-
-
-
-def is_bot_message_event_in_assistant_thread(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_bot_message_event_in_assistant_thread(body: Dict[str, Any]) -> bool:
-    if is_any_im_message_event(body):
-        return (
-            body["event"].get("subtype") is None
-            and body["event"].get("thread_ts") is not None
-            and body["event"].get("bot_id") is not None
-        )
-    return False
-
-
-
-
-def is_dialog_cancellation(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_dialog_cancellation(body: Dict[str, Any]) -> bool:
-    return body is not None and _is_expected_type(body, "dialog_cancellation") and "callback_id" in body
-
-
-
-
-def is_dialog_submission(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_dialog_submission(body: Dict[str, Any]) -> bool:
-    return body is not None and _is_expected_type(body, "dialog_submission") and "callback_id" in body
-
-
-
-
-def is_dialog_suggestion(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_dialog_suggestion(body: Dict[str, Any]) -> bool:
-    return body is not None and _is_expected_type(body, "dialog_suggestion") and "callback_id" in body
-
-
-
-
-def is_event(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_event(body: Dict[str, Any]) -> bool:
-    return body is not None and _is_expected_type(body, "event_callback") and "event" in body and "type" in body["event"]
-
-
-
-
-def is_function(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_function(body: Dict[str, Any]) -> bool:
-    return is_event(body) and "function_executed" == body["event"]["type"] and "function_execution_id" in body["event"]
-
-
-
-
-def is_global_shortcut(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_global_shortcut(body: Dict[str, Any]) -> bool:
-    return body is not None and _is_expected_type(body, "shortcut") and "callback_id" in body
-
-
-
-
-def is_im_message_event(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_im_message_event(body: Dict[str, Any]) -> bool:
-    if is_any_im_message_event(body):
-        return body["event"].get("subtype") in (None, "file_share")
-    return False
-
-
-
-
-def is_message_event(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_message_event(body: Dict[str, Any]) -> bool:
-    if is_event(body):
-        return body["event"]["type"] == "message"
-    return False
-
-
-
-
-def is_message_shortcut(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_message_shortcut(body: Dict[str, Any]) -> bool:
-    return body is not None and _is_expected_type(body, "message_action") and "callback_id" in body
-
-
-
-
-def is_options(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_options(body: Dict[str, Any]) -> bool:
-    return is_block_suggestion(body) or is_dialog_suggestion(body)
-
-
-
-
-def is_other_message_sub_event_in_assistant_thread(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_other_message_sub_event_in_assistant_thread(body: Dict[str, Any]) -> bool:
-    # message_changed, message_deleted etc.
-    if is_any_im_message_event(body):
-        return not is_user_message_event_in_assistant_thread(body) and (
-            _is_other_message_sub_event(body["event"].get("message"))
-            or _is_other_message_sub_event(body["event"].get("previous_message"))
-        )
-    return False
-
-
-
-
-def is_shortcut(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_shortcut(body: Dict[str, Any]) -> bool:
-    return is_global_shortcut(body) or is_message_shortcut(body)
-
-
-
-
-def is_slash_command(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_slash_command(body: Dict[str, Any]) -> bool:
-    return body is not None and "command" in body
-
-
-
-
-def is_user_message_event_in_assistant_thread(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_user_message_event_in_assistant_thread(body: Dict[str, Any]) -> bool:
-    if is_im_message_event(body):
-        return body["event"].get("thread_ts") is not None and body["event"].get("bot_id") is None
-    return False
-
-
-
-
-def is_view(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_view(body: Dict[str, Any]) -> bool:
-    return is_view_submission(body) or is_view_closed(body)
-
-
-
-
-def is_view_closed(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_view_closed(body: Dict[str, Any]) -> bool:
-    return body is not None and _is_expected_type(body, "view_closed") and "view" in body and "callback_id" in body["view"]
-
-
-
-
-def is_view_submission(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_view_submission(body: Dict[str, Any]) -> bool:
-    return (
-        body is not None and _is_expected_type(body, "view_submission") and "view" in body and "callback_id" in body["view"]
-    )
-
-
-
-
-def is_workflow_step_edit(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_workflow_step_edit(body: Dict[str, Any]) -> bool:
-    return body is not None and _is_expected_type(body, "workflow_step_edit") and "callback_id" in body
-
-
-
-
-def is_workflow_step_execute(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_workflow_step_execute(body: Dict[str, Any]) -> bool:
-    return is_event(body) and body["event"]["type"] == "workflow_step_execute" and "workflow_step" in body["event"]
-
-
-
-
-def is_workflow_step_save(body: Dict[str, Any]) ‑> bool -
-
-
- -Expand source code - -
def is_workflow_step_save(body: Dict[str, Any]) -> bool:
-    return is_view_submission(body) and body["view"]["type"] == "workflow_step"
-
-
-
-
-def to_action(body: Dict[str, Any]) ‑> Dict[str, Any] | None -
-
-
- -Expand source code - -
def to_action(body: Dict[str, Any]) -> Optional[Dict[str, Any]]:
-    if is_action(body):
-        if is_block_actions(body) or is_attachment_action(body):
-            return body["actions"][0]
-        else:
-            return body
-    return None
-
-
-
-
-def to_command(body: Dict[str, Any]) ‑> Dict[str, Any] | None -
-
-
- -Expand source code - -
def to_command(body: Dict[str, Any]) -> Optional[Dict[str, Any]]:
-    return body if is_slash_command(body) else None
-
-
-
-
-def to_event(body: Dict[str, Any]) ‑> Dict[str, Any] | None -
-
-
- -Expand source code - -
def to_event(body: Dict[str, Any]) -> Optional[Dict[str, Any]]:
-    return body["event"] if is_event(body) else None
-
-
-
-
-def to_message(body: Dict[str, Any]) ‑> Dict[str, Any] | None -
-
-
- -Expand source code - -
def to_message(body: Dict[str, Any]) -> Optional[Dict[str, Any]]:
-    if is_message_event(body):
-        return to_event(body)
-    return None
-
-
-
-
-def to_options(body: Dict[str, Any]) ‑> Dict[str, Any] | None -
-
-
- -Expand source code - -
def to_options(body: Dict[str, Any]) -> Optional[Dict[str, Any]]:
-    if is_options(body):
-        return body
-    return None
-
-
-
-
-def to_shortcut(body: Dict[str, Any]) ‑> Dict[str, Any] | None -
-
-
- -Expand source code - -
def to_shortcut(body: Dict[str, Any]) -> Optional[Dict[str, Any]]:
-    if is_shortcut(body):
-        return body
-    return None
-
-
-
-
-def to_step(body: Dict[str, Any]) ‑> Dict[str, Any] | None -
-
-
- -Expand source code - -
def to_step(body: Dict[str, Any]) -> Optional[Dict[str, Any]]:
-    # edit
-    if is_workflow_step_edit(body):
-        return body["workflow_step"]
-    # save
-    if is_workflow_step_save(body):
-        return body["workflow_step"]
-    # execute
-    if is_workflow_step_execute(body):
-        return body["event"]["workflow_step"]
-    return None
-
-
-
-
-def to_view(body: Dict[str, Any]) ‑> Dict[str, Any] | None -
-
-
- -Expand source code - -
def to_view(body: Dict[str, Any]) -> Optional[Dict[str, Any]]:
-    if is_view(body):
-        return body["view"]
-    return None
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/request/request.html b/docs/reference/request/request.html deleted file mode 100644 index 870b65f08..000000000 --- a/docs/reference/request/request.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - -slack_bolt.request.request API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.request.request

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class BoltRequest -(*,
body: str | dict,
query: str | Dict[str, str] | Dict[str, Sequence[str]] | None = None,
headers: Dict[str, str | Sequence[str]] | None = None,
context: Dict[str, Any] | None = None,
mode: str = 'http')
-
-
-
- -Expand source code - -
class BoltRequest:
-    raw_body: str
-    query: Dict[str, Sequence[str]]
-    headers: Dict[str, Sequence[str]]
-    content_type: Optional[str]
-    body: Dict[str, Any]
-    context: BoltContext
-    lazy_only: bool
-    lazy_function_name: Optional[str]
-    mode: str  # either "http" or "socket_mode"
-
-    def __init__(
-        self,
-        *,
-        body: Union[str, dict],
-        query: Optional[Union[str, Dict[str, str], Dict[str, Sequence[str]]]] = None,
-        headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None,
-        context: Optional[Dict[str, Any]] = None,
-        mode: str = "http",  # either "http" or "socket_mode"
-    ):
-        """Request to a Bolt app.
-
-        Args:
-            body: The raw request body (only plain text is supported for "http" mode)
-            query: The query string data in any data format.
-            headers: The request headers.
-            context: The context in this request.
-            mode: The mode used for this request. (either "http" or "socket_mode")
-        """
-        if mode == "http":
-            # HTTP Mode
-            if body is not None and not isinstance(body, str):
-                raise BoltError(error_message_raw_body_required_in_http_mode())
-            self.raw_body = body if body is not None else ""
-        else:
-            # Socket Mode
-            if body is not None and isinstance(body, str):
-                self.raw_body = body
-            else:
-                # We don't convert the dict value to str
-                # as doing so does not guarantee to keep the original structure/format.
-                self.raw_body = ""
-
-        self.query = parse_query(query)
-        self.headers = build_normalized_headers(headers)
-        self.content_type = extract_content_type(self.headers)
-
-        if isinstance(body, str):
-            self.body = parse_body(self.raw_body, self.content_type)
-        elif isinstance(body, dict):
-            self.body = body
-        else:
-            self.body = {}
-
-        self.context = build_context(BoltContext(context if context else {}), self.body)
-        self.lazy_only = bool(self.headers.get("x-slack-bolt-lazy-only", [False])[0])
-        self.lazy_function_name = self.headers.get("x-slack-bolt-lazy-function-name", [None])[0]
-        self.mode = mode
-
-    def to_copyable(self) -> "BoltRequest":
-        body: Union[str, dict] = self.raw_body if self.mode == "http" else self.body
-        return BoltRequest(
-            body=body,
-            query=self.query,
-            headers=self.headers,
-            context=self.context.to_copyable(),
-            mode=self.mode,
-        )
-
-

Request to a Bolt app.

-

Args

-
-
body
-
The raw request body (only plain text is supported for "http" mode)
-
query
-
The query string data in any data format.
-
headers
-
The request headers.
-
context
-
The context in this request.
-
mode
-
The mode used for this request. (either "http" or "socket_mode")
-
-

Class variables

-
-
var body : Dict[str, Any]
-
-

The type of the None singleton.

-
-
var content_type : str | None
-
-

The type of the None singleton.

-
-
var contextBoltContext
-
-

The type of the None singleton.

-
-
var headers : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var lazy_function_name : str | None
-
-

The type of the None singleton.

-
-
var lazy_only : bool
-
-

The type of the None singleton.

-
-
var mode : str
-
-

The type of the None singleton.

-
-
var query : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var raw_body : str
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def to_copyable(self) ‑> BoltRequest -
-
-
- -Expand source code - -
def to_copyable(self) -> "BoltRequest":
-    body: Union[str, dict] = self.raw_body if self.mode == "http" else self.body
-    return BoltRequest(
-        body=body,
-        query=self.query,
-        headers=self.headers,
-        context=self.context.to_copyable(),
-        mode=self.mode,
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/response/index.html b/docs/reference/response/index.html deleted file mode 100644 index a4f4989ee..000000000 --- a/docs/reference/response/index.html +++ /dev/null @@ -1,233 +0,0 @@ - - - - - - -slack_bolt.response API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.response

-
-
-

This interface represents Bolt's synchronous response to Slack.

-

In Socket Mode, the response data can be transformed to a WebSocket message. In the HTTP endpoint mode, -the response data becomes an HTTP response data.

-

Refer to https://docs.slack.dev/apis/events-api/ for the two types of connections.

-
-
-

Sub-modules

-
-
slack_bolt.response.response
-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class BoltResponse -(*,
status: int,
body: str | dict = '',
headers: Dict[str, str | Sequence[str]] | None = None)
-
-
-
- -Expand source code - -
class BoltResponse:
-    status: int
-    body: str
-    headers: Dict[str, Sequence[str]]
-
-    def __init__(
-        self,
-        *,
-        status: int,
-        body: Union[str, dict] = "",
-        headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None,
-    ):
-        """The response from a Bolt app.
-
-        Args:
-            status: HTTP status code
-            body: The response body (dict and str are supported)
-            headers: The response headers.
-        """
-        self.status: int = status
-        self.body: str = json.dumps(body) if isinstance(body, dict) else body
-        self.headers: Dict[str, Sequence[str]] = {}
-        if headers is not None:
-            for name, value in headers.items():
-                if value is None:
-                    continue
-                if isinstance(value, list):
-                    self.headers[name.lower()] = value
-                elif isinstance(value, set):
-                    self.headers[name.lower()] = list(value)
-                else:
-                    self.headers[name.lower()] = [str(value)]
-
-        if "content-type" not in self.headers.keys():
-            if self.body and self.body.startswith("{"):
-                self.headers["content-type"] = ["application/json;charset=utf-8"]
-            else:
-                self.headers["content-type"] = ["text/plain;charset=utf-8"]
-
-    def first_headers(self) -> Dict[str, str]:
-        return {k: list(v)[0] for k, v in self.headers.items()}
-
-    def first_headers_without_set_cookie(self) -> Dict[str, str]:
-        return {k: list(v)[0] for k, v in self.headers.items() if k != "set-cookie"}
-
-    def cookies(self) -> Sequence[SimpleCookie]:
-        header_values = self.headers.get("set-cookie", [])
-        return [self._to_simple_cookie(v) for v in header_values]
-
-    @staticmethod
-    def _to_simple_cookie(header_value: str) -> SimpleCookie:
-        c = SimpleCookie()
-        c.load(header_value)
-        return c
-
-

The response from a Bolt app.

-

Args

-
-
status
-
HTTP status code
-
body
-
The response body (dict and str are supported)
-
headers
-
The response headers.
-
-

Class variables

-
-
var body : str
-
-

The type of the None singleton.

-
-
var headers : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var status : int
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def cookies(self) ‑> Sequence[http.cookies.SimpleCookie] -
-
-
- -Expand source code - -
def cookies(self) -> Sequence[SimpleCookie]:
-    header_values = self.headers.get("set-cookie", [])
-    return [self._to_simple_cookie(v) for v in header_values]
-
-
-
-
-def first_headers(self) ‑> Dict[str, str] -
-
-
- -Expand source code - -
def first_headers(self) -> Dict[str, str]:
-    return {k: list(v)[0] for k, v in self.headers.items()}
-
-
-
- -
-
- -Expand source code - -
def first_headers_without_set_cookie(self) -> Dict[str, str]:
-    return {k: list(v)[0] for k, v in self.headers.items() if k != "set-cookie"}
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/response/response.html b/docs/reference/response/response.html deleted file mode 100644 index 5044254e8..000000000 --- a/docs/reference/response/response.html +++ /dev/null @@ -1,217 +0,0 @@ - - - - - - -slack_bolt.response.response API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.response.response

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class BoltResponse -(*,
status: int,
body: str | dict = '',
headers: Dict[str, str | Sequence[str]] | None = None)
-
-
-
- -Expand source code - -
class BoltResponse:
-    status: int
-    body: str
-    headers: Dict[str, Sequence[str]]
-
-    def __init__(
-        self,
-        *,
-        status: int,
-        body: Union[str, dict] = "",
-        headers: Optional[Dict[str, Union[str, Sequence[str]]]] = None,
-    ):
-        """The response from a Bolt app.
-
-        Args:
-            status: HTTP status code
-            body: The response body (dict and str are supported)
-            headers: The response headers.
-        """
-        self.status: int = status
-        self.body: str = json.dumps(body) if isinstance(body, dict) else body
-        self.headers: Dict[str, Sequence[str]] = {}
-        if headers is not None:
-            for name, value in headers.items():
-                if value is None:
-                    continue
-                if isinstance(value, list):
-                    self.headers[name.lower()] = value
-                elif isinstance(value, set):
-                    self.headers[name.lower()] = list(value)
-                else:
-                    self.headers[name.lower()] = [str(value)]
-
-        if "content-type" not in self.headers.keys():
-            if self.body and self.body.startswith("{"):
-                self.headers["content-type"] = ["application/json;charset=utf-8"]
-            else:
-                self.headers["content-type"] = ["text/plain;charset=utf-8"]
-
-    def first_headers(self) -> Dict[str, str]:
-        return {k: list(v)[0] for k, v in self.headers.items()}
-
-    def first_headers_without_set_cookie(self) -> Dict[str, str]:
-        return {k: list(v)[0] for k, v in self.headers.items() if k != "set-cookie"}
-
-    def cookies(self) -> Sequence[SimpleCookie]:
-        header_values = self.headers.get("set-cookie", [])
-        return [self._to_simple_cookie(v) for v in header_values]
-
-    @staticmethod
-    def _to_simple_cookie(header_value: str) -> SimpleCookie:
-        c = SimpleCookie()
-        c.load(header_value)
-        return c
-
-

The response from a Bolt app.

-

Args

-
-
status
-
HTTP status code
-
body
-
The response body (dict and str are supported)
-
headers
-
The response headers.
-
-

Class variables

-
-
var body : str
-
-

The type of the None singleton.

-
-
var headers : Dict[str, Sequence[str]]
-
-

The type of the None singleton.

-
-
var status : int
-
-

The type of the None singleton.

-
-
-

Methods

-
-
-def cookies(self) ‑> Sequence[http.cookies.SimpleCookie] -
-
-
- -Expand source code - -
def cookies(self) -> Sequence[SimpleCookie]:
-    header_values = self.headers.get("set-cookie", [])
-    return [self._to_simple_cookie(v) for v in header_values]
-
-
-
-
-def first_headers(self) ‑> Dict[str, str] -
-
-
- -Expand source code - -
def first_headers(self) -> Dict[str, str]:
-    return {k: list(v)[0] for k, v in self.headers.items()}
-
-
-
- -
-
- -Expand source code - -
def first_headers_without_set_cookie(self) -> Dict[str, str]:
-    return {k: list(v)[0] for k, v in self.headers.items() if k != "set-cookie"}
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/util/async_utils.html b/docs/reference/util/async_utils.html deleted file mode 100644 index f74d8f0ac..000000000 --- a/docs/reference/util/async_utils.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - -slack_bolt.util.async_utils API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.util.async_utils

-
-
-
-
-
-
-
-
-

Functions

-
-
-def create_async_web_client(token: str | None = None, logger: logging.Logger | None = None) ‑> slack_sdk.web.async_client.AsyncWebClient -
-
-
- -Expand source code - -
def create_async_web_client(token: Optional[str] = None, logger: Optional[Logger] = None) -> AsyncWebClient:
-    return AsyncWebClient(
-        token=token,
-        logger=logger,
-        user_agent_prefix=f"Bolt-Async/{bolt_version}",
-    )
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/util/index.html b/docs/reference/util/index.html deleted file mode 100644 index 6eadaacb9..000000000 --- a/docs/reference/util/index.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - -slack_bolt.util API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.util

-
-
-

Internal utilities for the Bolt framework.

-
-
-

Sub-modules

-
-
slack_bolt.util.async_utils
-
-
-
-
slack_bolt.util.utils
-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/util/utils.html b/docs/reference/util/utils.html deleted file mode 100644 index 85d336513..000000000 --- a/docs/reference/util/utils.html +++ /dev/null @@ -1,262 +0,0 @@ - - - - - - -slack_bolt.util.utils API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.util.utils

-
-
-
-
-
-
-
-
-

Functions

-
-
-def convert_to_dict(obj: Dict | slack_sdk.models.basic_objects.JsonObject) ‑> Dict -
-
-
- -Expand source code - -
def convert_to_dict(obj: Union[Dict, JsonObject]) -> Dict:
-    if isinstance(obj, dict):
-        return obj
-    if isinstance(obj, JsonObject) or hasattr(obj, "to_dict"):
-        return obj.to_dict()
-    raise BoltError(f"{obj} (type: {type(obj)}) is unsupported")
-
-
-
-
-def convert_to_dict_list(objects: Sequence[Dict | slack_sdk.models.basic_objects.JsonObject]) ‑> Sequence[Dict] -
-
-
- -Expand source code - -
def convert_to_dict_list(objects: Sequence[Union[Dict, JsonObject]]) -> Sequence[Dict]:
-    return [convert_to_dict(elm) for elm in objects]
-
-
-
-
-def create_copy(original: Any) ‑> Any -
-
-
- -Expand source code - -
def create_copy(original: Any) -> Any:
-    return copy.deepcopy(original)
-
-
-
-
-def create_web_client(token: str | None = None, logger: logging.Logger | None = None) ‑> slack_sdk.web.client.WebClient -
-
-
- -Expand source code - -
def create_web_client(token: Optional[str] = None, logger: Optional[Logger] = None) -> WebClient:
-    return WebClient(
-        token=token,
-        logger=logger,
-        user_agent_prefix=f"Bolt/{bolt_version}",
-    )
-
-
-
-
-def get_arg_names_of_callable(func: Callable) ‑> List[str] -
-
-
- -Expand source code - -
def get_arg_names_of_callable(func: Callable) -> List[str]:
-    return inspect.getfullargspec(inspect.unwrap(func)).args
-
-
-
-
-def get_boot_message(development_server: bool = False) ‑> str -
-
-
- -Expand source code - -
def get_boot_message(development_server: bool = False) -> str:
-    if sys.platform == "win32":
-        # Some Windows environments may fail to parse this str value
-        # and result in UnicodeEncodeError
-        if development_server:
-            return "Bolt app is running! (development server)"
-        else:
-            return "Bolt app is running!"
-
-    try:
-        if development_server:
-            return "⚡️ Bolt app is running! (development server)"
-        else:
-            return "⚡️ Bolt app is running!"
-    except ValueError:
-        # ValueError is a runtime exception for a given value
-        # It's a super class of UnicodeEncodeError, which may be raised in the scenario
-        # see also: https://github.com/slackapi/bolt-python/issues/170
-        if development_server:
-            return "Bolt app is running! (development server)"
-        else:
-            return "Bolt app is running!"
-
-
-
-
-def get_name_for_callable(func: Callable) ‑> str -
-
-
- -Expand source code - -
def get_name_for_callable(func: Callable) -> str:
-    """Returns the name for the given Callable function object.
-
-    Args:
-        func: Either a `Callable` instance or a function, which as `__name__`
-
-    Returns:
-        The name of the given Callable object
-    """
-    if hasattr(func, "__name__"):
-        return func.__name__
-    else:
-        return f"{func.__class__.__module__}.{func.__class__.__name__}"
-
-

Returns the name for the given Callable function object.

-

Args

-
-
func
-
Either a Callable instance or a function, which as __name__
-
-

Returns

-

The name of the given Callable object

-
-
-def is_callable_coroutine(func: Any | None) ‑> bool -
-
-
- -Expand source code - -
def is_callable_coroutine(func: Optional[Any]) -> bool:
-    return func is not None and (
-        inspect.iscoroutinefunction(func) or (hasattr(func, "__call__") and inspect.iscoroutinefunction(func.__call__))
-    )
-
-
-
-
-def is_used_without_argument(args) ‑> bool -
-
-
- -Expand source code - -
def is_used_without_argument(args) -> bool:
-    """Tests if a decorator invocation is without () or (args).
-
-    Args:
-        args: arguments
-
-    Returns:
-        True if it's an invocation without args
-    """
-    return len(args) == 1
-
-

Tests if a decorator invocation is without () or (args).

-

Args

-
-
args
-
arguments
-
-

Returns

-

True if it's an invocation without args

-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/version.html b/docs/reference/version.html deleted file mode 100644 index c4a0f9b83..000000000 --- a/docs/reference/version.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - -slack_bolt.version API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.version

-
-
-

Check the latest version at https://pypi.org/project/slack-bolt/

-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/index.html b/docs/reference/workflows/index.html deleted file mode 100644 index 0dfe7457f..000000000 --- a/docs/reference/workflows/index.html +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - -slack_bolt.workflows API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows

-
-
-

Steps from apps enables developers to build their own steps.

-

Check the following API documents first:

- -

Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details.

-
-
-

Sub-modules

-
-
slack_bolt.workflows.step
-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/async_step.html b/docs/reference/workflows/step/async_step.html deleted file mode 100644 index 18fdd3ab9..000000000 --- a/docs/reference/workflows/step/async_step.html +++ /dev/null @@ -1,1013 +0,0 @@ - - - - - - -slack_bolt.workflows.step.async_step API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.async_step

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncWorkflowStep -(*,
callback_id: str | Pattern,
edit: Callable[..., Awaitable[BoltResponse]] | AsyncListener | Sequence[Callable],
save: Callable[..., Awaitable[BoltResponse]] | AsyncListener | Sequence[Callable],
execute: Callable[..., Awaitable[BoltResponse]] | AsyncListener | Sequence[Callable],
app_name: str | None = None,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncWorkflowStep:
-    callback_id: Union[str, Pattern]
-    """The Callback ID of the step from app"""
-    edit: AsyncListener
-    """`edit` listener, which displays a modal in Workflow Builder"""
-    save: AsyncListener
-    """`save` listener, which accepts workflow creator's data submission in Workflow Builder"""
-    execute: AsyncListener
-    """`execute` listener, which processes the step from app execution"""
-
-    def __init__(
-        self,
-        *,
-        callback_id: Union[str, Pattern],
-        edit: Union[Callable[..., Awaitable[BoltResponse]], AsyncListener, Sequence[Callable]],
-        save: Union[Callable[..., Awaitable[BoltResponse]], AsyncListener, Sequence[Callable]],
-        execute: Union[Callable[..., Awaitable[BoltResponse]], AsyncListener, Sequence[Callable]],
-        app_name: Optional[str] = None,
-        base_logger: Optional[Logger] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Args:
-            callback_id: The callback_id for this step from app
-            edit: Either a single function or a list of functions for opening a modal in the builder UI
-                When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-            save: Either a single function or a list of functions for handling modal interactions in the builder UI
-                When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-            execute: Either a single function or a list of functions for handling steps from apps executions
-                When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-            app_name: The app name that can be mainly used for logging
-            base_logger: The logger instance that can be used as a template when creating this step's logger
-        """
-        self.callback_id = callback_id
-        app_name = app_name or __name__
-        self.edit = self.build_listener(
-            callback_id=callback_id,
-            app_name=app_name,
-            listener_or_functions=edit,
-            name="edit",
-            base_logger=base_logger,
-        )
-        self.save = self.build_listener(
-            callback_id=callback_id,
-            app_name=app_name,
-            listener_or_functions=save,
-            name="save",
-            base_logger=base_logger,
-        )
-        self.execute = self.build_listener(
-            callback_id=callback_id,
-            app_name=app_name,
-            listener_or_functions=execute,
-            name="execute",
-            base_logger=base_logger,
-        )
-
-    @classmethod
-    def builder(
-        cls,
-        callback_id: Union[str, Pattern],
-        base_logger: Optional[Logger] = None,
-    ) -> AsyncWorkflowStepBuilder:
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-        """
-        return AsyncWorkflowStepBuilder(callback_id, base_logger=base_logger)
-
-    @classmethod
-    def build_listener(
-        cls,
-        callback_id: Union[str, Pattern],
-        app_name: str,
-        listener_or_functions: Union[AsyncListener, Callable, List[Callable]],
-        name: str,
-        matchers: Optional[List[AsyncListenerMatcher]] = None,
-        middleware: Optional[List[AsyncMiddleware]] = None,
-        base_logger: Optional[Logger] = None,
-    ):
-        if listener_or_functions is None:
-            raise BoltError(f"{name} listener is required (callback_id: {callback_id})")
-
-        if isinstance(listener_or_functions, Callable):
-            listener_or_functions = [listener_or_functions]
-
-        if isinstance(listener_or_functions, AsyncListener):
-            return listener_or_functions
-        elif isinstance(listener_or_functions, list):
-            matchers = matchers if matchers else []
-            matchers.insert(0, cls._build_primary_matcher(name, callback_id, base_logger))
-            middleware = middleware if middleware else []
-            middleware.insert(0, cls._build_single_middleware(name, callback_id, base_logger))
-            functions = listener_or_functions
-            ack_function = functions.pop(0)
-            return AsyncCustomListener(
-                app_name=app_name,
-                matchers=matchers,
-                middleware=middleware,
-                ack_function=ack_function,
-                lazy_functions=functions,
-                auto_acknowledgement=name == "execute",
-                base_logger=base_logger,
-            )
-        else:
-            raise BoltError(f"Invalid {name} listener: {type(listener_or_functions)} detected (callback_id: {callback_id})")
-
-    @classmethod
-    def _build_primary_matcher(
-        cls,
-        name: str,
-        callback_id: str,
-        base_logger: Optional[Logger] = None,
-    ) -> AsyncListenerMatcher:
-        if name == "edit":
-            return workflow_step_edit(callback_id, asyncio=True, base_logger=base_logger)
-        elif name == "save":
-            return workflow_step_save(callback_id, asyncio=True, base_logger=base_logger)
-        elif name == "execute":
-            return workflow_step_execute(callback_id, asyncio=True, base_logger=base_logger)
-        else:
-            raise ValueError(f"Invalid name {name}")
-
-    @classmethod
-    def _build_single_middleware(
-        cls,
-        name: str,
-        callback_id: str,
-        base_logger: Optional[Logger] = None,
-    ) -> AsyncMiddleware:
-        if name == "edit":
-            return _build_edit_listener_middleware(callback_id, base_logger)
-        elif name == "save":
-            return _build_save_listener_middleware(base_logger)
-        elif name == "execute":
-            return _build_execute_listener_middleware(base_logger)
-        else:
-            raise ValueError(f"Invalid name {name}")
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Args

-
-
callback_id
-
The callback_id for this step from app
-
edit
-
Either a single function or a list of functions for opening a modal in the builder UI -When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-
save
-
Either a single function or a list of functions for handling modal interactions in the builder UI -When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-
execute
-
Either a single function or a list of functions for handling steps from apps executions -When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-
app_name
-
The app name that can be mainly used for logging
-
base_logger
-
The logger instance that can be used as a template when creating this step's logger
-
-

Class variables

-
-
var callback_id : str | Pattern
-
-

The Callback ID of the step from app

-
-
var editAsyncListener
-
-

edit listener, which displays a modal in Workflow Builder

-
-
var executeAsyncListener
-
-

execute listener, which processes the step from app execution

-
-
var saveAsyncListener
-
-

save listener, which accepts workflow creator's data submission in Workflow Builder

-
-
-

Static methods

-
-
-def build_listener(callback_id: str | Pattern,
app_name: str,
listener_or_functions: AsyncListener | Callable | List[Callable],
name: str,
matchers: List[AsyncListenerMatcher] | None = None,
middleware: List[AsyncMiddleware] | None = None,
base_logger: logging.Logger | None = None)
-
-
-
-
-
-def builder(callback_id: str | Pattern, base_logger: logging.Logger | None = None) ‑> AsyncWorkflowStepBuilder -
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-
-
-
-
-class AsyncWorkflowStepBuilder -(callback_id: str | Pattern,
app_name: str | None = None,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class AsyncWorkflowStepBuilder:
-    """Steps from apps
-    Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details.
-    """
-
-    callback_id: Union[str, Pattern]
-    _base_logger: Optional[Logger]
-    _edit: Optional[AsyncListener]
-    _save: Optional[AsyncListener]
-    _execute: Optional[AsyncListener]
-
-    def __init__(
-        self,
-        callback_id: Union[str, Pattern],
-        app_name: Optional[str] = None,
-        base_logger: Optional[Logger] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        This builder is supposed to be used as decorator.
-
-            my_step = AsyncWorkflowStep.builder("my_step")
-            @my_step.edit
-            async def edit_my_step(ack, configure):
-                pass
-            @my_step.save
-            async def save_my_step(ack, step, update):
-                pass
-            @my_step.execute
-            async def execute_my_step(step, complete, fail):
-                pass
-            app.step(my_step)
-
-        For further information about AsyncWorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            callback_id: The callback_id for the workflow
-            app_name: The application name mainly for logging
-            base_logger: The base logger
-        """
-        self.callback_id = callback_id
-        self.app_name = app_name or __name__
-        self._base_logger = base_logger
-        self._edit = None
-        self._save = None
-        self._execute = None
-
-    def edit(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-        lazy: Optional[List[Callable[..., Awaitable[None]]]] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Registers a new edit listener with details.
-
-        You can use this method as decorator as well.
-
-            @my_step.edit
-            def edit_my_step(ack, configure):
-                pass
-
-        It's also possible to add additional listener matchers and/or middleware
-
-            @my_step.edit(matchers=[is_valid], middleware=[update_context])
-            def edit_my_step(ack, configure):
-                pass
-
-        For further information about AsyncWorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            *args: This method can behave as either decorator or a method
-            matchers: Listener matchers
-            middleware: Listener middleware
-            lazy: Lazy listeners
-        """
-        if _is_used_without_argument(args):
-            func = args[0]
-            self._edit = self._to_listener("edit", func, matchers, middleware)
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._edit = self._to_listener("edit", functions, matchers, middleware)
-
-            @wraps(func)
-            async def _wrapper(*args, **kwargs):
-                return await func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def save(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-        lazy: Optional[List[Callable[..., Awaitable[None]]]] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Registers a new save listener with details.
-
-        You can use this method as decorator as well.
-
-            @my_step.save
-            def save_my_step(ack, step, update):
-                pass
-
-        It's also possible to add additional listener matchers and/or middleware
-
-            @my_step.save(matchers=[is_valid], middleware=[update_context])
-            def save_my_step(ack, step, update):
-                pass
-
-        For further information about AsyncWorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            *args: This method can behave as either decorator or a method
-            matchers: Listener matchers
-            middleware: Listener middleware
-            lazy: Lazy listeners
-        """
-        if _is_used_without_argument(args):
-            func = args[0]
-            self._save = self._to_listener("save", func, matchers, middleware)
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._save = self._to_listener("save", functions, matchers, middleware)
-
-            @wraps(func)
-            async def _wrapper(*args, **kwargs):
-                return await func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def execute(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-        lazy: Optional[List[Callable[..., Awaitable[None]]]] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Registers a new execute listener with details.
-
-        You can use this method as decorator as well.
-
-            @my_step.execute
-            def execute_my_step(step, complete, fail):
-                pass
-
-        It's also possible to add additional listener matchers and/or middleware
-
-            @my_step.save(matchers=[is_valid], middleware=[update_context])
-            def execute_my_step(step, complete, fail):
-                pass
-
-        For further information about AsyncWorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            *args: This method can behave as either decorator or a method
-            matchers: Listener matchers
-            middleware: Listener middleware
-            lazy: Lazy listeners
-        """
-        if _is_used_without_argument(args):
-            func = args[0]
-            self._execute = self._to_listener("execute", func, matchers, middleware)
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._execute = self._to_listener("execute", functions, matchers, middleware)
-
-            @wraps(func)
-            async def _wrapper(*args, **kwargs):
-                return await func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def build(self, base_logger: Optional[Logger] = None) -> "AsyncWorkflowStep":
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Constructs a WorkflowStep object. This method may raise an exception
-        if the builder doesn't have enough configurations to build the object.
-
-        Returns:
-            An `AsyncWorkflowStep` object
-        """
-        if self._edit is None:
-            raise BoltError("edit listener is not registered")
-        if self._save is None:
-            raise BoltError("save listener is not registered")
-        if self._execute is None:
-            raise BoltError("execute listener is not registered")
-
-        return AsyncWorkflowStep(
-            callback_id=self.callback_id,
-            edit=self._edit,
-            save=self._save,
-            execute=self._execute,
-            app_name=self.app_name,
-            base_logger=base_logger,
-        )
-
-    # ---------------------------------------
-
-    def _to_listener(
-        self,
-        name: str,
-        listener_or_functions: Union[AsyncListener, Callable, List[Callable]],
-        matchers: Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-    ) -> AsyncListener:
-        return AsyncWorkflowStep.build_listener(
-            callback_id=self.callback_id,
-            app_name=self.app_name,
-            listener_or_functions=listener_or_functions,
-            name=name,
-            matchers=self.to_listener_matchers(self.app_name, matchers),
-            middleware=self.to_listener_middleware(self.app_name, middleware),
-            base_logger=self._base_logger,
-        )
-
-    @staticmethod
-    def to_listener_matchers(
-        app_name: str,
-        matchers: Optional[List[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]]],
-    ) -> List[AsyncListenerMatcher]:
-        _matchers = []
-        if matchers is not None:
-            for m in matchers:
-                if isinstance(m, AsyncListenerMatcher):
-                    _matchers.append(m)
-                elif isinstance(m, Callable):
-                    _matchers.append(AsyncCustomListenerMatcher(app_name=app_name, func=m))
-                else:
-                    raise ValueError(f"Invalid matcher: {type(m)}")
-        return _matchers
-
-    @staticmethod
-    def to_listener_middleware(
-        app_name: str, middleware: Optional[List[Union[Callable, AsyncMiddleware]]]
-    ) -> List[AsyncMiddleware]:
-        _middleware = []
-        if middleware is not None:
-            for m in middleware:
-                if isinstance(m, AsyncMiddleware):
-                    _middleware.append(m)
-                elif isinstance(m, Callable):
-                    _middleware.append(AsyncCustomMiddleware(app_name=app_name, func=m))
-                else:
-                    raise ValueError(f"Invalid middleware: {type(m)}")
-        return _middleware
-
-

Steps from apps -Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details.

-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

This builder is supposed to be used as decorator.

-
my_step = AsyncWorkflowStep.builder("my_step")
-@my_step.edit
-async def edit_my_step(ack, configure):
-    pass
-@my_step.save
-async def save_my_step(ack, step, update):
-    pass
-@my_step.execute
-async def execute_my_step(step, complete, fail):
-    pass
-app.step(my_step)
-
-

For further information about AsyncWorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to the async prefixed ones in slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
callback_id
-
The callback_id for the workflow
-
app_name
-
The application name mainly for logging
-
base_logger
-
The base logger
-
-

Class variables

-
-
var callback_id : str | Pattern
-
-

The type of the None singleton.

-
-
-

Static methods

-
-
-def to_listener_matchers(app_name: str,
matchers: List[AsyncListenerMatcher | Callable[..., Awaitable[bool]]] | None) ‑> List[AsyncListenerMatcher]
-
-
-
- -Expand source code - -
@staticmethod
-def to_listener_matchers(
-    app_name: str,
-    matchers: Optional[List[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]]],
-) -> List[AsyncListenerMatcher]:
-    _matchers = []
-    if matchers is not None:
-        for m in matchers:
-            if isinstance(m, AsyncListenerMatcher):
-                _matchers.append(m)
-            elif isinstance(m, Callable):
-                _matchers.append(AsyncCustomListenerMatcher(app_name=app_name, func=m))
-            else:
-                raise ValueError(f"Invalid matcher: {type(m)}")
-    return _matchers
-
-
-
-
-def to_listener_middleware(app_name: str,
middleware: List[Callable | AsyncMiddleware] | None) ‑> List[AsyncMiddleware]
-
-
-
- -Expand source code - -
@staticmethod
-def to_listener_middleware(
-    app_name: str, middleware: Optional[List[Union[Callable, AsyncMiddleware]]]
-) -> List[AsyncMiddleware]:
-    _middleware = []
-    if middleware is not None:
-        for m in middleware:
-            if isinstance(m, AsyncMiddleware):
-                _middleware.append(m)
-            elif isinstance(m, Callable):
-                _middleware.append(AsyncCustomMiddleware(app_name=app_name, func=m))
-            else:
-                raise ValueError(f"Invalid middleware: {type(m)}")
-    return _middleware
-
-
-
-
-

Methods

-
-
-def build(self, base_logger: logging.Logger | None = None) ‑> AsyncWorkflowStep -
-
-
- -Expand source code - -
def build(self, base_logger: Optional[Logger] = None) -> "AsyncWorkflowStep":
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Constructs a WorkflowStep object. This method may raise an exception
-    if the builder doesn't have enough configurations to build the object.
-
-    Returns:
-        An `AsyncWorkflowStep` object
-    """
-    if self._edit is None:
-        raise BoltError("edit listener is not registered")
-    if self._save is None:
-        raise BoltError("save listener is not registered")
-    if self._execute is None:
-        raise BoltError("execute listener is not registered")
-
-    return AsyncWorkflowStep(
-        callback_id=self.callback_id,
-        edit=self._edit,
-        save=self._save,
-        execute=self._execute,
-        app_name=self.app_name,
-        base_logger=base_logger,
-    )
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Constructs a WorkflowStep object. This method may raise an exception -if the builder doesn't have enough configurations to build the object.

-

Returns

-

An AsyncWorkflowStep object

-
-
-def edit(self,
*args,
matchers: Callable[..., Awaitable[bool]] | AsyncListenerMatcher | None = None,
middleware: Callable | AsyncMiddleware | None = None,
lazy: List[Callable[..., Awaitable[None]]] | None = None)
-
-
-
- -Expand source code - -
def edit(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-    lazy: Optional[List[Callable[..., Awaitable[None]]]] = None,
-):
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Registers a new edit listener with details.
-
-    You can use this method as decorator as well.
-
-        @my_step.edit
-        def edit_my_step(ack, configure):
-            pass
-
-    It's also possible to add additional listener matchers and/or middleware
-
-        @my_step.edit(matchers=[is_valid], middleware=[update_context])
-        def edit_my_step(ack, configure):
-            pass
-
-    For further information about AsyncWorkflowStep specific function arguments
-    such as `configure`, `update`, `complete`, and `fail`,
-    refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents.
-
-    Args:
-        *args: This method can behave as either decorator or a method
-        matchers: Listener matchers
-        middleware: Listener middleware
-        lazy: Lazy listeners
-    """
-    if _is_used_without_argument(args):
-        func = args[0]
-        self._edit = self._to_listener("edit", func, matchers, middleware)
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._edit = self._to_listener("edit", functions, matchers, middleware)
-
-        @wraps(func)
-        async def _wrapper(*args, **kwargs):
-            return await func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Registers a new edit listener with details.

-

You can use this method as decorator as well.

-
@my_step.edit
-def edit_my_step(ack, configure):
-    pass
-
-

It's also possible to add additional listener matchers and/or middleware

-
@my_step.edit(matchers=[is_valid], middleware=[update_context])
-def edit_my_step(ack, configure):
-    pass
-
-

For further information about AsyncWorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to the async prefixed ones in slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
*args
-
This method can behave as either decorator or a method
-
matchers
-
Listener matchers
-
middleware
-
Listener middleware
-
lazy
-
Lazy listeners
-
-
-
-def execute(self,
*args,
matchers: Callable[..., Awaitable[bool]] | AsyncListenerMatcher | None = None,
middleware: Callable | AsyncMiddleware | None = None,
lazy: List[Callable[..., Awaitable[None]]] | None = None)
-
-
-
- -Expand source code - -
def execute(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-    lazy: Optional[List[Callable[..., Awaitable[None]]]] = None,
-):
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Registers a new execute listener with details.
-
-    You can use this method as decorator as well.
-
-        @my_step.execute
-        def execute_my_step(step, complete, fail):
-            pass
-
-    It's also possible to add additional listener matchers and/or middleware
-
-        @my_step.save(matchers=[is_valid], middleware=[update_context])
-        def execute_my_step(step, complete, fail):
-            pass
-
-    For further information about AsyncWorkflowStep specific function arguments
-    such as `configure`, `update`, `complete`, and `fail`,
-    refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents.
-
-    Args:
-        *args: This method can behave as either decorator or a method
-        matchers: Listener matchers
-        middleware: Listener middleware
-        lazy: Lazy listeners
-    """
-    if _is_used_without_argument(args):
-        func = args[0]
-        self._execute = self._to_listener("execute", func, matchers, middleware)
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._execute = self._to_listener("execute", functions, matchers, middleware)
-
-        @wraps(func)
-        async def _wrapper(*args, **kwargs):
-            return await func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Registers a new execute listener with details.

-

You can use this method as decorator as well.

-
@my_step.execute
-def execute_my_step(step, complete, fail):
-    pass
-
-

It's also possible to add additional listener matchers and/or middleware

-
@my_step.save(matchers=[is_valid], middleware=[update_context])
-def execute_my_step(step, complete, fail):
-    pass
-
-

For further information about AsyncWorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to the async prefixed ones in slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
*args
-
This method can behave as either decorator or a method
-
matchers
-
Listener matchers
-
middleware
-
Listener middleware
-
lazy
-
Lazy listeners
-
-
-
-def save(self,
*args,
matchers: Callable[..., Awaitable[bool]] | AsyncListenerMatcher | None = None,
middleware: Callable | AsyncMiddleware | None = None,
lazy: List[Callable[..., Awaitable[None]]] | None = None)
-
-
-
- -Expand source code - -
def save(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., Awaitable[bool]], AsyncListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, AsyncMiddleware]] = None,
-    lazy: Optional[List[Callable[..., Awaitable[None]]]] = None,
-):
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Registers a new save listener with details.
-
-    You can use this method as decorator as well.
-
-        @my_step.save
-        def save_my_step(ack, step, update):
-            pass
-
-    It's also possible to add additional listener matchers and/or middleware
-
-        @my_step.save(matchers=[is_valid], middleware=[update_context])
-        def save_my_step(ack, step, update):
-            pass
-
-    For further information about AsyncWorkflowStep specific function arguments
-    such as `configure`, `update`, `complete`, and `fail`,
-    refer to the `async` prefixed ones in `slack_bolt.workflows.step.utilities` API documents.
-
-    Args:
-        *args: This method can behave as either decorator or a method
-        matchers: Listener matchers
-        middleware: Listener middleware
-        lazy: Lazy listeners
-    """
-    if _is_used_without_argument(args):
-        func = args[0]
-        self._save = self._to_listener("save", func, matchers, middleware)
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._save = self._to_listener("save", functions, matchers, middleware)
-
-        @wraps(func)
-        async def _wrapper(*args, **kwargs):
-            return await func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Registers a new save listener with details.

-

You can use this method as decorator as well.

-
@my_step.save
-def save_my_step(ack, step, update):
-    pass
-
-

It's also possible to add additional listener matchers and/or middleware

-
@my_step.save(matchers=[is_valid], middleware=[update_context])
-def save_my_step(ack, step, update):
-    pass
-
-

For further information about AsyncWorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to the async prefixed ones in slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
*args
-
This method can behave as either decorator or a method
-
matchers
-
Listener matchers
-
middleware
-
Listener middleware
-
lazy
-
Lazy listeners
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/async_step_middleware.html b/docs/reference/workflows/step/async_step_middleware.html deleted file mode 100644 index a174b9c11..000000000 --- a/docs/reference/workflows/step/async_step_middleware.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - -slack_bolt.workflows.step.async_step_middleware API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.async_step_middleware

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncWorkflowStepMiddleware -(step: AsyncWorkflowStep) -
-
-
- -Expand source code - -
class AsyncWorkflowStepMiddleware(AsyncMiddleware):
-    """Base middleware for step from app specific ones"""
-
-    def __init__(self, step: AsyncWorkflowStep):
-        self.step = step
-
-    async def async_process(
-        self,
-        *,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-        next: Callable[[], Awaitable[BoltResponse]],
-    ) -> BoltResponse:
-
-        if await self.step.edit.async_matches(req=req, resp=resp):
-            resp = await self._run(self.step.edit, req, resp)
-            if resp is not None:
-                return resp
-        elif await self.step.save.async_matches(req=req, resp=resp):
-            resp = await self._run(self.step.save, req, resp)
-            if resp is not None:
-                return resp
-        elif await self.step.execute.async_matches(req=req, resp=resp):
-            resp = await self._run(self.step.execute, req, resp)
-            if resp is not None:
-                return resp
-
-        return await next()
-
-    @staticmethod
-    async def _run(
-        listener: AsyncListener,
-        req: AsyncBoltRequest,
-        resp: BoltResponse,
-    ) -> Optional[BoltResponse]:
-        resp, next_was_not_called = await listener.run_async_middleware(req=req, resp=resp)
-        if next_was_not_called:
-            return None
-
-        return await req.context.listener_runner.run(
-            request=req,
-            response=resp,
-            listener_name=get_name_for_callable(listener.ack_function),
-            listener=listener,
-        )
-
-

Base middleware for step from app specific ones

-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/index.html b/docs/reference/workflows/step/index.html deleted file mode 100644 index 50b52906b..000000000 --- a/docs/reference/workflows/step/index.html +++ /dev/null @@ -1,738 +0,0 @@ - - - - - - -slack_bolt.workflows.step API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step

-
-
-
-
-

Sub-modules

-
-
slack_bolt.workflows.step.async_step
-
-
-
-
slack_bolt.workflows.step.async_step_middleware
-
-
-
-
slack_bolt.workflows.step.internals
-
-
-
-
slack_bolt.workflows.step.step
-
-
-
-
slack_bolt.workflows.step.step_middleware
-
-
-
-
slack_bolt.workflows.step.utilities
-
-

Utilities specific to steps from apps …

-
-
-
-
-
-
-
-
-

Classes

-
-
-class Complete -(*, client: slack_sdk.web.client.WebClient, body: dict) -
-
-
- -Expand source code - -
class Complete:
-    """`complete()` utility to tell Slack the completion of a step from app execution.
-
-        def execute(step, complete, fail):
-            inputs = step["inputs"]
-            # if everything was successful
-            outputs = {
-                "task_name": inputs["task_name"]["value"],
-                "task_description": inputs["task_description"]["value"],
-            }
-            complete(outputs=outputs)
-
-        ws = WorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        app.step(ws)
-
-    This utility is a thin wrapper of workflows.stepCompleted API method.
-    Refer to https://api.slack.com/methods/workflows.stepCompleted for details.
-    """
-
-    def __init__(self, *, client: WebClient, body: dict):
-        self.client = client
-        self.body = body
-
-    def __call__(self, **kwargs) -> None:
-        self.client.workflows_stepCompleted(
-            workflow_step_execute_id=self.body["event"]["workflow_step"]["workflow_step_execute_id"],
-            **kwargs,
-        )
-
-

complete() utility to tell Slack the completion of a step from app execution.

-
def execute(step, complete, fail):
-    inputs = step["inputs"]
-    # if everything was successful
-    outputs = {
-        "task_name": inputs["task_name"]["value"],
-        "task_description": inputs["task_description"]["value"],
-    }
-    complete(outputs=outputs)
-
-ws = WorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-app.step(ws)
-
-

This utility is a thin wrapper of workflows.stepCompleted API method. -Refer to https://api.slack.com/methods/workflows.stepCompleted for details.

-
-
-class Configure -(*, callback_id: str, client: slack_sdk.web.client.WebClient, body: dict) -
-
-
- -Expand source code - -
class Configure:
-    """`configure()` utility to send the modal view in Workflow Builder.
-
-        def edit(ack, step, configure):
-            ack()
-
-            blocks = [
-                {
-                    "type": "input",
-                    "block_id": "task_name_input",
-                    "element": {
-                        "type": "plain_text_input",
-                        "action_id": "name",
-                        "placeholder": {"type": "plain_text", "text": "Add a task name"},
-                    },
-                    "label": {"type": "plain_text", "text": "Task name"},
-                },
-            ]
-            configure(blocks=blocks)
-
-        ws = WorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        app.step(ws)
-
-    Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details.
-    """
-
-    def __init__(self, *, callback_id: str, client: WebClient, body: dict):
-        self.callback_id = callback_id
-        self.client = client
-        self.body = body
-
-    def __call__(self, *, blocks: Optional[Sequence[Union[dict, Block]]] = None, **kwargs) -> None:
-        self.client.views_open(
-            trigger_id=self.body["trigger_id"],
-            view={
-                "type": "workflow_step",
-                "callback_id": self.callback_id,
-                "blocks": blocks,
-                **kwargs,
-            },
-        )
-
-

configure() utility to send the modal view in Workflow Builder.

-
def edit(ack, step, configure):
-    ack()
-
-    blocks = [
-        {
-            "type": "input",
-            "block_id": "task_name_input",
-            "element": {
-                "type": "plain_text_input",
-                "action_id": "name",
-                "placeholder": {"type": "plain_text", "text": "Add a task name"},
-            },
-            "label": {"type": "plain_text", "text": "Task name"},
-        },
-    ]
-    configure(blocks=blocks)
-
-ws = WorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-app.step(ws)
-
-

Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details.

-
-
-class Fail -(*, client: slack_sdk.web.client.WebClient, body: dict) -
-
-
- -Expand source code - -
class Fail:
-    """`fail()` utility to tell Slack the execution failure of a step from app.
-
-        def execute(step, complete, fail):
-            inputs = step["inputs"]
-            # if something went wrong
-            error = {"message": "Just testing step failure!"}
-            fail(error=error)
-
-        ws = WorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        app.step(ws)
-
-    This utility is a thin wrapper of workflows.stepFailed API method.
-    Refer to https://api.slack.com/methods/workflows.stepFailed for details.
-    """
-
-    def __init__(self, *, client: WebClient, body: dict):
-        self.client = client
-        self.body = body
-
-    def __call__(
-        self,
-        *,
-        error: dict,
-    ) -> None:
-        self.client.workflows_stepFailed(
-            workflow_step_execute_id=self.body["event"]["workflow_step"]["workflow_step_execute_id"],
-            error=error,
-        )
-
-

fail() utility to tell Slack the execution failure of a step from app.

-
def execute(step, complete, fail):
-    inputs = step["inputs"]
-    # if something went wrong
-    error = {"message": "Just testing step failure!"}
-    fail(error=error)
-
-ws = WorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-app.step(ws)
-
-

This utility is a thin wrapper of workflows.stepFailed API method. -Refer to https://api.slack.com/methods/workflows.stepFailed for details.

-
-
-class Update -(*, client: slack_sdk.web.client.WebClient, body: dict) -
-
-
- -Expand source code - -
class Update:
-    """`update()` utility to tell Slack the processing results of a `save` listener.
-
-        def save(ack, view, update):
-            ack()
-
-            values = view["state"]["values"]
-            task_name = values["task_name_input"]["name"]
-            task_description = values["task_description_input"]["description"]
-
-            inputs = {
-                "task_name": {"value": task_name["value"]},
-                "task_description": {"value": task_description["value"]}
-            }
-            outputs = [
-                {
-                    "type": "text",
-                    "name": "task_name",
-                    "label": "Task name",
-                },
-                {
-                    "type": "text",
-                    "name": "task_description",
-                    "label": "Task description",
-                }
-            ]
-            update(inputs=inputs, outputs=outputs)
-
-        ws = WorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        app.step(ws)
-
-    This utility is a thin wrapper of workflows.stepFailed API method.
-    Refer to https://api.slack.com/methods/workflows.updateStep for details.
-    """
-
-    def __init__(self, *, client: WebClient, body: dict):
-        self.client = client
-        self.body = body
-
-    def __call__(self, **kwargs) -> None:
-        self.client.workflows_updateStep(
-            workflow_step_edit_id=self.body["workflow_step"]["workflow_step_edit_id"],
-            **kwargs,
-        )
-
-

update() utility to tell Slack the processing results of a save listener.

-
def save(ack, view, update):
-    ack()
-
-    values = view["state"]["values"]
-    task_name = values["task_name_input"]["name"]
-    task_description = values["task_description_input"]["description"]
-
-    inputs = {
-        "task_name": {"value": task_name["value"]},
-        "task_description": {"value": task_description["value"]}
-    }
-    outputs = [
-        {
-            "type": "text",
-            "name": "task_name",
-            "label": "Task name",
-        },
-        {
-            "type": "text",
-            "name": "task_description",
-            "label": "Task description",
-        }
-    ]
-    update(inputs=inputs, outputs=outputs)
-
-ws = WorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-app.step(ws)
-
-

This utility is a thin wrapper of workflows.stepFailed API method. -Refer to https://api.slack.com/methods/workflows.updateStep for details.

-
-
-class WorkflowStep -(*,
callback_id: str | Pattern,
edit: Callable[..., BoltResponse | None] | Listener | Sequence[Callable],
save: Callable[..., BoltResponse | None] | Listener | Sequence[Callable],
execute: Callable[..., BoltResponse | None] | Listener | Sequence[Callable],
app_name: str | None = None,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class WorkflowStep:
-    callback_id: Union[str, Pattern]
-    """The Callback ID of the step from app"""
-    edit: Listener
-    """`edit` listener, which displays a modal in Workflow Builder"""
-    save: Listener
-    """`save` listener, which accepts workflow creator's data submission in Workflow Builder"""
-    execute: Listener
-    """`execute` listener, which processes step from app execution"""
-
-    def __init__(
-        self,
-        *,
-        callback_id: Union[str, Pattern],
-        edit: Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]],
-        save: Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]],
-        execute: Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]],
-        app_name: Optional[str] = None,
-        base_logger: Optional[Logger] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Args:
-            callback_id: The callback_id for this step from app
-            edit: Either a single function or a list of functions for opening a modal in the builder UI
-                When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-            save: Either a single function or a list of functions for handling modal interactions in the builder UI
-                When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-            execute: Either a single function or a list of functions for handling step from app executions
-                When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-            app_name: The app name that can be mainly used for logging
-            base_logger: The logger instance that can be used as a template when creating this step's logger
-        """
-        self.callback_id = callback_id
-        app_name = app_name or __name__
-        self.edit = self.build_listener(
-            callback_id=callback_id,
-            app_name=app_name,
-            listener_or_functions=edit,
-            name="edit",
-            base_logger=base_logger,
-        )
-        self.save = self.build_listener(
-            callback_id=callback_id,
-            app_name=app_name,
-            listener_or_functions=save,
-            name="save",
-            base_logger=base_logger,
-        )
-        self.execute = self.build_listener(
-            callback_id=callback_id,
-            app_name=app_name,
-            listener_or_functions=execute,
-            name="execute",
-            base_logger=base_logger,
-        )
-
-    @classmethod
-    def builder(cls, callback_id: Union[str, Pattern], base_logger: Optional[Logger] = None) -> WorkflowStepBuilder:
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-        """
-        return WorkflowStepBuilder(
-            callback_id,
-            base_logger=base_logger,
-        )
-
-    @classmethod
-    def build_listener(
-        cls,
-        callback_id: Union[str, Pattern],
-        app_name: str,
-        listener_or_functions: Union[Listener, Callable, List[Callable]],
-        name: str,
-        matchers: Optional[List[ListenerMatcher]] = None,
-        middleware: Optional[List[Middleware]] = None,
-        base_logger: Optional[Logger] = None,
-    ) -> Listener:
-        if listener_or_functions is None:
-            raise BoltError(f"{name} listener is required (callback_id: {callback_id})")
-
-        if isinstance(listener_or_functions, Callable):
-            listener_or_functions = [listener_or_functions]
-
-        if isinstance(listener_or_functions, Listener):
-            return listener_or_functions
-        elif isinstance(listener_or_functions, list):
-            matchers = matchers if matchers else []
-            matchers.insert(
-                0,
-                cls._build_primary_matcher(
-                    name,
-                    callback_id,
-                    base_logger=base_logger,
-                ),
-            )
-            middleware = middleware if middleware else []
-            middleware.insert(
-                0,
-                cls._build_single_middleware(
-                    name,
-                    callback_id,
-                    base_logger=base_logger,
-                ),
-            )
-            functions = listener_or_functions
-            ack_function = functions.pop(0)
-            return CustomListener(
-                app_name=app_name,
-                matchers=matchers,
-                middleware=middleware,
-                ack_function=ack_function,
-                lazy_functions=functions,
-                auto_acknowledgement=name == "execute",
-                base_logger=base_logger,
-            )
-        else:
-            raise BoltError(f"Invalid {name} listener: {type(listener_or_functions)} detected (callback_id: {callback_id})")
-
-    @classmethod
-    def _build_primary_matcher(
-        cls,
-        name: str,
-        callback_id: Union[str, Pattern],
-        base_logger: Optional[Logger] = None,
-    ) -> ListenerMatcher:
-        if name == "edit":
-            return workflow_step_edit(callback_id, base_logger=base_logger)
-        elif name == "save":
-            return workflow_step_save(callback_id, base_logger=base_logger)
-        elif name == "execute":
-            return workflow_step_execute(callback_id, base_logger=base_logger)
-        else:
-            raise ValueError(f"Invalid name {name}")
-
-    @classmethod
-    def _build_single_middleware(
-        cls,
-        name: str,
-        callback_id: Union[str, Pattern],
-        base_logger: Optional[Logger] = None,
-    ) -> Middleware:
-        if name == "edit":
-            return _build_edit_listener_middleware(callback_id, base_logger=base_logger)
-        elif name == "save":
-            return _build_save_listener_middleware(base_logger=base_logger)
-        elif name == "execute":
-            return _build_execute_listener_middleware(base_logger=base_logger)
-        else:
-            raise ValueError(f"Invalid name {name}")
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Args

-
-
callback_id
-
The callback_id for this step from app
-
edit
-
Either a single function or a list of functions for opening a modal in the builder UI -When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-
save
-
Either a single function or a list of functions for handling modal interactions in the builder UI -When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-
execute
-
Either a single function or a list of functions for handling step from app executions -When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-
app_name
-
The app name that can be mainly used for logging
-
base_logger
-
The logger instance that can be used as a template when creating this step's logger
-
-

Class variables

-
-
var callback_id : str | Pattern
-
-

The Callback ID of the step from app

-
-
var editListener
-
-

edit listener, which displays a modal in Workflow Builder

-
-
var executeListener
-
-

execute listener, which processes step from app execution

-
-
var saveListener
-
-

save listener, which accepts workflow creator's data submission in Workflow Builder

-
-
-

Static methods

-
-
-def build_listener(callback_id: str | Pattern,
app_name: str,
listener_or_functions: Listener | Callable | List[Callable],
name: str,
matchers: List[ListenerMatcher] | None = None,
middleware: List[Middleware] | None = None,
base_logger: logging.Logger | None = None) ‑> Listener
-
-
-
-
-
-def builder(callback_id: str | Pattern, base_logger: logging.Logger | None = None) ‑> WorkflowStepBuilder -
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-
-
-
-
-class WorkflowStepMiddleware -(step: WorkflowStep) -
-
-
- -Expand source code - -
class WorkflowStepMiddleware(Middleware):
-    """Base middleware for step from app specific ones"""
-
-    def __init__(self, step: WorkflowStep):
-        self.step = step
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> Optional[BoltResponse]:
-
-        if self.step.edit.matches(req=req, resp=resp):
-            resp = self._run(self.step.edit, req, resp)
-            if resp is not None:
-                return resp
-        elif self.step.save.matches(req=req, resp=resp):
-            resp = self._run(self.step.save, req, resp)
-            if resp is not None:
-                return resp
-        elif self.step.execute.matches(req=req, resp=resp):
-            resp = self._run(self.step.execute, req, resp)
-            if resp is not None:
-                return resp
-
-        return next()
-
-    @staticmethod
-    def _run(
-        listener: Listener,
-        req: BoltRequest,
-        resp: BoltResponse,
-    ) -> Optional[BoltResponse]:
-        resp, next_was_not_called = listener.run_middleware(req=req, resp=resp)
-        if next_was_not_called:
-            return None
-
-        return req.context.listener_runner.run(
-            request=req,
-            response=resp,
-            listener_name=get_name_for_callable(listener.ack_function),
-            listener=listener,
-        )
-
-

Base middleware for step from app specific ones

-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/internals.html b/docs/reference/workflows/step/internals.html deleted file mode 100644 index c5fda1012..000000000 --- a/docs/reference/workflows/step/internals.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - -slack_bolt.workflows.step.internals API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.internals

-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/step.html b/docs/reference/workflows/step/step.html deleted file mode 100644 index 0309acd88..000000000 --- a/docs/reference/workflows/step/step.html +++ /dev/null @@ -1,1058 +0,0 @@ - - - - - - -slack_bolt.workflows.step.step API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.step

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class WorkflowStep -(*,
callback_id: str | Pattern,
edit: Callable[..., BoltResponse | None] | Listener | Sequence[Callable],
save: Callable[..., BoltResponse | None] | Listener | Sequence[Callable],
execute: Callable[..., BoltResponse | None] | Listener | Sequence[Callable],
app_name: str | None = None,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class WorkflowStep:
-    callback_id: Union[str, Pattern]
-    """The Callback ID of the step from app"""
-    edit: Listener
-    """`edit` listener, which displays a modal in Workflow Builder"""
-    save: Listener
-    """`save` listener, which accepts workflow creator's data submission in Workflow Builder"""
-    execute: Listener
-    """`execute` listener, which processes step from app execution"""
-
-    def __init__(
-        self,
-        *,
-        callback_id: Union[str, Pattern],
-        edit: Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]],
-        save: Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]],
-        execute: Union[Callable[..., Optional[BoltResponse]], Listener, Sequence[Callable]],
-        app_name: Optional[str] = None,
-        base_logger: Optional[Logger] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Args:
-            callback_id: The callback_id for this step from app
-            edit: Either a single function or a list of functions for opening a modal in the builder UI
-                When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-            save: Either a single function or a list of functions for handling modal interactions in the builder UI
-                When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-            execute: Either a single function or a list of functions for handling step from app executions
-                When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-            app_name: The app name that can be mainly used for logging
-            base_logger: The logger instance that can be used as a template when creating this step's logger
-        """
-        self.callback_id = callback_id
-        app_name = app_name or __name__
-        self.edit = self.build_listener(
-            callback_id=callback_id,
-            app_name=app_name,
-            listener_or_functions=edit,
-            name="edit",
-            base_logger=base_logger,
-        )
-        self.save = self.build_listener(
-            callback_id=callback_id,
-            app_name=app_name,
-            listener_or_functions=save,
-            name="save",
-            base_logger=base_logger,
-        )
-        self.execute = self.build_listener(
-            callback_id=callback_id,
-            app_name=app_name,
-            listener_or_functions=execute,
-            name="execute",
-            base_logger=base_logger,
-        )
-
-    @classmethod
-    def builder(cls, callback_id: Union[str, Pattern], base_logger: Optional[Logger] = None) -> WorkflowStepBuilder:
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-        """
-        return WorkflowStepBuilder(
-            callback_id,
-            base_logger=base_logger,
-        )
-
-    @classmethod
-    def build_listener(
-        cls,
-        callback_id: Union[str, Pattern],
-        app_name: str,
-        listener_or_functions: Union[Listener, Callable, List[Callable]],
-        name: str,
-        matchers: Optional[List[ListenerMatcher]] = None,
-        middleware: Optional[List[Middleware]] = None,
-        base_logger: Optional[Logger] = None,
-    ) -> Listener:
-        if listener_or_functions is None:
-            raise BoltError(f"{name} listener is required (callback_id: {callback_id})")
-
-        if isinstance(listener_or_functions, Callable):
-            listener_or_functions = [listener_or_functions]
-
-        if isinstance(listener_or_functions, Listener):
-            return listener_or_functions
-        elif isinstance(listener_or_functions, list):
-            matchers = matchers if matchers else []
-            matchers.insert(
-                0,
-                cls._build_primary_matcher(
-                    name,
-                    callback_id,
-                    base_logger=base_logger,
-                ),
-            )
-            middleware = middleware if middleware else []
-            middleware.insert(
-                0,
-                cls._build_single_middleware(
-                    name,
-                    callback_id,
-                    base_logger=base_logger,
-                ),
-            )
-            functions = listener_or_functions
-            ack_function = functions.pop(0)
-            return CustomListener(
-                app_name=app_name,
-                matchers=matchers,
-                middleware=middleware,
-                ack_function=ack_function,
-                lazy_functions=functions,
-                auto_acknowledgement=name == "execute",
-                base_logger=base_logger,
-            )
-        else:
-            raise BoltError(f"Invalid {name} listener: {type(listener_or_functions)} detected (callback_id: {callback_id})")
-
-    @classmethod
-    def _build_primary_matcher(
-        cls,
-        name: str,
-        callback_id: Union[str, Pattern],
-        base_logger: Optional[Logger] = None,
-    ) -> ListenerMatcher:
-        if name == "edit":
-            return workflow_step_edit(callback_id, base_logger=base_logger)
-        elif name == "save":
-            return workflow_step_save(callback_id, base_logger=base_logger)
-        elif name == "execute":
-            return workflow_step_execute(callback_id, base_logger=base_logger)
-        else:
-            raise ValueError(f"Invalid name {name}")
-
-    @classmethod
-    def _build_single_middleware(
-        cls,
-        name: str,
-        callback_id: Union[str, Pattern],
-        base_logger: Optional[Logger] = None,
-    ) -> Middleware:
-        if name == "edit":
-            return _build_edit_listener_middleware(callback_id, base_logger=base_logger)
-        elif name == "save":
-            return _build_save_listener_middleware(base_logger=base_logger)
-        elif name == "execute":
-            return _build_execute_listener_middleware(base_logger=base_logger)
-        else:
-            raise ValueError(f"Invalid name {name}")
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Args

-
-
callback_id
-
The callback_id for this step from app
-
edit
-
Either a single function or a list of functions for opening a modal in the builder UI -When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-
save
-
Either a single function or a list of functions for handling modal interactions in the builder UI -When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-
execute
-
Either a single function or a list of functions for handling step from app executions -When it's a list, the first one is responsible for ack() while the rest are lazy listeners.
-
app_name
-
The app name that can be mainly used for logging
-
base_logger
-
The logger instance that can be used as a template when creating this step's logger
-
-

Class variables

-
-
var callback_id : str | Pattern
-
-

The Callback ID of the step from app

-
-
var editListener
-
-

edit listener, which displays a modal in Workflow Builder

-
-
var executeListener
-
-

execute listener, which processes step from app execution

-
-
var saveListener
-
-

save listener, which accepts workflow creator's data submission in Workflow Builder

-
-
-

Static methods

-
-
-def build_listener(callback_id: str | Pattern,
app_name: str,
listener_or_functions: Listener | Callable | List[Callable],
name: str,
matchers: List[ListenerMatcher] | None = None,
middleware: List[Middleware] | None = None,
base_logger: logging.Logger | None = None) ‑> Listener
-
-
-
-
-
-def builder(callback_id: str | Pattern, base_logger: logging.Logger | None = None) ‑> WorkflowStepBuilder -
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-
-
-
-
-class WorkflowStepBuilder -(callback_id: str | Pattern,
app_name: str | None = None,
base_logger: logging.Logger | None = None)
-
-
-
- -Expand source code - -
class WorkflowStepBuilder:
-    """Steps from apps
-    Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details.
-    """
-
-    callback_id: Union[str, Pattern]
-    _base_logger: Optional[Logger]
-    _edit: Optional[Listener]
-    _save: Optional[Listener]
-    _execute: Optional[Listener]
-
-    def __init__(
-        self,
-        callback_id: Union[str, Pattern],
-        app_name: Optional[str] = None,
-        base_logger: Optional[Logger] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        This builder is supposed to be used as decorator.
-
-            my_step = WorkflowStep.builder("my_step")
-            @my_step.edit
-            def edit_my_step(ack, configure):
-                pass
-            @my_step.save
-            def save_my_step(ack, step, update):
-                pass
-            @my_step.execute
-            def execute_my_step(step, complete, fail):
-                pass
-            app.step(my_step)
-
-        For further information about WorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            callback_id: The callback_id for the workflow
-            app_name: The application name mainly for logging
-            base_logger: The base logger
-        """
-        self.callback_id = callback_id
-        self.app_name = app_name or __name__
-        self._base_logger = base_logger
-        self._edit = None
-        self._save = None
-        self._execute = None
-
-    def edit(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Registers a new edit listener with details.
-
-        You can use this method as decorator as well.
-
-            @my_step.edit
-            def edit_my_step(ack, configure):
-                pass
-
-        It's also possible to add additional listener matchers and/or middleware
-
-            @my_step.edit(matchers=[is_valid], middleware=[update_context])
-            def edit_my_step(ack, configure):
-                pass
-
-        For further information about WorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            *args: This method can behave as either decorator or a method
-            matchers: Listener matchers
-            middleware: Listener middleware
-            lazy: Lazy listeners
-        """
-
-        if _is_used_without_argument(args):
-            func = args[0]
-            self._edit = self._to_listener("edit", func, matchers, middleware)
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._edit = self._to_listener("edit", functions, matchers, middleware)
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def save(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Registers a new save listener with details.
-
-        You can use this method as decorator as well.
-
-            @my_step.save
-            def save_my_step(ack, step, update):
-                pass
-
-        It's also possible to add additional listener matchers and/or middleware
-
-            @my_step.save(matchers=[is_valid], middleware=[update_context])
-            def save_my_step(ack, step, update):
-                pass
-
-        For further information about WorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            *args: This method can behave as either decorator or a method
-            matchers: Listener matchers
-            middleware: Listener middleware
-            lazy: Lazy listeners
-        """
-        if _is_used_without_argument(args):
-            func = args[0]
-            self._save = self._to_listener("save", func, matchers, middleware)
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._save = self._to_listener("save", functions, matchers, middleware)
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def execute(
-        self,
-        *args,
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-        lazy: Optional[List[Callable[..., None]]] = None,
-    ):
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Registers a new execute listener with details.
-
-        You can use this method as decorator as well.
-
-            @my_step.execute
-            def execute_my_step(step, complete, fail):
-                pass
-
-        It's also possible to add additional listener matchers and/or middleware
-
-            @my_step.save(matchers=[is_valid], middleware=[update_context])
-            def execute_my_step(step, complete, fail):
-                pass
-
-        For further information about WorkflowStep specific function arguments
-        such as `configure`, `update`, `complete`, and `fail`,
-        refer to `slack_bolt.workflows.step.utilities` API documents.
-
-        Args:
-            *args: This method can behave as either decorator or a method
-            matchers: Listener matchers
-            middleware: Listener middleware
-            lazy: Lazy listeners
-        """
-        if _is_used_without_argument(args):
-            func = args[0]
-            self._execute = self._to_listener("execute", func, matchers, middleware)
-            return func
-
-        def _inner(func):
-            functions = [func] + (lazy if lazy is not None else [])
-            self._execute = self._to_listener("execute", functions, matchers, middleware)
-
-            @wraps(func)
-            def _wrapper(*args, **kwargs):
-                return func(*args, **kwargs)
-
-            return _wrapper
-
-        return _inner
-
-    def build(self, base_logger: Optional[Logger] = None) -> "WorkflowStep":
-        """
-        Deprecated:
-            Steps from apps for legacy workflows are now deprecated.
-            Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-        Constructs a WorkflowStep object. This method may raise an exception
-        if the builder doesn't have enough configurations to build the object.
-
-        Returns:
-            WorkflowStep object
-        """
-        if self._edit is None:
-            raise BoltError("edit listener is not registered")
-        if self._save is None:
-            raise BoltError("save listener is not registered")
-        if self._execute is None:
-            raise BoltError("execute listener is not registered")
-
-        return WorkflowStep(
-            callback_id=self.callback_id,
-            edit=self._edit,
-            save=self._save,
-            execute=self._execute,
-            app_name=self.app_name,
-            base_logger=base_logger,
-        )
-
-    # ---------------------------------------
-
-    def _to_listener(
-        self,
-        name: str,
-        listener_or_functions: Union[Listener, Callable, List[Callable]],
-        matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-        middleware: Optional[Union[Callable, Middleware]] = None,
-    ) -> Listener:
-        return WorkflowStep.build_listener(
-            callback_id=self.callback_id,
-            app_name=self.app_name,
-            listener_or_functions=listener_or_functions,
-            name=name,
-            matchers=self.to_listener_matchers(self.app_name, matchers, self._base_logger),
-            middleware=self.to_listener_middleware(self.app_name, middleware, self._base_logger),
-            base_logger=self._base_logger,
-        )
-
-    @staticmethod
-    def to_listener_matchers(
-        app_name: str,
-        matchers: Optional[List[Union[Callable[..., bool], ListenerMatcher]]],
-        base_logger: Optional[Logger] = None,
-    ) -> List[ListenerMatcher]:
-        _matchers = []
-        if matchers is not None:
-            for m in matchers:
-                if isinstance(m, ListenerMatcher):
-                    _matchers.append(m)
-                elif isinstance(m, Callable):
-                    _matchers.append(
-                        CustomListenerMatcher(
-                            app_name=app_name,
-                            func=m,
-                            base_logger=base_logger,
-                        )
-                    )
-                else:
-                    raise ValueError(f"Invalid matcher: {type(m)}")
-        return _matchers
-
-    @staticmethod
-    def to_listener_middleware(
-        app_name: str,
-        middleware: Optional[List[Union[Callable, Middleware]]],
-        base_logger: Optional[Logger] = None,
-    ) -> List[Middleware]:
-        _middleware = []
-        if middleware is not None:
-            for m in middleware:
-                if isinstance(m, Middleware):
-                    _middleware.append(m)
-                elif isinstance(m, Callable):
-                    _middleware.append(
-                        CustomMiddleware(
-                            app_name=app_name,
-                            func=m,
-                            base_logger=base_logger,
-                        )
-                    )
-                else:
-                    raise ValueError(f"Invalid middleware: {type(m)}")
-        return _middleware
-
-

Steps from apps -Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details.

-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

This builder is supposed to be used as decorator.

-
my_step = WorkflowStep.builder("my_step")
-@my_step.edit
-def edit_my_step(ack, configure):
-    pass
-@my_step.save
-def save_my_step(ack, step, update):
-    pass
-@my_step.execute
-def execute_my_step(step, complete, fail):
-    pass
-app.step(my_step)
-
-

For further information about WorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
callback_id
-
The callback_id for the workflow
-
app_name
-
The application name mainly for logging
-
base_logger
-
The base logger
-
-

Class variables

-
-
var callback_id : str | Pattern
-
-

The type of the None singleton.

-
-
-

Static methods

-
-
-def to_listener_matchers(app_name: str,
matchers: List[ListenerMatcher | Callable[..., bool]] | None,
base_logger: logging.Logger | None = None) ‑> List[ListenerMatcher]
-
-
-
- -Expand source code - -
@staticmethod
-def to_listener_matchers(
-    app_name: str,
-    matchers: Optional[List[Union[Callable[..., bool], ListenerMatcher]]],
-    base_logger: Optional[Logger] = None,
-) -> List[ListenerMatcher]:
-    _matchers = []
-    if matchers is not None:
-        for m in matchers:
-            if isinstance(m, ListenerMatcher):
-                _matchers.append(m)
-            elif isinstance(m, Callable):
-                _matchers.append(
-                    CustomListenerMatcher(
-                        app_name=app_name,
-                        func=m,
-                        base_logger=base_logger,
-                    )
-                )
-            else:
-                raise ValueError(f"Invalid matcher: {type(m)}")
-    return _matchers
-
-
-
-
-def to_listener_middleware(app_name: str,
middleware: List[Callable | Middleware] | None,
base_logger: logging.Logger | None = None) ‑> List[Middleware]
-
-
-
- -Expand source code - -
@staticmethod
-def to_listener_middleware(
-    app_name: str,
-    middleware: Optional[List[Union[Callable, Middleware]]],
-    base_logger: Optional[Logger] = None,
-) -> List[Middleware]:
-    _middleware = []
-    if middleware is not None:
-        for m in middleware:
-            if isinstance(m, Middleware):
-                _middleware.append(m)
-            elif isinstance(m, Callable):
-                _middleware.append(
-                    CustomMiddleware(
-                        app_name=app_name,
-                        func=m,
-                        base_logger=base_logger,
-                    )
-                )
-            else:
-                raise ValueError(f"Invalid middleware: {type(m)}")
-    return _middleware
-
-
-
-
-

Methods

-
-
-def build(self, base_logger: logging.Logger | None = None) ‑> WorkflowStep -
-
-
- -Expand source code - -
def build(self, base_logger: Optional[Logger] = None) -> "WorkflowStep":
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Constructs a WorkflowStep object. This method may raise an exception
-    if the builder doesn't have enough configurations to build the object.
-
-    Returns:
-        WorkflowStep object
-    """
-    if self._edit is None:
-        raise BoltError("edit listener is not registered")
-    if self._save is None:
-        raise BoltError("save listener is not registered")
-    if self._execute is None:
-        raise BoltError("execute listener is not registered")
-
-    return WorkflowStep(
-        callback_id=self.callback_id,
-        edit=self._edit,
-        save=self._save,
-        execute=self._execute,
-        app_name=self.app_name,
-        base_logger=base_logger,
-    )
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Constructs a WorkflowStep object. This method may raise an exception -if the builder doesn't have enough configurations to build the object.

-

Returns

-

WorkflowStep object

-
-
-def edit(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def edit(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Registers a new edit listener with details.
-
-    You can use this method as decorator as well.
-
-        @my_step.edit
-        def edit_my_step(ack, configure):
-            pass
-
-    It's also possible to add additional listener matchers and/or middleware
-
-        @my_step.edit(matchers=[is_valid], middleware=[update_context])
-        def edit_my_step(ack, configure):
-            pass
-
-    For further information about WorkflowStep specific function arguments
-    such as `configure`, `update`, `complete`, and `fail`,
-    refer to `slack_bolt.workflows.step.utilities` API documents.
-
-    Args:
-        *args: This method can behave as either decorator or a method
-        matchers: Listener matchers
-        middleware: Listener middleware
-        lazy: Lazy listeners
-    """
-
-    if _is_used_without_argument(args):
-        func = args[0]
-        self._edit = self._to_listener("edit", func, matchers, middleware)
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._edit = self._to_listener("edit", functions, matchers, middleware)
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Registers a new edit listener with details.

-

You can use this method as decorator as well.

-
@my_step.edit
-def edit_my_step(ack, configure):
-    pass
-
-

It's also possible to add additional listener matchers and/or middleware

-
@my_step.edit(matchers=[is_valid], middleware=[update_context])
-def edit_my_step(ack, configure):
-    pass
-
-

For further information about WorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
*args
-
This method can behave as either decorator or a method
-
matchers
-
Listener matchers
-
middleware
-
Listener middleware
-
lazy
-
Lazy listeners
-
-
-
-def execute(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def execute(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Registers a new execute listener with details.
-
-    You can use this method as decorator as well.
-
-        @my_step.execute
-        def execute_my_step(step, complete, fail):
-            pass
-
-    It's also possible to add additional listener matchers and/or middleware
-
-        @my_step.save(matchers=[is_valid], middleware=[update_context])
-        def execute_my_step(step, complete, fail):
-            pass
-
-    For further information about WorkflowStep specific function arguments
-    such as `configure`, `update`, `complete`, and `fail`,
-    refer to `slack_bolt.workflows.step.utilities` API documents.
-
-    Args:
-        *args: This method can behave as either decorator or a method
-        matchers: Listener matchers
-        middleware: Listener middleware
-        lazy: Lazy listeners
-    """
-    if _is_used_without_argument(args):
-        func = args[0]
-        self._execute = self._to_listener("execute", func, matchers, middleware)
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._execute = self._to_listener("execute", functions, matchers, middleware)
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Registers a new execute listener with details.

-

You can use this method as decorator as well.

-
@my_step.execute
-def execute_my_step(step, complete, fail):
-    pass
-
-

It's also possible to add additional listener matchers and/or middleware

-
@my_step.save(matchers=[is_valid], middleware=[update_context])
-def execute_my_step(step, complete, fail):
-    pass
-
-

For further information about WorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
*args
-
This method can behave as either decorator or a method
-
matchers
-
Listener matchers
-
middleware
-
Listener middleware
-
lazy
-
Lazy listeners
-
-
-
-def save(self,
*args,
matchers: Callable[..., bool] | ListenerMatcher | None = None,
middleware: Callable | Middleware | None = None,
lazy: List[Callable[..., None]] | None = None)
-
-
-
- -Expand source code - -
def save(
-    self,
-    *args,
-    matchers: Optional[Union[Callable[..., bool], ListenerMatcher]] = None,
-    middleware: Optional[Union[Callable, Middleware]] = None,
-    lazy: Optional[List[Callable[..., None]]] = None,
-):
-    """
-    Deprecated:
-        Steps from apps for legacy workflows are now deprecated.
-        Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/
-
-    Registers a new save listener with details.
-
-    You can use this method as decorator as well.
-
-        @my_step.save
-        def save_my_step(ack, step, update):
-            pass
-
-    It's also possible to add additional listener matchers and/or middleware
-
-        @my_step.save(matchers=[is_valid], middleware=[update_context])
-        def save_my_step(ack, step, update):
-            pass
-
-    For further information about WorkflowStep specific function arguments
-    such as `configure`, `update`, `complete`, and `fail`,
-    refer to `slack_bolt.workflows.step.utilities` API documents.
-
-    Args:
-        *args: This method can behave as either decorator or a method
-        matchers: Listener matchers
-        middleware: Listener middleware
-        lazy: Lazy listeners
-    """
-    if _is_used_without_argument(args):
-        func = args[0]
-        self._save = self._to_listener("save", func, matchers, middleware)
-        return func
-
-    def _inner(func):
-        functions = [func] + (lazy if lazy is not None else [])
-        self._save = self._to_listener("save", functions, matchers, middleware)
-
-        @wraps(func)
-        def _wrapper(*args, **kwargs):
-            return func(*args, **kwargs)
-
-        return _wrapper
-
-    return _inner
-
-

Deprecated

-

Steps from apps for legacy workflows are now deprecated. -Use new custom steps: https://docs.slack.dev/workflows/workflow-steps/

-

Registers a new save listener with details.

-

You can use this method as decorator as well.

-
@my_step.save
-def save_my_step(ack, step, update):
-    pass
-
-

It's also possible to add additional listener matchers and/or middleware

-
@my_step.save(matchers=[is_valid], middleware=[update_context])
-def save_my_step(ack, step, update):
-    pass
-
-

For further information about WorkflowStep specific function arguments -such as configure, update, complete, and fail, -refer to slack_bolt.workflows.step.utilities API documents.

-

Args

-
-
*args
-
This method can behave as either decorator or a method
-
matchers
-
Listener matchers
-
middleware
-
Listener middleware
-
lazy
-
Lazy listeners
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/step_middleware.html b/docs/reference/workflows/step/step_middleware.html deleted file mode 100644 index 2ac62dd93..000000000 --- a/docs/reference/workflows/step/step_middleware.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - -slack_bolt.workflows.step.step_middleware API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.step_middleware

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class WorkflowStepMiddleware -(step: WorkflowStep) -
-
-
- -Expand source code - -
class WorkflowStepMiddleware(Middleware):
-    """Base middleware for step from app specific ones"""
-
-    def __init__(self, step: WorkflowStep):
-        self.step = step
-
-    def process(
-        self,
-        *,
-        req: BoltRequest,
-        resp: BoltResponse,
-        # As this method is not supposed to be invoked by bolt-python users,
-        # the naming conflict with the built-in one affects
-        # only the internals of this method
-        next: Callable[[], BoltResponse],
-    ) -> Optional[BoltResponse]:
-
-        if self.step.edit.matches(req=req, resp=resp):
-            resp = self._run(self.step.edit, req, resp)
-            if resp is not None:
-                return resp
-        elif self.step.save.matches(req=req, resp=resp):
-            resp = self._run(self.step.save, req, resp)
-            if resp is not None:
-                return resp
-        elif self.step.execute.matches(req=req, resp=resp):
-            resp = self._run(self.step.execute, req, resp)
-            if resp is not None:
-                return resp
-
-        return next()
-
-    @staticmethod
-    def _run(
-        listener: Listener,
-        req: BoltRequest,
-        resp: BoltResponse,
-    ) -> Optional[BoltResponse]:
-        resp, next_was_not_called = listener.run_middleware(req=req, resp=resp)
-        if next_was_not_called:
-            return None
-
-        return req.context.listener_runner.run(
-            request=req,
-            response=resp,
-            listener_name=get_name_for_callable(listener.ack_function),
-            listener=listener,
-        )
-
-

Base middleware for step from app specific ones

-

Ancestors

- -

Inherited members

- -
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/utilities/async_complete.html b/docs/reference/workflows/step/utilities/async_complete.html deleted file mode 100644 index 8e95cc267..000000000 --- a/docs/reference/workflows/step/utilities/async_complete.html +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - -slack_bolt.workflows.step.utilities.async_complete API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.utilities.async_complete

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncComplete -(*, client: slack_sdk.web.async_client.AsyncWebClient, body: dict) -
-
-
- -Expand source code - -
class AsyncComplete:
-    """`complete()` utility to tell Slack the completion of a step from app execution.
-
-        async def execute(step, complete, fail):
-            inputs = step["inputs"]
-            # if everything was successful
-            outputs = {
-                "task_name": inputs["task_name"]["value"],
-                "task_description": inputs["task_description"]["value"],
-            }
-            await complete(outputs=outputs)
-
-        ws = AsyncWorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        app.step(ws)
-
-    This utility is a thin wrapper of workflows.stepCompleted API method.
-    Refer to https://api.slack.com/methods/workflows.stepCompleted for details.
-    """
-
-    def __init__(self, *, client: AsyncWebClient, body: dict):
-        self.client = client
-        self.body = body
-
-    async def __call__(self, **kwargs) -> None:
-        await self.client.workflows_stepCompleted(
-            workflow_step_execute_id=self.body["event"]["workflow_step"]["workflow_step_execute_id"],
-            **kwargs,
-        )
-
-

complete() utility to tell Slack the completion of a step from app execution.

-
async def execute(step, complete, fail):
-    inputs = step["inputs"]
-    # if everything was successful
-    outputs = {
-        "task_name": inputs["task_name"]["value"],
-        "task_description": inputs["task_description"]["value"],
-    }
-    await complete(outputs=outputs)
-
-ws = AsyncWorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-app.step(ws)
-
-

This utility is a thin wrapper of workflows.stepCompleted API method. -Refer to https://api.slack.com/methods/workflows.stepCompleted for details.

-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/utilities/async_configure.html b/docs/reference/workflows/step/utilities/async_configure.html deleted file mode 100644 index 10f236c47..000000000 --- a/docs/reference/workflows/step/utilities/async_configure.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - -slack_bolt.workflows.step.utilities.async_configure API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.utilities.async_configure

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncConfigure -(*,
callback_id: str,
client: slack_sdk.web.async_client.AsyncWebClient,
body: dict)
-
-
-
- -Expand source code - -
class AsyncConfigure:
-    """`configure()` utility to send the modal view in Workflow Builder.
-
-        async def edit(ack, step, configure):
-            await ack()
-
-            blocks = [
-                {
-                    "type": "input",
-                    "block_id": "task_name_input",
-                    "element": {
-                        "type": "plain_text_input",
-                        "action_id": "name",
-                        "placeholder": {"type": "plain_text", "text": "Add a task name"},
-                    },
-                    "label": {"type": "plain_text", "text": "Task name"},
-                },
-            ]
-            await configure(blocks=blocks)
-
-        ws = AsyncWorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        app.step(ws)
-
-    Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details.
-    """
-
-    def __init__(self, *, callback_id: str, client: AsyncWebClient, body: dict):
-        self.callback_id = callback_id
-        self.client = client
-        self.body = body
-
-    async def __call__(
-        self,
-        *,
-        blocks: Optional[Sequence[Union[dict, Block]]] = None,
-    ) -> None:
-        await self.client.views_open(
-            trigger_id=self.body["trigger_id"],
-            view={
-                "type": "workflow_step",
-                "callback_id": self.callback_id,
-                "blocks": blocks,
-            },
-        )
-
-

configure() utility to send the modal view in Workflow Builder.

-
async def edit(ack, step, configure):
-    await ack()
-
-    blocks = [
-        {
-            "type": "input",
-            "block_id": "task_name_input",
-            "element": {
-                "type": "plain_text_input",
-                "action_id": "name",
-                "placeholder": {"type": "plain_text", "text": "Add a task name"},
-            },
-            "label": {"type": "plain_text", "text": "Task name"},
-        },
-    ]
-    await configure(blocks=blocks)
-
-ws = AsyncWorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-app.step(ws)
-
-

Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details.

-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/utilities/async_fail.html b/docs/reference/workflows/step/utilities/async_fail.html deleted file mode 100644 index b27c36251..000000000 --- a/docs/reference/workflows/step/utilities/async_fail.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - -slack_bolt.workflows.step.utilities.async_fail API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.utilities.async_fail

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncFail -(*, client: slack_sdk.web.async_client.AsyncWebClient, body: dict) -
-
-
- -Expand source code - -
class AsyncFail:
-    """`fail()` utility to tell Slack the execution failure of a step from app.
-
-        async def execute(step, complete, fail):
-            inputs = step["inputs"]
-            # if something went wrong
-            error = {"message": "Just testing step failure!"}
-            await fail(error=error)
-
-        ws = AsyncWorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        app.step(ws)
-
-    This utility is a thin wrapper of workflows.stepFailed API method.
-    Refer to https://api.slack.com/methods/workflows.stepFailed for details.
-    """
-
-    def __init__(self, *, client: AsyncWebClient, body: dict):
-        self.client = client
-        self.body = body
-
-    async def __call__(
-        self,
-        *,
-        error: dict,
-    ) -> None:
-        await self.client.workflows_stepFailed(
-            workflow_step_execute_id=self.body["event"]["workflow_step"]["workflow_step_execute_id"],
-            error=error,
-        )
-
-

fail() utility to tell Slack the execution failure of a step from app.

-
async def execute(step, complete, fail):
-    inputs = step["inputs"]
-    # if something went wrong
-    error = {"message": "Just testing step failure!"}
-    await fail(error=error)
-
-ws = AsyncWorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-app.step(ws)
-
-

This utility is a thin wrapper of workflows.stepFailed API method. -Refer to https://api.slack.com/methods/workflows.stepFailed for details.

-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/utilities/async_update.html b/docs/reference/workflows/step/utilities/async_update.html deleted file mode 100644 index bfb210fc3..000000000 --- a/docs/reference/workflows/step/utilities/async_update.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - -slack_bolt.workflows.step.utilities.async_update API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.utilities.async_update

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class AsyncUpdate -(*, client: slack_sdk.web.async_client.AsyncWebClient, body: dict) -
-
-
- -Expand source code - -
class AsyncUpdate:
-    """`update()` utility to tell Slack the processing results of a `save` listener.
-
-        async def save(ack, view, update):
-            await ack()
-
-            values = view["state"]["values"]
-            task_name = values["task_name_input"]["name"]
-            task_description = values["task_description_input"]["description"]
-
-            inputs = {
-                "task_name": {"value": task_name["value"]},
-                "task_description": {"value": task_description["value"]}
-            }
-            outputs = [
-                {
-                    "type": "text",
-                    "name": "task_name",
-                    "label": "Task name",
-                },
-                {
-                    "type": "text",
-                    "name": "task_description",
-                    "label": "Task description",
-                }
-            ]
-            await update(inputs=inputs, outputs=outputs)
-
-        ws = AsyncWorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        app.step(ws)
-
-    This utility is a thin wrapper of workflows.stepFailed API method.
-    Refer to https://api.slack.com/methods/workflows.updateStep for details.
-    """
-
-    def __init__(self, *, client: AsyncWebClient, body: dict):
-        self.client = client
-        self.body = body
-
-    async def __call__(self, **kwargs) -> None:
-        await self.client.workflows_updateStep(
-            workflow_step_edit_id=self.body["workflow_step"]["workflow_step_edit_id"],
-            **kwargs,
-        )
-
-

update() utility to tell Slack the processing results of a save listener.

-
async def save(ack, view, update):
-    await ack()
-
-    values = view["state"]["values"]
-    task_name = values["task_name_input"]["name"]
-    task_description = values["task_description_input"]["description"]
-
-    inputs = {
-        "task_name": {"value": task_name["value"]},
-        "task_description": {"value": task_description["value"]}
-    }
-    outputs = [
-        {
-            "type": "text",
-            "name": "task_name",
-            "label": "Task name",
-        },
-        {
-            "type": "text",
-            "name": "task_description",
-            "label": "Task description",
-        }
-    ]
-    await update(inputs=inputs, outputs=outputs)
-
-ws = AsyncWorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-app.step(ws)
-
-

This utility is a thin wrapper of workflows.stepFailed API method. -Refer to https://api.slack.com/methods/workflows.updateStep for details.

-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/utilities/complete.html b/docs/reference/workflows/step/utilities/complete.html deleted file mode 100644 index f1cf11f56..000000000 --- a/docs/reference/workflows/step/utilities/complete.html +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - -slack_bolt.workflows.step.utilities.complete API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.utilities.complete

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Complete -(*, client: slack_sdk.web.client.WebClient, body: dict) -
-
-
- -Expand source code - -
class Complete:
-    """`complete()` utility to tell Slack the completion of a step from app execution.
-
-        def execute(step, complete, fail):
-            inputs = step["inputs"]
-            # if everything was successful
-            outputs = {
-                "task_name": inputs["task_name"]["value"],
-                "task_description": inputs["task_description"]["value"],
-            }
-            complete(outputs=outputs)
-
-        ws = WorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        app.step(ws)
-
-    This utility is a thin wrapper of workflows.stepCompleted API method.
-    Refer to https://api.slack.com/methods/workflows.stepCompleted for details.
-    """
-
-    def __init__(self, *, client: WebClient, body: dict):
-        self.client = client
-        self.body = body
-
-    def __call__(self, **kwargs) -> None:
-        self.client.workflows_stepCompleted(
-            workflow_step_execute_id=self.body["event"]["workflow_step"]["workflow_step_execute_id"],
-            **kwargs,
-        )
-
-

complete() utility to tell Slack the completion of a step from app execution.

-
def execute(step, complete, fail):
-    inputs = step["inputs"]
-    # if everything was successful
-    outputs = {
-        "task_name": inputs["task_name"]["value"],
-        "task_description": inputs["task_description"]["value"],
-    }
-    complete(outputs=outputs)
-
-ws = WorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-app.step(ws)
-
-

This utility is a thin wrapper of workflows.stepCompleted API method. -Refer to https://api.slack.com/methods/workflows.stepCompleted for details.

-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/utilities/configure.html b/docs/reference/workflows/step/utilities/configure.html deleted file mode 100644 index 258bce312..000000000 --- a/docs/reference/workflows/step/utilities/configure.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - -slack_bolt.workflows.step.utilities.configure API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.utilities.configure

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Configure -(*, callback_id: str, client: slack_sdk.web.client.WebClient, body: dict) -
-
-
- -Expand source code - -
class Configure:
-    """`configure()` utility to send the modal view in Workflow Builder.
-
-        def edit(ack, step, configure):
-            ack()
-
-            blocks = [
-                {
-                    "type": "input",
-                    "block_id": "task_name_input",
-                    "element": {
-                        "type": "plain_text_input",
-                        "action_id": "name",
-                        "placeholder": {"type": "plain_text", "text": "Add a task name"},
-                    },
-                    "label": {"type": "plain_text", "text": "Task name"},
-                },
-            ]
-            configure(blocks=blocks)
-
-        ws = WorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        app.step(ws)
-
-    Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details.
-    """
-
-    def __init__(self, *, callback_id: str, client: WebClient, body: dict):
-        self.callback_id = callback_id
-        self.client = client
-        self.body = body
-
-    def __call__(self, *, blocks: Optional[Sequence[Union[dict, Block]]] = None, **kwargs) -> None:
-        self.client.views_open(
-            trigger_id=self.body["trigger_id"],
-            view={
-                "type": "workflow_step",
-                "callback_id": self.callback_id,
-                "blocks": blocks,
-                **kwargs,
-            },
-        )
-
-

configure() utility to send the modal view in Workflow Builder.

-
def edit(ack, step, configure):
-    ack()
-
-    blocks = [
-        {
-            "type": "input",
-            "block_id": "task_name_input",
-            "element": {
-                "type": "plain_text_input",
-                "action_id": "name",
-                "placeholder": {"type": "plain_text", "text": "Add a task name"},
-            },
-            "label": {"type": "plain_text", "text": "Task name"},
-        },
-    ]
-    configure(blocks=blocks)
-
-ws = WorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-app.step(ws)
-
-

Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details.

-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/utilities/fail.html b/docs/reference/workflows/step/utilities/fail.html deleted file mode 100644 index 00d0be83d..000000000 --- a/docs/reference/workflows/step/utilities/fail.html +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - -slack_bolt.workflows.step.utilities.fail API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.utilities.fail

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Fail -(*, client: slack_sdk.web.client.WebClient, body: dict) -
-
-
- -Expand source code - -
class Fail:
-    """`fail()` utility to tell Slack the execution failure of a step from app.
-
-        def execute(step, complete, fail):
-            inputs = step["inputs"]
-            # if something went wrong
-            error = {"message": "Just testing step failure!"}
-            fail(error=error)
-
-        ws = WorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        app.step(ws)
-
-    This utility is a thin wrapper of workflows.stepFailed API method.
-    Refer to https://api.slack.com/methods/workflows.stepFailed for details.
-    """
-
-    def __init__(self, *, client: WebClient, body: dict):
-        self.client = client
-        self.body = body
-
-    def __call__(
-        self,
-        *,
-        error: dict,
-    ) -> None:
-        self.client.workflows_stepFailed(
-            workflow_step_execute_id=self.body["event"]["workflow_step"]["workflow_step_execute_id"],
-            error=error,
-        )
-
-

fail() utility to tell Slack the execution failure of a step from app.

-
def execute(step, complete, fail):
-    inputs = step["inputs"]
-    # if something went wrong
-    error = {"message": "Just testing step failure!"}
-    fail(error=error)
-
-ws = WorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-app.step(ws)
-
-

This utility is a thin wrapper of workflows.stepFailed API method. -Refer to https://api.slack.com/methods/workflows.stepFailed for details.

-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/utilities/index.html b/docs/reference/workflows/step/utilities/index.html deleted file mode 100644 index 54261ea96..000000000 --- a/docs/reference/workflows/step/utilities/index.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - - - -slack_bolt.workflows.step.utilities API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.utilities

-
-
-

Utilities specific to steps from apps.

-

In steps from apps listeners, you can use a few specific listener/middleware arguments.

-

edit listener

- -

save listener

- -

execute listener

- -

For asyncio-based apps, refer to the corresponding async prefixed ones.

-
-
-

Sub-modules

-
-
slack_bolt.workflows.step.utilities.async_complete
-
-
-
-
slack_bolt.workflows.step.utilities.async_configure
-
-
-
-
slack_bolt.workflows.step.utilities.async_fail
-
-
-
-
slack_bolt.workflows.step.utilities.async_update
-
-
-
-
slack_bolt.workflows.step.utilities.complete
-
-
-
-
slack_bolt.workflows.step.utilities.configure
-
-
-
-
slack_bolt.workflows.step.utilities.fail
-
-
-
-
slack_bolt.workflows.step.utilities.update
-
-
-
-
-
-
-
-
-
-
-
-
- -
- - - diff --git a/docs/reference/workflows/step/utilities/update.html b/docs/reference/workflows/step/utilities/update.html deleted file mode 100644 index 9899448f9..000000000 --- a/docs/reference/workflows/step/utilities/update.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - -slack_bolt.workflows.step.utilities.update API documentation - - - - - - - - - - - -
-
-
-

Module slack_bolt.workflows.step.utilities.update

-
-
-
-
-
-
-
-
-
-
-

Classes

-
-
-class Update -(*, client: slack_sdk.web.client.WebClient, body: dict) -
-
-
- -Expand source code - -
class Update:
-    """`update()` utility to tell Slack the processing results of a `save` listener.
-
-        def save(ack, view, update):
-            ack()
-
-            values = view["state"]["values"]
-            task_name = values["task_name_input"]["name"]
-            task_description = values["task_description_input"]["description"]
-
-            inputs = {
-                "task_name": {"value": task_name["value"]},
-                "task_description": {"value": task_description["value"]}
-            }
-            outputs = [
-                {
-                    "type": "text",
-                    "name": "task_name",
-                    "label": "Task name",
-                },
-                {
-                    "type": "text",
-                    "name": "task_description",
-                    "label": "Task description",
-                }
-            ]
-            update(inputs=inputs, outputs=outputs)
-
-        ws = WorkflowStep(
-            callback_id="add_task",
-            edit=edit,
-            save=save,
-            execute=execute,
-        )
-        app.step(ws)
-
-    This utility is a thin wrapper of workflows.stepFailed API method.
-    Refer to https://api.slack.com/methods/workflows.updateStep for details.
-    """
-
-    def __init__(self, *, client: WebClient, body: dict):
-        self.client = client
-        self.body = body
-
-    def __call__(self, **kwargs) -> None:
-        self.client.workflows_updateStep(
-            workflow_step_edit_id=self.body["workflow_step"]["workflow_step_edit_id"],
-            **kwargs,
-        )
-
-

update() utility to tell Slack the processing results of a save listener.

-
def save(ack, view, update):
-    ack()
-
-    values = view["state"]["values"]
-    task_name = values["task_name_input"]["name"]
-    task_description = values["task_description_input"]["description"]
-
-    inputs = {
-        "task_name": {"value": task_name["value"]},
-        "task_description": {"value": task_description["value"]}
-    }
-    outputs = [
-        {
-            "type": "text",
-            "name": "task_name",
-            "label": "Task name",
-        },
-        {
-            "type": "text",
-            "name": "task_description",
-            "label": "Task description",
-        }
-    ]
-    update(inputs=inputs, outputs=outputs)
-
-ws = WorkflowStep(
-    callback_id="add_task",
-    edit=edit,
-    save=save,
-    execute=execute,
-)
-app.step(ws)
-
-

This utility is a thin wrapper of workflows.stepFailed API method. -Refer to https://api.slack.com/methods/workflows.updateStep for details.

-
-
-
-
- -
- - - diff --git a/scripts/generate_api_docs.py b/scripts/generate_api_docs.py new file mode 100644 index 000000000..25e266ef6 --- /dev/null +++ b/scripts/generate_api_docs.py @@ -0,0 +1,640 @@ +#!/usr/bin/env python +"""Generate the Markdown API reference for slack_bolt using griffe. + +Invoked by scripts/generate_api_docs.sh. griffe (the parser behind +mkdocstrings) is used purely as the extraction engine: it loads the package, +resolves re-export aliases to their concrete definition, and parses Google-style +docstrings into structured sections. This module renders that structured data +into the Docusaurus-flavored Markdown tree the docs site imports. + +The output layout (flattened under ``reference/``, package overviews as +``index.md``, an import-ready ``sidebar.json``) is produced directly rather than +rendered and then rewritten. +""" + +import json +import os +import re +import shutil + +import griffe + +REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +# The API reference lives under the English docs tree. DOCS_BASE_PATH is the +# directory Docusaurus doc IDs are relative to; the reference is written to +# DOCS_BASE_PATH/REFERENCE_SUBDIR. +DOCS_BASE_PATH = os.path.join(REPO_ROOT, "docs", "english") +REFERENCE_SUBDIR = "reference" + +# The docs site (docs.slack.dev) imports the generated sidebar.json into its +# sidebars.js and appends it under "Bolt for Python". Its doc IDs resolve +# relative to the docs root there, hence the prefix. +SIDEBAR_DOC_ID_PREFIX = "tools/bolt-python/" + +# Signatures longer than this render one parameter per line. +MAX_SIGNATURE_WIDTH = 88 + +PACKAGE = "slack_bolt" + + +# --------------------------------------------------------------------------- # +# MDX escaping +# --------------------------------------------------------------------------- # + +# Docusaurus v3 parses every .md file as MDX: a bare ``<`` reads as JSX and a +# bare ``{`` as a JS expression, either of which aborts the docs build. Escape +# those two characters in prose while leaving fenced blocks and inline code +# spans untouched. +_CODE_SPLIT_RE = re.compile(r"(```[\s\S]*?```|`[^`]*`)") + + +def _escape_mdx(text): + """Escape MDX-hazardous characters outside code spans and fenced blocks.""" + out = [] + for i, chunk in enumerate(_CODE_SPLIT_RE.split(text)): + # Odd indices are the captured code spans/blocks -- leave them verbatim. + if i % 2 == 1: + out.append(chunk) + else: + out.append(chunk.replace("<", "<").replace("{", "{")) + return "".join(out) + + +def _escape_header(name): + """Escape a name for use in a Markdown header (underscores/asterisks).""" + return name.replace("_", "\\_").replace("*", "\\*") + + +# --------------------------------------------------------------------------- # +# Signatures +# --------------------------------------------------------------------------- # + +_VAR_POSITIONAL = "variadic positional" +_VAR_KEYWORD = "variadic keyword" +_POSITIONAL_ONLY = "positional-only" +_KEYWORD_ONLY = "keyword-only" + + +def _parameter_source(param): + """Render a single parameter as Python source (``name: type = default``).""" + if param.kind.value == _VAR_POSITIONAL: + text = "*" + param.name + elif param.kind.value == _VAR_KEYWORD: + text = "**" + param.name + else: + text = param.name + + annotation = str(param.annotation) if param.annotation is not None else None + default = str(param.default) if param.default is not None else None + if annotation: + text += ": " + annotation + if default is not None and param.kind.value not in (_VAR_POSITIONAL, _VAR_KEYWORD): + text += " = " + default if annotation else "=" + default + return text + + +def _parameter_list(func, drop_first_self): + """Build the ordered parameter fragments for a function, inserting the + ``/`` (positional-only) and bare ``*`` (keyword-only) separators the way + ``inspect.Signature`` does.""" + params = list(func.parameters) + if drop_first_self and params and params[0].name in ("self", "cls"): + params = params[1:] + + fragments = [] + render_pos_only_sep = False + render_kw_only_sep = True + for param in params: + kind = param.kind.value + if kind == _POSITIONAL_ONLY: + render_pos_only_sep = True + elif render_pos_only_sep: + fragments.append("/") + render_pos_only_sep = False + + if kind == _VAR_POSITIONAL: + render_kw_only_sep = False + elif kind == _KEYWORD_ONLY and render_kw_only_sep: + fragments.append("*") + render_kw_only_sep = False + + fragments.append(_parameter_source(param)) + + if render_pos_only_sep: + fragments.append("/") + return fragments + + +def _format_function_signature(func, name, is_method): + """Render a ``def``/``async def`` signature, wrapping long ones one + parameter per line.""" + prefix = "async def " if "async" in (func.labels or set()) else "def " + fragments = _parameter_list(func, drop_first_self=is_method) + returns = " -> {}".format(func.returns) if func.returns is not None else "" + + one_line = "{}{}({}){}".format(prefix, name, ", ".join(fragments), returns) + if len(one_line) <= MAX_SIGNATURE_WIDTH: + return one_line + + inner = ",\n".join(" " + fragment for fragment in fragments) + return "{}{}(\n{}){}".format(prefix, name, inner, returns) + + +def _format_classdef_signature(cls): + """Render a ``class Name(bases)`` signature.""" + bases = ", ".join(str(base) for base in cls.bases) + return "class {}({})".format(cls.name, bases) + + +def _property_signature(attr): + """Render a property as a ``@property``-decorated getter.""" + returns = " -> {}".format(attr.annotation) if attr.annotation is not None else "" + return "@property\ndef {}(){}".format(attr.name, returns) + + +# --------------------------------------------------------------------------- # +# Docstrings +# --------------------------------------------------------------------------- # + + +def _reflow_indented_code(text): + """Convert Markdown indented code blocks (4-space, RST literal-block style + used in many docstrings) into fenced ``python`` blocks. + + A bare indented block renders without syntax highlighting and, worse, its + ``#`` comment lines can be misread as headers by some Markdown/MDX + processors. Re-emitting the block fenced removes both problems and lets + _escape_mdx leave the code verbatim. Only blocks preceded by a blank line + are treated as code, matching CommonMark (an indented run cannot interrupt + a paragraph).""" + lines = text.split("\n") + out = [] + i = 0 + prev_blank = True # start of a section counts as a preceding blank line + fence_open = False + while i < len(lines): + line = lines[i] + # Never touch content inside an existing fenced block; just mirror it. + if line.strip().startswith("```"): + fence_open = not fence_open + out.append(line) + prev_blank = False + i += 1 + continue + if fence_open: + out.append(line) + prev_blank = False + i += 1 + continue + if prev_blank and line.startswith(" ") and line.strip(): + block = [] + while i < len(lines) and (lines[i].startswith(" ") or not lines[i].strip()): + if lines[i].strip().startswith("```"): + break + block.append(lines[i]) + i += 1 + while block and not block[-1].strip(): + block.pop() + out.append("```python") + out.extend(bl[4:] if bl.startswith(" ") else bl for bl in block) + out.append("```") + out.append("") + prev_blank = True + continue + out.append(line) + prev_blank = not line.strip() + i += 1 + return "\n".join(out) + + +def _indent_continuation(text): + """Indent wrapped continuation lines of a list item by two spaces.""" + return _escape_mdx(text).replace("\n", "\n ") + + +def _render_docstring(obj, out): + """Append an object's docstring, section by section, to ``out``.""" + if not obj.docstring: + return + for section in obj.docstring.parsed: + kind = section.kind.value + if kind == "text": + out.append(_escape_mdx(_reflow_indented_code(section.value))) + out.append("") + elif kind == "parameters": + out.append("**Arguments**:") + out.append("") + for param in section.value: + typ = " _{}_".format(param.annotation) if param.annotation else "" + if param.description: + out.append("- `{}`{} - {}".format(param.name, typ, _indent_continuation(param.description))) + else: + out.append("- `{}`{}".format(param.name, typ)) + out.append("") + elif kind == "returns": + out.append("**Returns**:") + out.append("") + for ret in section.value: + bits = [] + if ret.annotation: + bits.append("`{}`".format(ret.annotation)) + if ret.description: + bits.append(_indent_continuation(ret.description)) + out.append("- " + " - ".join(bits)) + out.append("") + elif kind == "raises": + out.append("**Raises**:") + out.append("") + for exc in section.value: + typ = "`{}`".format(exc.annotation) if exc.annotation else "" + if exc.description: + out.append("- {} - {}".format(typ, _indent_continuation(exc.description))) + else: + out.append("- {}".format(typ)) + out.append("") + elif kind == "admonition": + label = (section.value.kind or "note").replace("-", " ").title() + out.append("**{}**:".format(label)) + out.append("") + out.append(_escape_mdx(_reflow_indented_code(section.value.contents))) + out.append("") + else: + # Unknown/rare section (examples, yields, ...): render its text form. + contents = str(getattr(section.value, "contents", section.value)) + out.append(_escape_mdx(_reflow_indented_code(contents))) + out.append("") + + +# --------------------------------------------------------------------------- # +# Member selection (with re-export inlining) +# --------------------------------------------------------------------------- # + + +def _is_public(name): + """Keep public names plus ``__init__`` (constructors carry the class's + ``Args:``); drop every other dunder/private name.""" + return name == "__init__" or not name.startswith("_") + + +def _inlined_export_target(alias): + """If *alias* re-exports a concrete slack_bolt class/function, return it.""" + try: + target = alias.target + except Exception: + return None + if target.canonical_path.startswith(PACKAGE + ".") and target.kind.value in ("class", "function"): + return target + return None + + +def _documented_members(parent): + """Yield ``(display_name, object)`` pairs to document under *parent*. + + Submodules are skipped (they become their own files). Aliases are inlined + only when they are declared in the module's ``__all__`` and resolve to a + concrete slack_bolt class/function, so genuine public re-exports render + inline while incidental imports do not.""" + exports = set(parent.exports or []) if parent.is_module else set() + members = [] + for name, member in parent.members.items(): + if member.is_alias: + if name in exports: + target = _inlined_export_target(member) + if target is not None: + members.append((name, target)) + continue + if member.is_module: + continue + if not _is_public(name): + continue + # Drop undocumented instance attributes (bare ``self.x = x`` assignments + # with neither a type annotation nor a docstring) -- they are + # implementation detail. Class- and module-level constants are kept. + labels = member.labels or set() + if member.kind.value == "attribute" and labels == {"instance-attribute"}: + if member.annotation is None and not member.docstring: + continue + members.append((name, member)) + return members + + +# --------------------------------------------------------------------------- # +# Object rendering +# --------------------------------------------------------------------------- # + + +def _render_object(display_name, obj, out): + """Append the Markdown for a single class/function/attribute to ``out``.""" + kind = obj.kind.value + + if kind == "class": + out.append("## {} Objects".format(_escape_header(obj.name))) + out.append("") + out.append("```python") + out.append(_format_classdef_signature(obj)) + out.append("```") + out.append("") + _render_docstring(obj, out) + for child_name, child in _documented_members(obj): + _render_object(child_name, child, out) + return + + if kind == "function": + is_method = obj.parent is not None and obj.parent.kind.value == "class" + out.append("#### {}".format(_escape_header(display_name))) + out.append("") + out.append("```python") + out.append(_format_function_signature(obj, display_name, is_method)) + out.append("```") + out.append("") + _render_docstring(obj, out) + return + + # Attribute -- a property renders as a getter, a plain variable as a header + # carrying its type hint (no value block). + if "property" in (obj.labels or set()): + out.append("#### {}".format(_escape_header(display_name))) + out.append("") + out.append("```python") + out.append(_property_signature(obj)) + out.append("```") + out.append("") + elif obj.annotation is not None: + out.append("#### {}: `{}`".format(_escape_header(display_name), obj.annotation)) + out.append("") + else: + out.append("#### {}".format(_escape_header(display_name))) + out.append("") + _render_docstring(obj, out) + + +# --------------------------------------------------------------------------- # +# Module -> page +# --------------------------------------------------------------------------- # + + +def _relative_path(module): + """Path of *module* relative to the top package (``""`` for slack_bolt).""" + if module.name == PACKAGE: + return "" + return module.canonical_path.split(".", 1)[1].replace(".", "/") + + +def _iter_modules(module): + """Yield *module* and every submodule, depth-first in source order.""" + yield module + for member in module.members.values(): + if not member.is_alias and member.is_module: + yield from _iter_modules(member) + + +def _module_docstring(module): + """Render a module's own docstring (the package/module overview), if any.""" + out = [] + _render_docstring(module, out) + return "\n".join(out).rstrip("\n") + + +def _render_body(module): + """Render a module's members (the module docstring is rendered separately + at the top of the page).""" + out = [] + for name, obj in _documented_members(module): + _render_object(name, obj, out) + return "\n".join(out).rstrip("\n") + "\n" if out else "" + + +# --------------------------------------------------------------------------- # +# Routes and the sidebar +# --------------------------------------------------------------------------- # + + +def _doc_id(rel_path, is_package): + """Docs-root doc ID for a module, e.g. ``reference/app/app`` or the package + overview ``reference/app/index``.""" + if not rel_path: + base = REFERENCE_SUBDIR + "/index" + elif is_package: + base = "{}/{}/index".format(REFERENCE_SUBDIR, rel_path) + else: + base = "{}/{}".format(REFERENCE_SUBDIR, rel_path) + return SIDEBAR_DOC_ID_PREFIX + base + + +def _doc_route(doc_id): + """Absolute Docusaurus route for a doc ID (``.../index`` served at folder).""" + route = "/" + doc_id + if route.endswith("/index"): + route = route[: -len("/index")] + return route + + +# --------------------------------------------------------------------------- # +# Generation +# --------------------------------------------------------------------------- # + + +def _load_package(): + return griffe.load( + PACKAGE, + search_paths=[REPO_ROOT], + docstring_parser=griffe.Parser.google, + ) + + +def _build_pages(root): + """Render every module into an in-memory page record.""" + pages = {} + for module in _iter_modules(root): + rel_path = _relative_path(module) + is_package = os.path.basename(str(module.filepath)) == "__init__.py" + dotted = module.canonical_path + # Sidebar labels use the bare final component (e.g. "error", "app"); + # the dotted path lives in the page title instead. + sidebar_label = dotted.rsplit(".", 1)[-1] + pages[rel_path] = { + "module": module, + "is_package": is_package, + "title": dotted, + "sidebar_label": sidebar_label, + "doc_id": _doc_id(rel_path, is_package), + "docstring": _module_docstring(module), + "body": _render_body(module), + } + return pages + + +def _submodule_links(rel_path, pages): + """Sorted child module/subpackage links for a package overview page.""" + prefix = rel_path + "/" if rel_path else "" + depth = prefix.count("/") + children = [] + for other_rel, page in pages.items(): + if not other_rel or not other_rel.startswith(prefix): + continue + if other_rel.count("/") != depth: + continue + children.append((page["title"], _doc_route(page["doc_id"]))) + children.sort() + return children + + +def _write_pages(pages): + reference_dir = os.path.join(DOCS_BASE_PATH, REFERENCE_SUBDIR) + for rel_path, page in pages.items(): + if page["is_package"] or not rel_path: + path = os.path.join(reference_dir, rel_path, "index.md") + else: + path = os.path.join(reference_dir, rel_path + ".md") + os.makedirs(os.path.dirname(path), exist_ok=True) + + frontmatter = ["---", "sidebar_label: {}".format(page["sidebar_label"]), "title: {}".format(page["title"])] + # A module whose file is /.md collides with the folder's + # index.md route; pin it with a relative slug. + basename = os.path.basename(path)[: -len(".md")] + parent = os.path.basename(os.path.dirname(path)) + if basename == parent and basename != "index": + frontmatter.append("slug: {}".format(basename)) + frontmatter.append("---") + + body_parts = [] + if page["docstring"]: + body_parts.append(page["docstring"]) + body_parts.append("") + if page["is_package"] or not rel_path: + links = _submodule_links(rel_path, pages) + if links: + body_parts.append("## Submodules") + body_parts.append("") + body_parts += ["- [{}]({})".format(title, route) for title, route in links] + body_parts.append("") + if page["body"]: + body_parts.append(page["body"]) + + with open(path, "w", encoding="utf-8") as handle: + handle.write("\n".join(frontmatter) + "\n\n" + "\n".join(body_parts).rstrip("\n") + "\n") + + +def _build_sidebar(pages): + """Build the import-ready "Reference" category from the page tree.""" + + def category(rel_path): + page = pages[rel_path] + label = page["title"].rsplit(".", 1)[-1] + prefix = rel_path + "/" if rel_path else "" + child_depth = prefix.count("/") + + subcategories = [] + leaves = [] + for other_rel, other in sorted(pages.items()): + if other_rel == rel_path or not other_rel.startswith(prefix): + continue + if other_rel.count("/") != child_depth: + continue + if other["is_package"]: + subcategories.append(category(other_rel)) + else: + leaves.append(other["doc_id"]) + + items = subcategories + leaves + node = {"type": "category", "label": label, "link": {"type": "doc", "id": page["doc_id"]}} + if items: + node["items"] = items + else: + # No children: a plain doc leaf avoids an empty expandable node. + return {"type": "doc", "id": page["doc_id"], "label": label} + return node + + root = category("") + root["label"] = "Reference" + return root + + +def _write_sidebar(pages): + sidebar = _build_sidebar(pages) + path = os.path.join(DOCS_BASE_PATH, REFERENCE_SUBDIR, "sidebar.json") + with open(path, "w", encoding="utf-8") as handle: + json.dump(sidebar, handle, indent=2, ensure_ascii=False) + handle.write("\n") + print("Wrote sidebar.json") + + +# --------------------------------------------------------------------------- # +# Safety gate + site sidebar +# --------------------------------------------------------------------------- # + +_MDX_ESM_RE = re.compile(r"^(export|import)\s") + + +def _check_mdx_hazards(): + """Fail generation if any rendered Markdown has an MDX/acorn hazard: a line + outside a code fence beginning with ``export``/``import`` (ESM) or ``<`` + (JSX). These come from unfenced code examples in docstrings; the fix is to + fence the example in its source docstring.""" + reference_dir = os.path.join(DOCS_BASE_PATH, REFERENCE_SUBDIR) + hazards = [] + for dirpath, _dirnames, filenames in os.walk(reference_dir): + for filename in filenames: + if not filename.endswith(".md"): + continue + path = os.path.join(dirpath, filename) + in_codeblock = False + with open(path, encoding="utf-8") as handle: + for lineno, raw in enumerate(handle, 1): + line = raw.rstrip("\n") + if line.lstrip().startswith("```"): + in_codeblock = not in_codeblock + continue + if in_codeblock: + continue + if _MDX_ESM_RE.match(line) or line.startswith("<"): + rel = os.path.relpath(path, DOCS_BASE_PATH) + hazards.append("{}:{}: {}".format(rel, lineno, line)) + if hazards: + raise SystemExit( + "MDX/acorn hazards found in generated Markdown (unfenced code at column " + "zero). Fence the offending example in its source docstring:\n " + "\n ".join(hazards) + ) + print("No MDX/acorn hazards in generated Markdown") + + +def _strip_reference_from_site_sidebar(): + """Remove the "Reference" entry from docs/english/_sidebar.json. + + The reference nav is contributed by the docs-site build from + reference/sidebar.json, so a Reference entry here too would render it twice. + A missing entry is fine (idempotent).""" + site_sidebar = os.path.join(DOCS_BASE_PATH, "_sidebar.json") + with open(site_sidebar, encoding="utf-8") as handle: + entries = json.load(handle) + + new_entries = [e for e in entries if not (isinstance(e, dict) and e.get("label") == "Reference")] + if len(new_entries) == len(entries): + print('No "Reference" entry in _sidebar.json to strip (already absent)') + return + + # _sidebar.json is tab-indented; match it so the diff stays minimal. + with open(site_sidebar, "w", encoding="utf-8") as handle: + json.dump(new_entries, handle, indent="\t", ensure_ascii=False) + handle.write("\n") + print("Stripped Reference entry from _sidebar.json") + + +def main(): + # Rebuild the reference tree from scratch so renamed/removed modules don't + # leave orphaned pages behind. Everything under reference/ is generated. + reference_dir = os.path.join(DOCS_BASE_PATH, REFERENCE_SUBDIR) + shutil.rmtree(reference_dir, ignore_errors=True) + os.makedirs(reference_dir, exist_ok=True) + root = _load_package() + pages = _build_pages(root) + _write_pages(pages) + _write_sidebar(pages) + _check_mdx_hazards() + _strip_reference_from_site_sidebar() + print("Generated {} reference pages".format(len(pages))) + + +if __name__ == "__main__": + main() diff --git a/scripts/generate_api_docs.sh b/scripts/generate_api_docs.sh index 275aa0fe1..8537c52b7 100755 --- a/scripts/generate_api_docs.sh +++ b/scripts/generate_api_docs.sh @@ -1,5 +1,7 @@ #!/bin/bash -# Generate API documents from the latest source code +# Generate the Markdown API reference from the latest source code. +# The heavy lifting (including inlining re-exported classes) lives in +# scripts/generate_api_docs.py. set -e script_dir=$(dirname "$0") @@ -8,12 +10,8 @@ cd "${script_dir}/.." pip install -U pip pip install -U -r requirements/adapter_dev.txt pip install -U -r requirements/async_dev.txt -pip install -U pdoc3 +pip install -U griffe pip install . -rm -rf docs/reference +rm -rf docs/english/reference -pdoc slack_bolt --html -o docs/reference -cp -R docs/reference/slack_bolt/* docs/reference/ -rm -rf docs/reference/slack_bolt - -open docs/reference/index.html +python scripts/generate_api_docs.py diff --git a/slack_bolt/__init__.py b/slack_bolt/__init__.py index e3664814b..7631f19e0 100644 --- a/slack_bolt/__init__.py +++ b/slack_bolt/__init__.py @@ -1,5 +1,5 @@ """ -A Python framework to build Slack apps in a flash with the latest platform features.Read the [getting started guide](https://docs.slack.dev/tools/bolt-python/creating-an-app) and look at our [code examples](https://github.com/slackapi/bolt-python/tree/main/examples) to learn how to build apps using Bolt. +A Python framework to build Slack apps in a flash with the latest platform features. Read the [getting started guide](https://docs.slack.dev/tools/bolt-python/creating-an-app) and look at our [code examples](https://github.com/slackapi/bolt-python/tree/main/examples) to learn how to build apps using Bolt. * Website: https://docs.slack.dev/tools/bolt-python/ * GitHub repository: https://github.com/slackapi/bolt-python diff --git a/slack_bolt/adapter/asgi/aiohttp/__init__.py b/slack_bolt/adapter/asgi/aiohttp/__init__.py index aed8458d9..2193fe8a7 100644 --- a/slack_bolt/adapter/asgi/aiohttp/__init__.py +++ b/slack_bolt/adapter/asgi/aiohttp/__init__.py @@ -17,14 +17,16 @@ def __init__(self, app: AsyncApp, path: str = "/slack/events"): With the default settings, `http://localhost:3000/slack/events` Run Bolt with [uvicron](https://www.uvicorn.org/) - # Python - app = AsyncApp() - api = SlackRequestHandler(app) - - # bash - export SLACK_SIGNING_SECRET=*** - export SLACK_BOT_TOKEN=xoxb-*** - uvicorn app:api --port 3000 --log-level debug + ```python + # Python + app = AsyncApp() + api = SlackRequestHandler(app) + + # bash + export SLACK_SIGNING_SECRET=*** + export SLACK_BOT_TOKEN=xoxb-*** + uvicorn app:api --port 3000 --log-level debug + ``` Args: app: Your bolt application diff --git a/slack_bolt/adapter/asgi/builtin/__init__.py b/slack_bolt/adapter/asgi/builtin/__init__.py index 93f7ab845..d267080d7 100644 --- a/slack_bolt/adapter/asgi/builtin/__init__.py +++ b/slack_bolt/adapter/asgi/builtin/__init__.py @@ -16,14 +16,16 @@ def __init__(self, app: App, path: str = "/slack/events"): With the default settings, `http://localhost:3000/slack/events` Run Bolt with [uvicron](https://www.uvicorn.org/) - # Python - app = App() - api = SlackRequestHandler(app) - - # bash - export SLACK_SIGNING_SECRET=*** - export SLACK_BOT_TOKEN=xoxb-*** - uvicorn app:api --port 3000 --log-level debug + ```python + # Python + app = App() + api = SlackRequestHandler(app) + + # bash + export SLACK_SIGNING_SECRET=*** + export SLACK_BOT_TOKEN=xoxb-*** + uvicorn app:api --port 3000 --log-level debug + ``` Args: app: Your bolt application diff --git a/slack_bolt/adapter/falcon/async_resource.py b/slack_bolt/adapter/falcon/async_resource.py index fdb2d975f..b9271ad16 100644 --- a/slack_bolt/adapter/falcon/async_resource.py +++ b/slack_bolt/adapter/falcon/async_resource.py @@ -15,12 +15,14 @@ class AsyncSlackAppResource: """ For use with ASGI Falcon Apps. + ```python from slack_bolt.async_app import AsyncApp app = AsyncApp() import falcon app = falcon.asgi.App() app.add_route("/slack/events", AsyncSlackAppResource(app)) + ``` """ def __init__(self, app: AsyncApp): diff --git a/slack_bolt/adapter/falcon/resource.py b/slack_bolt/adapter/falcon/resource.py index 5d162ad23..80d24ee9d 100644 --- a/slack_bolt/adapter/falcon/resource.py +++ b/slack_bolt/adapter/falcon/resource.py @@ -12,12 +12,14 @@ class SlackAppResource: """ + ```python from slack_bolt import App app = App() import falcon api = application = falcon.API() api.add_route("/slack/events", SlackAppResource(app)) + ``` """ def __init__(self, app: App): diff --git a/slack_bolt/adapter/wsgi/handler.py b/slack_bolt/adapter/wsgi/handler.py index fef54f73e..4d9766a4b 100644 --- a/slack_bolt/adapter/wsgi/handler.py +++ b/slack_bolt/adapter/wsgi/handler.py @@ -19,17 +19,18 @@ def __init__(self, app: App, path: str = "/slack/events"): With the default settings, `http://localhost:3000/slack/events` Run Bolt with [gunicorn](https://gunicorn.org/) - # Python - app = App() + ```python + app = App() - api = SlackRequestHandler(app) + api = SlackRequestHandler(app) + ``` - # bash - export SLACK_SIGNING_SECRET=*** + ```bash + export SLACK_SIGNING_SECRET=*** + export SLACK_BOT_TOKEN=xoxb-*** - export SLACK_BOT_TOKEN=xoxb-*** - - gunicorn app:api -b 0.0.0.0:3000 --log-level debug + gunicorn app:api -b 0.0.0.0:3000 --log-level debug + ``` Args: app: Your bolt application diff --git a/slack_bolt/app/app.py b/slack_bolt/app/app.py index e20649902..1276be398 100644 --- a/slack_bolt/app/app.py +++ b/slack_bolt/app/app.py @@ -137,24 +137,26 @@ def __init__( ): """Bolt App that provides functionalities to register middleware/listeners. - import os - from slack_bolt import App - - # Initializes your app with your bot token and signing secret - app = App( - token=os.environ.get("SLACK_BOT_TOKEN"), - signing_secret=os.environ.get("SLACK_SIGNING_SECRET") - ) + ```python + import os + from slack_bolt import App + + # Initializes your app with your bot token and signing secret + app = App( + token=os.environ.get("SLACK_BOT_TOKEN"), + signing_secret=os.environ.get("SLACK_SIGNING_SECRET") + ) - # Listens to incoming messages that contain "hello" - @app.message("hello") - def message_hello(message, say): - # say() sends a message to the channel where the event was triggered - say(f"Hey there <@{message['user']}>!") + # Listens to incoming messages that contain "hello" + @app.message("hello") + def message_hello(message, say): + # say() sends a message to the channel where the event was triggered + say(f"Hey there <@{message['user']}>!") - # Start your app - if __name__ == "__main__": - app.start(port=int(os.environ.get("PORT", 3000))) + # Start your app + if __name__ == "__main__": + app.start(port=int(os.environ.get("PORT", 3000))) + ``` Refer to https://docs.slack.dev/tools/bolt-python/creating-an-app for details. @@ -511,9 +513,11 @@ def start( ) -> None: """Starts a web server for local development. - # With the default settings, `http://localhost:3000/slack/events` - # is available for handling incoming requests from Slack - app.start() + ```python + # With the default settings, `http://localhost:3000/slack/events` + # is available for handling incoming requests from Slack + app.start() + ``` This method internally starts a Web server process built with the `http.server` module. For production, consider using a production-ready WSGI server such as Gunicorn. @@ -660,14 +664,16 @@ def middleware(self, *args) -> Optional[Callable]: """Registers a new middleware to this app. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.middleware - def middleware_func(logger, body, next): - logger.info(f"request body: {body}") - next() + ```python + # Use this method as a decorator + @app.middleware + def middleware_func(logger, body, next): + logger.info(f"request body: {body}") + next() - # Pass a function to this method - app.middleware(middleware_func) + # Pass a function to this method + app.middleware(middleware_func) + ``` Refer to https://docs.slack.dev/tools/bolt-python/concepts/global-middleware for details. @@ -722,16 +728,18 @@ def step( Unlike others, this method doesn't behave as a decorator. If you want to register a step from app by a decorator, use `WorkflowStepBuilder`'s methods. - # Create a new WorkflowStep instance - from slack_bolt.workflows.step import WorkflowStep - ws = WorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, - ) - # Pass Step to set up listeners - app.step(ws) + ```python + # Create a new WorkflowStep instance + from slack_bolt.workflows.step import WorkflowStep + ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, + ) + # Pass Step to set up listeners + app.step(ws) + ``` Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps. @@ -776,14 +784,16 @@ def step( def error(self, func: Callable[..., Optional[BoltResponse]]) -> Callable[..., Optional[BoltResponse]]: """Updates the global error handler. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.error - def custom_error_handler(error, body, logger): - logger.exception(f"Error: {error}") - logger.info(f"Request body: {body}") + ```python + # Use this method as a decorator + @app.error + def custom_error_handler(error, body, logger): + logger.exception(f"Error: {error}") + logger.info(f"Request body: {body}") - # Pass a function to this method - app.error(custom_error_handler) + # Pass a function to this method + app.error(custom_error_handler) + ``` To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. @@ -816,16 +826,18 @@ def event( ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]: """Registers a new event listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.event("team_join") - def ask_for_introduction(event, say): - welcome_channel_id = "C12345" - user_id = event["user"] - text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel." - say(text=text, channel=welcome_channel_id) + ```python + # Use this method as a decorator + @app.event("team_join") + def ask_for_introduction(event, say): + welcome_channel_id = "C12345" + user_id = event["user"] + text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel." + say(text=text, channel=welcome_channel_id) - # Pass a function to this method - app.event("team_join")(ask_for_introduction) + # Pass a function to this method + app.event("team_join")(ask_for_introduction) + ``` Refer to https://docs.slack.dev/apis/events-api/ for details of Events API. @@ -859,14 +871,16 @@ def message( """Registers a new message event listener. This method can be used as either a decorator or a method. Check the `App#event` method's docstring for details. - # Use this method as a decorator - @app.message(":wave:") - def say_hello(message, say): - user = message['user'] - say(f"Hi there, <@{user}>!") + ```python + # Use this method as a decorator + @app.message(":wave:") + def say_hello(message, say): + user = message['user'] + say(f"Hi there, <@{user}>!") - # Pass a function to this method - app.message(":wave:")(say_hello) + # Pass a function to this method + app.message(":wave:")(say_hello) + ``` Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events. @@ -921,19 +935,21 @@ def function( """Registers a new Function listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.function("reverse") - def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail): - try: - ack() - string_to_reverse = inputs["stringToReverse"] - complete(outputs={"reverseString": string_to_reverse[::-1]}) - except Exception as e: - fail(f"Cannot reverse string (error: {e})") - raise e + ```python + # Use this method as a decorator + @app.function("reverse") + def reverse_string(ack: Ack, inputs: dict, complete: Complete, fail: Fail): + try: + ack() + string_to_reverse = inputs["stringToReverse"] + complete(outputs={"reverseString": string_to_reverse[::-1]}) + except Exception as e: + fail(f"Cannot reverse string (error: {e})") + raise e - # Pass a function to this method - app.function("reverse")(reverse_string) + # Pass a function to this method + app.function("reverse")(reverse_string) + ``` To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.args`'s API document. @@ -971,15 +987,17 @@ def command( """Registers a new slash command listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.command("/echo") - def repeat_text(ack, say, command): - # Acknowledge command request - ack() - say(f"{command['text']}") + ```python + # Use this method as a decorator + @app.command("/echo") + def repeat_text(ack, say, command): + # Acknowledge command request + ack() + say(f"{command['text']}") - # Pass a function to this method - app.command("/echo")(repeat_text) + # Pass a function to this method + app.command("/echo")(repeat_text) + ``` Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands. @@ -1012,21 +1030,23 @@ def shortcut( """Registers a new shortcut listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.shortcut("open_modal") - def open_modal(ack, body, client): - # Acknowledge the command request - ack() - # Call views_open with the built-in client - client.views_open( - # Pass a valid trigger_id within 3 seconds of receiving it - trigger_id=body["trigger_id"], - # View payload - view={ ... } - ) + ```python + # Use this method as a decorator + @app.shortcut("open_modal") + def open_modal(ack, body, client): + # Acknowledge the command request + ack() + # Call views_open with the built-in client + client.views_open( + # Pass a valid trigger_id within 3 seconds of receiving it + trigger_id=body["trigger_id"], + # View payload + view={ ... } + ) - # Pass a function to this method - app.shortcut("open_modal")(open_modal) + # Pass a function to this method + app.shortcut("open_modal")(open_modal) + ``` Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts. @@ -1088,13 +1108,15 @@ def action( ) -> Callable[..., Optional[Callable[..., Optional[BoltResponse]]]]: """Registers a new action listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.action("approve_button") - def update_message(ack): - ack() + ```python + # Use this method as a decorator + @app.action("approve_button") + def update_message(ack): + ack() - # Pass a function to this method - app.action("approve_button")(update_message) + # Pass a function to this method + app.action("approve_button")(update_message) + ``` * Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`. * Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`. @@ -1194,25 +1216,27 @@ def view( """Registers a new `view_submission`/`view_closed` event listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.view("view_1") - def handle_submission(ack, body, client, view): - # Assume there's an input block with `block_c` as the block_id and `dreamy_input` - hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"] - user = body["user"]["id"] - # Validate the inputs - errors = {} - if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5: - errors["block_c"] = "The value must be longer than 5 characters" - if len(errors) > 0: - ack(response_action="errors", errors=errors) - return - # Acknowledge the view_submission event and close the modal - ack() - # Do whatever you want with the input data - here we're saving it to a DB - - # Pass a function to this method - app.view("view_1")(handle_submission) + ```python + # Use this method as a decorator + @app.view("view_1") + def handle_submission(ack, body, client, view): + # Assume there's an input block with `block_c` as the block_id and `dreamy_input` + hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"] + user = body["user"]["id"] + # Validate the inputs + errors = {} + if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5: + errors["block_c"] = "The value must be longer than 5 characters" + if len(errors) > 0: + ack(response_action="errors", errors=errors) + return + # Acknowledge the view_submission event and close the modal + ack() + # Do whatever you want with the input data - here we're saving it to a DB + + # Pass a function to this method + app.view("view_1")(handle_submission) + ``` Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads. @@ -1279,23 +1303,25 @@ def options( """Registers a new options listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.options("menu_selection") - def show_menu_options(ack): - options = [ - { - "text": {"type": "plain_text", "text": "Option 1"}, - "value": "1-1", - }, - { - "text": {"type": "plain_text", "text": "Option 2"}, - "value": "1-2", - }, - ] - ack(options=options) - - # Pass a function to this method - app.options("menu_selection")(show_menu_options) + ```python + # Use this method as a decorator + @app.options("menu_selection") + def show_menu_options(ack): + options = [ + { + "text": {"type": "plain_text", "text": "Option 1"}, + "value": "1-1", + }, + { + "text": {"type": "plain_text", "text": "Option 2"}, + "value": "1-2", + }, + ] + ack(options=options) + + # Pass a function to this method + app.options("menu_selection")(show_menu_options) + ``` Refer to the following documents for details: diff --git a/slack_bolt/app/async_app.py b/slack_bolt/app/async_app.py index cc94f9e15..f2124f5e1 100644 --- a/slack_bolt/app/async_app.py +++ b/slack_bolt/app/async_app.py @@ -146,24 +146,26 @@ def __init__( ): """Bolt App that provides functionalities to register middleware/listeners. - import os - from slack_bolt.async_app import AsyncApp - - # Initializes your app with your bot token and signing secret - app = AsyncApp( - token=os.environ.get("SLACK_BOT_TOKEN"), - signing_secret=os.environ.get("SLACK_SIGNING_SECRET") - ) + ```python + import os + from slack_bolt.async_app import AsyncApp + + # Initializes your app with your bot token and signing secret + app = AsyncApp( + token=os.environ.get("SLACK_BOT_TOKEN"), + signing_secret=os.environ.get("SLACK_SIGNING_SECRET") + ) - # Listens to incoming messages that contain "hello" - @app.message("hello") - async def message_hello(message, say): # async function - # say() sends a message to the channel where the event was triggered - await say(f"Hey there <@{message['user']}>!") + # Listens to incoming messages that contain "hello" + @app.message("hello") + async def message_hello(message, say): # async function + # say() sends a message to the channel where the event was triggered + await say(f"Hey there <@{message['user']}>!") - # Start your app - if __name__ == "__main__": - app.start(port=int(os.environ.get("PORT", 3000))) + # Start your app + if __name__ == "__main__": + app.start(port=int(os.environ.get("PORT", 3000))) + ``` Refer to https://docs.slack.dev/tools/bolt-python/concepts/async for details. @@ -530,18 +532,20 @@ def server( def web_app(self, path: str = "/slack/events", port: int = 3000) -> web.Application: """Returns a `web.Application` instance for aiohttp-devtools users. - from slack_bolt.async_app import AsyncApp - app = AsyncApp() + ```python + from slack_bolt.async_app import AsyncApp + app = AsyncApp() - @app.event("app_mention") - async def event_test(body, say, logger): - logger.info(body) - await say("What's up?") + @app.event("app_mention") + async def event_test(body, say, logger): + logger.info(body) + await say("What's up?") - def app_factory(): - return app.web_app() + def app_factory(): + return app.web_app() - # adev runserver --port 3000 --app-factory app_factory async_app.py + # adev runserver --port 3000 --app-factory app_factory async_app.py + ``` Args: path: The path to receive incoming requests from Slack @@ -689,14 +693,16 @@ def middleware(self, *args) -> Optional[Callable]: """Registers a new middleware to this app. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.middleware - async def middleware_func(logger, body, next): - logger.info(f"request body: {body}") - await next() + ```python + # Use this method as a decorator + @app.middleware + async def middleware_func(logger, body, next): + logger.info(f"request body: {body}") + await next() - # Pass a function to this method - app.middleware(middleware_func) + # Pass a function to this method + app.middleware(middleware_func) + ``` To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. @@ -746,16 +752,18 @@ def step( Unlike others, this method doesn't behave as a decorator. If you want to register a step from app by a decorator, use `AsyncWorkflowStepBuilder`'s methods. - # Create a new WorkflowStep instance - from slack_bolt.workflows.async_step import AsyncWorkflowStep - ws = AsyncWorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, - ) - # Pass Step to set up listeners - app.step(ws) + ```python + # Create a new WorkflowStep instance + from slack_bolt.workflows.async_step import AsyncWorkflowStep + ws = AsyncWorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, + ) + # Pass Step to set up listeners + app.step(ws) + ``` Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details of steps from apps. @@ -801,14 +809,16 @@ def error( ) -> Callable[..., Awaitable[Optional[BoltResponse]]]: """Updates the global error handler. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.error - async def custom_error_handler(error, body, logger): - logger.exception(f"Error: {error}") - logger.info(f"Request body: {body}") + ```python + # Use this method as a decorator + @app.error + async def custom_error_handler(error, body, logger): + logger.exception(f"Error: {error}") + logger.info(f"Request body: {body}") - # Pass a function to this method - app.error(custom_error_handler) + # Pass a function to this method + app.error(custom_error_handler) + ``` To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. @@ -844,16 +854,18 @@ def event( ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]: """Registers a new event listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.event("team_join") - async def ask_for_introduction(event, say): - welcome_channel_id = "C12345" - user_id = event["user"] - text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel." - await say(text=text, channel=welcome_channel_id) + ```python + # Use this method as a decorator + @app.event("team_join") + async def ask_for_introduction(event, say): + welcome_channel_id = "C12345" + user_id = event["user"] + text = f"Welcome to the team, <@{user_id}>! :tada: You can introduce yourself in this channel." + await say(text=text, channel=welcome_channel_id) - # Pass a function to this method - app.event("team_join")(ask_for_introduction) + # Pass a function to this method + app.event("team_join")(ask_for_introduction) + ``` Refer to https://docs.slack.dev/apis/events-api/ for details of Events API. @@ -887,14 +899,16 @@ def message( """Registers a new message event listener. This method can be used as either a decorator or a method. Check the `App#event` method's docstring for details. - # Use this method as a decorator - @app.message(":wave:") - async def say_hello(message, say): - user = message['user'] - await say(f"Hi there, <@{user}>!") + ```python + # Use this method as a decorator + @app.message(":wave:") + async def say_hello(message, say): + user = message['user'] + await say(f"Hi there, <@{user}>!") - # Pass a function to this method - app.message(":wave:")(say_hello) + # Pass a function to this method + app.message(":wave:")(say_hello) + ``` Refer to https://docs.slack.dev/reference/events/message/ for details of `message` events. @@ -952,19 +966,21 @@ def function( """Registers a new Function listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.function("reverse") - async def reverse_string(ack: AsyncAck, inputs: dict, complete: AsyncComplete, fail: AsyncFail): - try: - await ack() - string_to_reverse = inputs["stringToReverse"] - await complete({"reverseString": string_to_reverse[::-1]}) - except Exception as e: - await fail(f"Cannot reverse string (error: {e})") - raise e + ```python + # Use this method as a decorator + @app.function("reverse") + async def reverse_string(ack: AsyncAck, inputs: dict, complete: AsyncComplete, fail: AsyncFail): + try: + await ack() + string_to_reverse = inputs["stringToReverse"] + await complete({"reverseString": string_to_reverse[::-1]}) + except Exception as e: + await fail(f"Cannot reverse string (error: {e})") + raise e - # Pass a function to this method - app.function("reverse")(reverse_string) + # Pass a function to this method + app.function("reverse")(reverse_string) + ``` To learn available arguments for middleware/listeners, see `slack_bolt.kwargs_injection.async_args`'s API document. @@ -1003,15 +1019,17 @@ def command( """Registers a new slash command listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.command("/echo") - async def repeat_text(ack, say, command): - # Acknowledge command request - await ack() - await say(f"{command['text']}") + ```python + # Use this method as a decorator + @app.command("/echo") + async def repeat_text(ack, say, command): + # Acknowledge command request + await ack() + await say(f"{command['text']}") - # Pass a function to this method - app.command("/echo")(repeat_text) + # Pass a function to this method + app.command("/echo")(repeat_text) + ``` Refer to https://docs.slack.dev/interactivity/implementing-slash-commands/ for details of Slash Commands. @@ -1044,21 +1062,23 @@ def shortcut( """Registers a new shortcut listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.shortcut("open_modal") - async def open_modal(ack, body, client): - # Acknowledge the command request - await ack() - # Call views_open with the built-in client - await client.views_open( - # Pass a valid trigger_id within 3 seconds of receiving it - trigger_id=body["trigger_id"], - # View payload - view={ ... } - ) + ```python + # Use this method as a decorator + @app.shortcut("open_modal") + async def open_modal(ack, body, client): + # Acknowledge the command request + await ack() + # Call views_open with the built-in client + await client.views_open( + # Pass a valid trigger_id within 3 seconds of receiving it + trigger_id=body["trigger_id"], + # View payload + view={ ... } + ) - # Pass a function to this method - app.shortcut("open_modal")(open_modal) + # Pass a function to this method + app.shortcut("open_modal")(open_modal) + ``` Refer to https://docs.slack.dev/interactivity/implementing-shortcuts/ for details about Shortcuts. @@ -1120,13 +1140,15 @@ def action( ) -> Callable[..., Optional[Callable[..., Awaitable[Optional[BoltResponse]]]]]: """Registers a new action listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.action("approve_button") - async def update_message(ack): - await ack() + ```python + # Use this method as a decorator + @app.action("approve_button") + async def update_message(ack): + await ack() - # Pass a function to this method - app.action("approve_button")(update_message) + # Pass a function to this method + app.action("approve_button")(update_message) + ``` * Refer to https://docs.slack.dev/reference/interaction-payloads/block_actions-payload/ for actions in `blocks`. * Refer to https://docs.slack.dev/legacy/legacy-messaging/legacy-message-buttons/ for actions in `attachments`. @@ -1226,25 +1248,27 @@ def view( """Registers a new `view_submission`/`view_closed` event listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.view("view_1") - async def handle_submission(ack, body, client, view): - # Assume there's an input block with `block_c` as the block_id and `dreamy_input` - hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"] - user = body["user"]["id"] - # Validate the inputs - errors = {} - if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5: - errors["block_c"] = "The value must be longer than 5 characters" - if len(errors) > 0: - await ack(response_action="errors", errors=errors) - return - # Acknowledge the view_submission event and close the modal - await ack() - # Do whatever you want with the input data - here we're saving it to a DB - - # Pass a function to this method - app.view("view_1")(handle_submission) + ```python + # Use this method as a decorator + @app.view("view_1") + async def handle_submission(ack, body, client, view): + # Assume there's an input block with `block_c` as the block_id and `dreamy_input` + hopes_and_dreams = view["state"]["values"]["block_c"]["dreamy_input"] + user = body["user"]["id"] + # Validate the inputs + errors = {} + if hopes_and_dreams is not None and len(hopes_and_dreams) <= 5: + errors["block_c"] = "The value must be longer than 5 characters" + if len(errors) > 0: + await ack(response_action="errors", errors=errors) + return + # Acknowledge the view_submission event and close the modal + await ack() + # Do whatever you want with the input data - here we're saving it to a DB + + # Pass a function to this method + app.view("view_1")(handle_submission) + ``` Refer to https://docs.slack.dev/reference/interaction-payloads/view-interactions-payload for details of payloads. @@ -1311,23 +1335,25 @@ def options( """Registers a new options listener. This method can be used as either a decorator or a method. - # Use this method as a decorator - @app.options("menu_selection") - async def show_menu_options(ack): - options = [ - { - "text": {"type": "plain_text", "text": "Option 1"}, - "value": "1-1", - }, - { - "text": {"type": "plain_text", "text": "Option 2"}, - "value": "1-2", - }, - ] - await ack(options=options) - - # Pass a function to this method - app.options("menu_selection")(show_menu_options) + ```python + # Use this method as a decorator + @app.options("menu_selection") + async def show_menu_options(ack): + options = [ + { + "text": {"type": "plain_text", "text": "Option 1"}, + "value": "1-1", + }, + { + "text": {"type": "plain_text", "text": "Option 2"}, + "value": "1-2", + }, + ] + await ack(options=options) + + # Pass a function to this method + app.options("menu_selection")(show_menu_options) + ``` Refer to the following documents for details: diff --git a/slack_bolt/context/async_context.py b/slack_bolt/context/async_context.py index 94b2b5cbe..1f78330d1 100644 --- a/slack_bolt/context/async_context.py +++ b/slack_bolt/context/async_context.py @@ -53,20 +53,22 @@ def listener_runner(self) -> "AsyncioListenerRunner": def client(self) -> AsyncWebClient: """The `AsyncWebClient` instance available for this request. - @app.event("app_mention") - async def handle_events(context): - await context.client.chat_postMessage( - channel=context.channel_id, - text="Thanks!", - ) - - # You can access "client" this way too. - @app.event("app_mention") - async def handle_events(client, context): - await client.chat_postMessage( - channel=context.channel_id, - text="Thanks!", - ) + ```python + @app.event("app_mention") + async def handle_events(context): + await context.client.chat_postMessage( + channel=context.channel_id, + text="Thanks!", + ) + + # You can access "client" this way too. + @app.event("app_mention") + async def handle_events(client, context): + await client.chat_postMessage( + channel=context.channel_id, + text="Thanks!", + ) + ``` Returns: `AsyncWebClient` instance @@ -79,14 +81,16 @@ async def handle_events(client, context): def ack(self) -> AsyncAck: """`ack()` function for this request. - @app.action("button") - async def handle_button_clicks(context): - await context.ack() + ```python + @app.action("button") + async def handle_button_clicks(context): + await context.ack() - # You can access "ack" this way too. - @app.action("button") - async def handle_button_clicks(ack): - await ack() + # You can access "ack" this way too. + @app.action("button") + async def handle_button_clicks(ack): + await ack() + ``` Returns: Callable `ack()` function @@ -99,16 +103,18 @@ async def handle_button_clicks(ack): def say(self) -> AsyncSay: """`say()` function for this request. - @app.action("button") - async def handle_button_clicks(context): - await context.ack() - await context.say("Hi!") + ```python + @app.action("button") + async def handle_button_clicks(context): + await context.ack() + await context.say("Hi!") - # You can access "ack" this way too. - @app.action("button") - async def handle_button_clicks(ack, say): - await ack() - await say("Hi!") + # You can access "ack" this way too. + @app.action("button") + async def handle_button_clicks(ack, say): + await ack() + await say("Hi!") + ``` Returns: Callable `say()` function @@ -121,16 +127,18 @@ async def handle_button_clicks(ack, say): def respond(self) -> Optional[AsyncRespond]: """`respond()` function for this request. - @app.action("button") - async def handle_button_clicks(context): - await context.ack() - await context.respond("Hi!") + ```python + @app.action("button") + async def handle_button_clicks(context): + await context.ack() + await context.respond("Hi!") - # You can access "ack" this way too. - @app.action("button") - async def handle_button_clicks(ack, respond): - await ack() - await respond("Hi!") + # You can access "ack" this way too. + @app.action("button") + async def handle_button_clicks(ack, respond): + await ack() + await respond("Hi!") + ``` Returns: Callable `respond()` function @@ -150,15 +158,17 @@ def complete(self) -> AsyncComplete: or complete the workflow if the function is the last step in a workflow. Additionally, any interactivity handlers associated to a function invocation will no longer be invocable. - @app.function("reverse") - async def handle_button_clicks(ack, complete): - await ack() - await complete(outputs={"stringReverse":"olleh"}) + ```python + @app.function("reverse") + async def handle_button_clicks(ack, complete): + await ack() + await complete(outputs={"stringReverse":"olleh"}) - @app.function("reverse") - async def handle_button_clicks(context): - await context.ack() - await context.complete(outputs={"stringReverse":"olleh"}) + @app.function("reverse") + async def handle_button_clicks(context): + await context.ack() + await context.complete(outputs={"stringReverse":"olleh"}) + ``` Returns: Callable `complete()` function @@ -174,15 +184,17 @@ def fail(self) -> AsyncFail: on to the end user through SlackBot. Additionally, any interactivity handlers associated to a function invocation will no longer be invocable. - @app.function("reverse") - async def handle_button_clicks(ack, fail): - await ack() - await fail(error="something went wrong") - - @app.function("reverse") - async def handle_button_clicks(context): - await context.ack() - await context.fail(error="something went wrong") + ```python + @app.function("reverse") + async def handle_button_clicks(ack, fail): + await ack() + await fail(error="something went wrong") + + @app.function("reverse") + async def handle_button_clicks(context): + await context.ack() + await context.fail(error="something went wrong") + ``` Returns: Callable `fail()` function diff --git a/slack_bolt/context/context.py b/slack_bolt/context/context.py index b101460a5..3b7f2ebbb 100644 --- a/slack_bolt/context/context.py +++ b/slack_bolt/context/context.py @@ -54,20 +54,22 @@ def listener_runner(self) -> "ThreadListenerRunner": def client(self) -> WebClient: """The `WebClient` instance available for this request. - @app.event("app_mention") - def handle_events(context): - context.client.chat_postMessage( - channel=context.channel_id, - text="Thanks!", - ) - - # You can access "client" this way too. - @app.event("app_mention") - def handle_events(client, context): - client.chat_postMessage( - channel=context.channel_id, - text="Thanks!", - ) + ```python + @app.event("app_mention") + def handle_events(context): + context.client.chat_postMessage( + channel=context.channel_id, + text="Thanks!", + ) + + # You can access "client" this way too. + @app.event("app_mention") + def handle_events(client, context): + client.chat_postMessage( + channel=context.channel_id, + text="Thanks!", + ) + ``` Returns: `WebClient` instance @@ -80,14 +82,16 @@ def handle_events(client, context): def ack(self) -> Ack: """`ack()` function for this request. - @app.action("button") - def handle_button_clicks(context): - context.ack() + ```python + @app.action("button") + def handle_button_clicks(context): + context.ack() - # You can access "ack" this way too. - @app.action("button") - def handle_button_clicks(ack): - ack() + # You can access "ack" this way too. + @app.action("button") + def handle_button_clicks(ack): + ack() + ``` Returns: Callable `ack()` function @@ -100,16 +104,18 @@ def handle_button_clicks(ack): def say(self) -> Say: """`say()` function for this request. - @app.action("button") - def handle_button_clicks(context): - context.ack() - context.say("Hi!") + ```python + @app.action("button") + def handle_button_clicks(context): + context.ack() + context.say("Hi!") - # You can access "ack" this way too. - @app.action("button") - def handle_button_clicks(ack, say): - ack() - say("Hi!") + # You can access "ack" this way too. + @app.action("button") + def handle_button_clicks(ack, say): + ack() + say("Hi!") + ``` Returns: Callable `say()` function @@ -122,16 +128,18 @@ def handle_button_clicks(ack, say): def respond(self) -> Optional[Respond]: """`respond()` function for this request. - @app.action("button") - def handle_button_clicks(context): - context.ack() - context.respond("Hi!") + ```python + @app.action("button") + def handle_button_clicks(context): + context.ack() + context.respond("Hi!") - # You can access "ack" this way too. - @app.action("button") - def handle_button_clicks(ack, respond): - ack() - respond("Hi!") + # You can access "ack" this way too. + @app.action("button") + def handle_button_clicks(ack, respond): + ack() + respond("Hi!") + ``` Returns: Callable `respond()` function @@ -151,15 +159,17 @@ def complete(self) -> Complete: or complete the workflow if the function is the last step in a workflow. Additionally, any interactivity handlers associated to a function invocation will no longer be invocable. - @app.function("reverse") - def handle_button_clicks(ack, complete): - ack() - complete(outputs={"stringReverse":"olleh"}) + ```python + @app.function("reverse") + def handle_button_clicks(ack, complete): + ack() + complete(outputs={"stringReverse":"olleh"}) - @app.function("reverse") - def handle_button_clicks(context): - context.ack() - context.complete(outputs={"stringReverse":"olleh"}) + @app.function("reverse") + def handle_button_clicks(context): + context.ack() + context.complete(outputs={"stringReverse":"olleh"}) + ``` Returns: Callable `complete()` function @@ -175,15 +185,17 @@ def fail(self) -> Fail: on to the end user through SlackBot. Additionally, any interactivity handlers associated to a function invocation will no longer be invocable. - @app.function("reverse") - def handle_button_clicks(ack, fail): - ack() - fail(error="something went wrong") - - @app.function("reverse") - def handle_button_clicks(context): - context.ack() - context.fail(error="something went wrong") + ```python + @app.function("reverse") + def handle_button_clicks(ack, fail): + ack() + fail(error="something went wrong") + + @app.function("reverse") + def handle_button_clicks(context): + context.ack() + context.fail(error="something went wrong") + ``` Returns: Callable `fail()` function diff --git a/slack_bolt/kwargs_injection/args.py b/slack_bolt/kwargs_injection/args.py index f2b4099d6..b47a008d2 100644 --- a/slack_bolt/kwargs_injection/args.py +++ b/slack_bolt/kwargs_injection/args.py @@ -23,29 +23,33 @@ class Args: """All the arguments in this class are available in any middleware / listeners. You can inject the named variables in the argument list in arbitrary order. - @app.action("link_button") - def handle_buttons(ack, respond, logger, context, body, client): - logger.info(f"request body: {body}") - ack() - if context.channel_id is not None: - respond("Hi!") - client.views_open( - trigger_id=body["trigger_id"], - view={ ... } - ) + ```python + @app.action("link_button") + def handle_buttons(ack, respond, logger, context, body, client): + logger.info(f"request body: {body}") + ack() + if context.channel_id is not None: + respond("Hi!") + client.views_open( + trigger_id=body["trigger_id"], + view={ ... } + ) + ``` Alternatively, you can include a parameter named `args` and it will be injected with an instance of this class. - @app.action("link_button") - def handle_buttons(args): - args.logger.info(f"request body: {args.body}") - args.ack() - if args.context.channel_id is not None: - args.respond("Hi!") - args.client.views_open( - trigger_id=args.body["trigger_id"], - view={ ... } - ) + ```python + @app.action("link_button") + def handle_buttons(args): + args.logger.info(f"request body: {args.body}") + args.ack() + if args.context.channel_id is not None: + args.respond("Hi!") + args.client.views_open( + trigger_id=args.body["trigger_id"], + view={ ... } + ) + ``` """ diff --git a/slack_bolt/kwargs_injection/async_args.py b/slack_bolt/kwargs_injection/async_args.py index 2217cfe9f..d1ac10087 100644 --- a/slack_bolt/kwargs_injection/async_args.py +++ b/slack_bolt/kwargs_injection/async_args.py @@ -22,29 +22,33 @@ class AsyncArgs: """All the arguments in this class are available in any middleware / listeners. You can inject the named variables in the argument list in arbitrary order. - @app.action("link_button") - async def handle_buttons(ack, respond, logger, context, body, client): - logger.info(f"request body: {body}") - await ack() - if context.channel_id is not None: - await respond("Hi!") - await client.views_open( - trigger_id=body["trigger_id"], - view={ ... } - ) + ```python + @app.action("link_button") + async def handle_buttons(ack, respond, logger, context, body, client): + logger.info(f"request body: {body}") + await ack() + if context.channel_id is not None: + await respond("Hi!") + await client.views_open( + trigger_id=body["trigger_id"], + view={ ... } + ) + ``` Alternatively, you can include a parameter named `args` and it will be injected with an instance of this class. - @app.action("link_button") - async def handle_buttons(args): - args.logger.info(f"request body: {args.body}") - await args.ack() - if args.context.channel_id is not None: - await args.respond("Hi!") - await args.client.views_open( - trigger_id=args.body["trigger_id"], - view={ ... } - ) + ```python + @app.action("link_button") + async def handle_buttons(args): + args.logger.info(f"request body: {args.body}") + await args.ack() + if args.context.channel_id is not None: + await args.respond("Hi!") + await args.client.views_open( + trigger_id=args.body["trigger_id"], + view={ ... } + ) + ``` """ diff --git a/slack_bolt/lazy_listener/__init__.py b/slack_bolt/lazy_listener/__init__.py index a92c18483..f2e574473 100644 --- a/slack_bolt/lazy_listener/__init__.py +++ b/slack_bolt/lazy_listener/__init__.py @@ -1,23 +1,25 @@ """Lazy listener runner is a beta feature for the apps running on Function-as-a-Service platforms. - def respond_to_slack_within_3_seconds(body, ack): - text = body.get("text") - if text is None or len(text) == 0: - ack(f":x: Usage: /start-process (description here)") - else: - ack(f"Accepted! (task: {body['text']})") +```python +def respond_to_slack_within_3_seconds(body, ack): + text = body.get("text") + if text is None or len(text) == 0: + ack(f":x: Usage: /start-process (description here)") + else: + ack(f"Accepted! (task: {body['text']})") - import time - def run_long_process(respond, body): - time.sleep(5) # longer than 3 seconds - respond(f"Completed! (task: {body['text']})") +import time +def run_long_process(respond, body): + time.sleep(5) # longer than 3 seconds + respond(f"Completed! (task: {body['text']})") - app.command("/start-process")( - # ack() is still called within 3 seconds - ack=respond_to_slack_within_3_seconds, - # Lazy function is responsible for processing the event - lazy=[run_long_process] - ) +app.command("/start-process")( + # ack() is still called within 3 seconds + ack=respond_to_slack_within_3_seconds, + # Lazy function is responsible for processing the event + lazy=[run_long_process] +) +``` Refer to https://docs.slack.dev/tools/bolt-python/concepts/lazy-listeners for more details. """ diff --git a/slack_bolt/middleware/async_middleware.py b/slack_bolt/middleware/async_middleware.py index 163def40a..b4174985e 100644 --- a/slack_bolt/middleware/async_middleware.py +++ b/slack_bolt/middleware/async_middleware.py @@ -22,18 +22,22 @@ async def async_process( """Processes a request data before other middleware and listeners. A middleware calls `next()` function if the chain should continue. - @app.middleware - async def simple_middleware(req, resp, next): - # do something here - await next() + ```python + @app.middleware + async def simple_middleware(req, resp, next): + # do something here + await next() + ``` This `async_process(req, resp, next)` method is supposed to be invoked only inside bolt-python. If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead. - @app.middleware - async def simple_middleware(req, resp, next_): - # do something here - await next_() + ```python + @app.middleware + async def simple_middleware(req, resp, next_): + # do something here + await next_() + ``` Args: req: The incoming request diff --git a/slack_bolt/middleware/middleware.py b/slack_bolt/middleware/middleware.py index 560499d6c..e2e57fb4c 100644 --- a/slack_bolt/middleware/middleware.py +++ b/slack_bolt/middleware/middleware.py @@ -22,18 +22,22 @@ def process( """Processes a request data before other middleware and listeners. A middleware calls `next()` function if the chain should continue. - @app.middleware - def simple_middleware(req, resp, next): - # do something here - next() + ```python + @app.middleware + def simple_middleware(req, resp, next): + # do something here + next() + ``` This `process(req, resp, next)` method is supposed to be invoked only inside bolt-python. If you want to avoid the name `next()` in your middleware functions, you can use `next_()` method instead. - @app.middleware - def simple_middleware(req, resp, next_): - # do something here - next_() + ```python + @app.middleware + def simple_middleware(req, resp, next_): + # do something here + next_() + ``` Args: req: The incoming request diff --git a/slack_bolt/workflows/step/async_step.py b/slack_bolt/workflows/step/async_step.py index 7fa0ed858..46672fb57 100644 --- a/slack_bolt/workflows/step/async_step.py +++ b/slack_bolt/workflows/step/async_step.py @@ -51,17 +51,19 @@ def __init__( This builder is supposed to be used as decorator. - my_step = AsyncWorkflowStep.builder("my_step") - @my_step.edit - async def edit_my_step(ack, configure): - pass - @my_step.save - async def save_my_step(ack, step, update): - pass - @my_step.execute - async def execute_my_step(step, complete, fail): - pass - app.step(my_step) + ```python + my_step = AsyncWorkflowStep.builder("my_step") + @my_step.edit + async def edit_my_step(ack, configure): + pass + @my_step.save + async def save_my_step(ack, step, update): + pass + @my_step.execute + async def execute_my_step(step, complete, fail): + pass + app.step(my_step) + ``` For further information about AsyncWorkflowStep specific function arguments such as `configure`, `update`, `complete`, and `fail`, @@ -95,15 +97,19 @@ def edit( You can use this method as decorator as well. - @my_step.edit - def edit_my_step(ack, configure): - pass + ```python + @my_step.edit + def edit_my_step(ack, configure): + pass + ``` It's also possible to add additional listener matchers and/or middleware - @my_step.edit(matchers=[is_valid], middleware=[update_context]) - def edit_my_step(ack, configure): - pass + ```python + @my_step.edit(matchers=[is_valid], middleware=[update_context]) + def edit_my_step(ack, configure): + pass + ``` For further information about AsyncWorkflowStep specific function arguments such as `configure`, `update`, `complete`, and `fail`, @@ -148,15 +154,19 @@ def save( You can use this method as decorator as well. - @my_step.save - def save_my_step(ack, step, update): - pass + ```python + @my_step.save + def save_my_step(ack, step, update): + pass + ``` It's also possible to add additional listener matchers and/or middleware - @my_step.save(matchers=[is_valid], middleware=[update_context]) - def save_my_step(ack, step, update): - pass + ```python + @my_step.save(matchers=[is_valid], middleware=[update_context]) + def save_my_step(ack, step, update): + pass + ``` For further information about AsyncWorkflowStep specific function arguments such as `configure`, `update`, `complete`, and `fail`, @@ -201,15 +211,19 @@ def execute( You can use this method as decorator as well. - @my_step.execute - def execute_my_step(step, complete, fail): - pass + ```python + @my_step.execute + def execute_my_step(step, complete, fail): + pass + ``` It's also possible to add additional listener matchers and/or middleware - @my_step.save(matchers=[is_valid], middleware=[update_context]) - def execute_my_step(step, complete, fail): - pass + ```python + @my_step.save(matchers=[is_valid], middleware=[update_context]) + def execute_my_step(step, complete, fail): + pass + ``` For further information about AsyncWorkflowStep specific function arguments such as `configure`, `update`, `complete`, and `fail`, diff --git a/slack_bolt/workflows/step/step.py b/slack_bolt/workflows/step/step.py index 4fca25717..95fbda3a3 100644 --- a/slack_bolt/workflows/step/step.py +++ b/slack_bolt/workflows/step/step.py @@ -46,17 +46,19 @@ def __init__( This builder is supposed to be used as decorator. - my_step = WorkflowStep.builder("my_step") - @my_step.edit - def edit_my_step(ack, configure): - pass - @my_step.save - def save_my_step(ack, step, update): - pass - @my_step.execute - def execute_my_step(step, complete, fail): - pass - app.step(my_step) + ```python + my_step = WorkflowStep.builder("my_step") + @my_step.edit + def edit_my_step(ack, configure): + pass + @my_step.save + def save_my_step(ack, step, update): + pass + @my_step.execute + def execute_my_step(step, complete, fail): + pass + app.step(my_step) + ``` For further information about WorkflowStep specific function arguments such as `configure`, `update`, `complete`, and `fail`, @@ -90,15 +92,19 @@ def edit( You can use this method as decorator as well. - @my_step.edit - def edit_my_step(ack, configure): - pass + ```python + @my_step.edit + def edit_my_step(ack, configure): + pass + ``` It's also possible to add additional listener matchers and/or middleware - @my_step.edit(matchers=[is_valid], middleware=[update_context]) - def edit_my_step(ack, configure): - pass + ```python + @my_step.edit(matchers=[is_valid], middleware=[update_context]) + def edit_my_step(ack, configure): + pass + ``` For further information about WorkflowStep specific function arguments such as `configure`, `update`, `complete`, and `fail`, @@ -144,15 +150,19 @@ def save( You can use this method as decorator as well. - @my_step.save - def save_my_step(ack, step, update): - pass + ```python + @my_step.save + def save_my_step(ack, step, update): + pass + ``` It's also possible to add additional listener matchers and/or middleware - @my_step.save(matchers=[is_valid], middleware=[update_context]) - def save_my_step(ack, step, update): - pass + ```python + @my_step.save(matchers=[is_valid], middleware=[update_context]) + def save_my_step(ack, step, update): + pass + ``` For further information about WorkflowStep specific function arguments such as `configure`, `update`, `complete`, and `fail`, @@ -197,15 +207,19 @@ def execute( You can use this method as decorator as well. - @my_step.execute - def execute_my_step(step, complete, fail): - pass + ```python + @my_step.execute + def execute_my_step(step, complete, fail): + pass + ``` It's also possible to add additional listener matchers and/or middleware - @my_step.save(matchers=[is_valid], middleware=[update_context]) - def execute_my_step(step, complete, fail): - pass + ```python + @my_step.save(matchers=[is_valid], middleware=[update_context]) + def execute_my_step(step, complete, fail): + pass + ``` For further information about WorkflowStep specific function arguments such as `configure`, `update`, `complete`, and `fail`, diff --git a/slack_bolt/workflows/step/utilities/async_complete.py b/slack_bolt/workflows/step/utilities/async_complete.py index b73e22aee..f22440e59 100644 --- a/slack_bolt/workflows/step/utilities/async_complete.py +++ b/slack_bolt/workflows/step/utilities/async_complete.py @@ -4,22 +4,24 @@ class AsyncComplete: """`complete()` utility to tell Slack the completion of a step from app execution. - async def execute(step, complete, fail): - inputs = step["inputs"] - # if everything was successful - outputs = { - "task_name": inputs["task_name"]["value"], - "task_description": inputs["task_description"]["value"], - } - await complete(outputs=outputs) + ```python + async def execute(step, complete, fail): + inputs = step["inputs"] + # if everything was successful + outputs = { + "task_name": inputs["task_name"]["value"], + "task_description": inputs["task_description"]["value"], + } + await complete(outputs=outputs) - ws = AsyncWorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, - ) - app.step(ws) + ws = AsyncWorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, + ) + app.step(ws) + ``` This utility is a thin wrapper of workflows.stepCompleted API method. Refer to https://api.slack.com/methods/workflows.stepCompleted for details. diff --git a/slack_bolt/workflows/step/utilities/async_configure.py b/slack_bolt/workflows/step/utilities/async_configure.py index 5b9a7f9ae..839c84ad3 100644 --- a/slack_bolt/workflows/step/utilities/async_configure.py +++ b/slack_bolt/workflows/step/utilities/async_configure.py @@ -7,30 +7,32 @@ class AsyncConfigure: """`configure()` utility to send the modal view in Workflow Builder. - async def edit(ack, step, configure): - await ack() - - blocks = [ - { - "type": "input", - "block_id": "task_name_input", - "element": { - "type": "plain_text_input", - "action_id": "name", - "placeholder": {"type": "plain_text", "text": "Add a task name"}, - }, - "label": {"type": "plain_text", "text": "Task name"}, + ```python + async def edit(ack, step, configure): + await ack() + + blocks = [ + { + "type": "input", + "block_id": "task_name_input", + "element": { + "type": "plain_text_input", + "action_id": "name", + "placeholder": {"type": "plain_text", "text": "Add a task name"}, }, - ] - await configure(blocks=blocks) - - ws = AsyncWorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, - ) - app.step(ws) + "label": {"type": "plain_text", "text": "Task name"}, + }, + ] + await configure(blocks=blocks) + + ws = AsyncWorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, + ) + app.step(ws) + ``` Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details. """ diff --git a/slack_bolt/workflows/step/utilities/async_fail.py b/slack_bolt/workflows/step/utilities/async_fail.py index af200bb65..ea52133cb 100644 --- a/slack_bolt/workflows/step/utilities/async_fail.py +++ b/slack_bolt/workflows/step/utilities/async_fail.py @@ -4,19 +4,21 @@ class AsyncFail: """`fail()` utility to tell Slack the execution failure of a step from app. - async def execute(step, complete, fail): - inputs = step["inputs"] - # if something went wrong - error = {"message": "Just testing step failure!"} - await fail(error=error) + ```python + async def execute(step, complete, fail): + inputs = step["inputs"] + # if something went wrong + error = {"message": "Just testing step failure!"} + await fail(error=error) - ws = AsyncWorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, - ) - app.step(ws) + ws = AsyncWorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, + ) + app.step(ws) + ``` This utility is a thin wrapper of workflows.stepFailed API method. Refer to https://api.slack.com/methods/workflows.stepFailed for details. diff --git a/slack_bolt/workflows/step/utilities/async_update.py b/slack_bolt/workflows/step/utilities/async_update.py index d3409bca3..a555a74f4 100644 --- a/slack_bolt/workflows/step/utilities/async_update.py +++ b/slack_bolt/workflows/step/utilities/async_update.py @@ -4,38 +4,40 @@ class AsyncUpdate: """`update()` utility to tell Slack the processing results of a `save` listener. - async def save(ack, view, update): - await ack() - - values = view["state"]["values"] - task_name = values["task_name_input"]["name"] - task_description = values["task_description_input"]["description"] - - inputs = { - "task_name": {"value": task_name["value"]}, - "task_description": {"value": task_description["value"]} + ```python + async def save(ack, view, update): + await ack() + + values = view["state"]["values"] + task_name = values["task_name_input"]["name"] + task_description = values["task_description_input"]["description"] + + inputs = { + "task_name": {"value": task_name["value"]}, + "task_description": {"value": task_description["value"]} + } + outputs = [ + { + "type": "text", + "name": "task_name", + "label": "Task name", + }, + { + "type": "text", + "name": "task_description", + "label": "Task description", } - outputs = [ - { - "type": "text", - "name": "task_name", - "label": "Task name", - }, - { - "type": "text", - "name": "task_description", - "label": "Task description", - } - ] - await update(inputs=inputs, outputs=outputs) - - ws = AsyncWorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, - ) - app.step(ws) + ] + await update(inputs=inputs, outputs=outputs) + + ws = AsyncWorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, + ) + app.step(ws) + ``` This utility is a thin wrapper of workflows.stepFailed API method. Refer to https://api.slack.com/methods/workflows.updateStep for details. diff --git a/slack_bolt/workflows/step/utilities/complete.py b/slack_bolt/workflows/step/utilities/complete.py index e17d2f024..7a40df00e 100644 --- a/slack_bolt/workflows/step/utilities/complete.py +++ b/slack_bolt/workflows/step/utilities/complete.py @@ -4,22 +4,24 @@ class Complete: """`complete()` utility to tell Slack the completion of a step from app execution. - def execute(step, complete, fail): - inputs = step["inputs"] - # if everything was successful - outputs = { - "task_name": inputs["task_name"]["value"], - "task_description": inputs["task_description"]["value"], - } - complete(outputs=outputs) + ```python + def execute(step, complete, fail): + inputs = step["inputs"] + # if everything was successful + outputs = { + "task_name": inputs["task_name"]["value"], + "task_description": inputs["task_description"]["value"], + } + complete(outputs=outputs) - ws = WorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, - ) - app.step(ws) + ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, + ) + app.step(ws) + ``` This utility is a thin wrapper of workflows.stepCompleted API method. Refer to https://api.slack.com/methods/workflows.stepCompleted for details. diff --git a/slack_bolt/workflows/step/utilities/configure.py b/slack_bolt/workflows/step/utilities/configure.py index 1280be8f7..49fe1e9eb 100644 --- a/slack_bolt/workflows/step/utilities/configure.py +++ b/slack_bolt/workflows/step/utilities/configure.py @@ -7,30 +7,32 @@ class Configure: """`configure()` utility to send the modal view in Workflow Builder. - def edit(ack, step, configure): - ack() - - blocks = [ - { - "type": "input", - "block_id": "task_name_input", - "element": { - "type": "plain_text_input", - "action_id": "name", - "placeholder": {"type": "plain_text", "text": "Add a task name"}, - }, - "label": {"type": "plain_text", "text": "Task name"}, + ```python + def edit(ack, step, configure): + ack() + + blocks = [ + { + "type": "input", + "block_id": "task_name_input", + "element": { + "type": "plain_text_input", + "action_id": "name", + "placeholder": {"type": "plain_text", "text": "Add a task name"}, }, - ] - configure(blocks=blocks) - - ws = WorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, - ) - app.step(ws) + "label": {"type": "plain_text", "text": "Task name"}, + }, + ] + configure(blocks=blocks) + + ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, + ) + app.step(ws) + ``` Refer to https://docs.slack.dev/legacy/legacy-steps-from-apps/ for details. """ diff --git a/slack_bolt/workflows/step/utilities/fail.py b/slack_bolt/workflows/step/utilities/fail.py index b96add08b..4f7f7c081 100644 --- a/slack_bolt/workflows/step/utilities/fail.py +++ b/slack_bolt/workflows/step/utilities/fail.py @@ -4,19 +4,21 @@ class Fail: """`fail()` utility to tell Slack the execution failure of a step from app. - def execute(step, complete, fail): - inputs = step["inputs"] - # if something went wrong - error = {"message": "Just testing step failure!"} - fail(error=error) + ```python + def execute(step, complete, fail): + inputs = step["inputs"] + # if something went wrong + error = {"message": "Just testing step failure!"} + fail(error=error) - ws = WorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, - ) - app.step(ws) + ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, + ) + app.step(ws) + ``` This utility is a thin wrapper of workflows.stepFailed API method. Refer to https://api.slack.com/methods/workflows.stepFailed for details. diff --git a/slack_bolt/workflows/step/utilities/update.py b/slack_bolt/workflows/step/utilities/update.py index bfc81d9d3..f95a0dc03 100644 --- a/slack_bolt/workflows/step/utilities/update.py +++ b/slack_bolt/workflows/step/utilities/update.py @@ -4,38 +4,40 @@ class Update: """`update()` utility to tell Slack the processing results of a `save` listener. - def save(ack, view, update): - ack() - - values = view["state"]["values"] - task_name = values["task_name_input"]["name"] - task_description = values["task_description_input"]["description"] - - inputs = { - "task_name": {"value": task_name["value"]}, - "task_description": {"value": task_description["value"]} + ```python + def save(ack, view, update): + ack() + + values = view["state"]["values"] + task_name = values["task_name_input"]["name"] + task_description = values["task_description_input"]["description"] + + inputs = { + "task_name": {"value": task_name["value"]}, + "task_description": {"value": task_description["value"]} + } + outputs = [ + { + "type": "text", + "name": "task_name", + "label": "Task name", + }, + { + "type": "text", + "name": "task_description", + "label": "Task description", } - outputs = [ - { - "type": "text", - "name": "task_name", - "label": "Task name", - }, - { - "type": "text", - "name": "task_description", - "label": "Task description", - } - ] - update(inputs=inputs, outputs=outputs) - - ws = WorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, - ) - app.step(ws) + ] + update(inputs=inputs, outputs=outputs) + + ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, + ) + app.step(ws) + ``` This utility is a thin wrapper of workflows.stepFailed API method. Refer to https://api.slack.com/methods/workflows.updateStep for details.