From 8368ab8f43a512b48ab82d092d7ba85d96b5873f Mon Sep 17 00:00:00 2001 From: Luke Russell Date: Tue, 29 Oct 2024 16:06:43 -0700 Subject: [PATCH 1/4] docs: intiial --- docs/README.md | 1 - docs/content/basic/action-listening.md | 46 --- docs/content/basic/action-respond.md | 36 -- .../{basic => concepts}/acknowledge.md | 0 docs/content/concepts/actions.md | 73 ++++ .../{advanced => concepts}/adapters.md | 8 +- docs/content/{basic => concepts}/app-home.md | 4 +- docs/content/{basic => concepts}/assistant.md | 14 +- docs/content/{advanced => concepts}/async.md | 17 +- .../authenticating-oauth.md | 9 +- .../{advanced => concepts}/authorization.md | 2 - docs/content/{basic => concepts}/commands.md | 0 .../content/{advanced => concepts}/context.md | 2 - .../{advanced => concepts}/custom-adapters.md | 2 - .../{basic => concepts}/custom-steps.md | 1 + docs/content/{advanced => concepts}/errors.md | 2 - .../{basic => concepts}/event-listening.md | 8 +- .../global-middleware.md | 3 - .../{advanced => concepts}/lazy-listeners.md | 14 +- .../listener-middleware.md | 0 .../content/{advanced => concepts}/logging.md | 2 - .../{basic => concepts}/message-listening.md | 9 +- .../{basic => concepts}/message-sending.md | 9 +- .../{basic => concepts}/opening-modals.md | 4 +- .../select-menu-options.md} | 2 +- docs/content/{basic => concepts}/shortcuts.md | 11 +- .../{basic => concepts}/socket-mode.md | 9 +- docs/content/concepts/steps-from-apps.md | 205 +++++++++++ .../{advanced => concepts}/token-rotation.md | 4 +- .../updating-pushing-views.md | 10 +- .../view-submissions.md} | 12 +- docs/content/{basic => concepts}/web-api.md | 0 docs/content/getting-started.md | 310 ++++++++++++++--- docs/content/steps/adding-editing-steps.md | 62 ---- docs/content/steps/creating-steps.md | 59 ---- docs/content/steps/executing-steps.md | 45 --- docs/content/steps/saving-steps.md | 62 ---- docs/content/steps/steps.md | 29 -- docs/content/tutorial/ai-chatbot.md | 5 +- docs/content/tutorial/getting-started-http.md | 322 ------------------ docs/docusaurus.config.js | 25 +- .../current/basic/action-respond.md | 36 -- .../{basic => concepts}/acknowledge.md | 4 - .../actions.md} | 39 ++- .../{advanced => concepts}/adapters.md | 1 - .../current/{basic => concepts}/app-home.md | 0 .../current/{basic => concepts}/assistant.md | 14 +- .../current/{advanced => concepts}/async.md | 11 +- .../authenticating-oauth.md | 9 +- .../{advanced => concepts}/authorization.md | 0 .../current/{basic => concepts}/commands.md | 0 .../current/{advanced => concepts}/context.md | 0 .../{advanced => concepts}/custom-adapters.md | 1 - .../{basic => concepts}/custom-steps.md | 0 .../current/{advanced => concepts}/errors.md | 0 .../{basic => concepts}/event-listening.md | 10 +- .../global-middleware.md | 0 .../{advanced => concepts}/lazy-listeners.md | 11 +- .../listener-middleware.md | 0 .../current/{advanced => concepts}/logging.md | 0 .../{basic => concepts}/message-listening.md | 8 +- .../{basic => concepts}/message-sending.md | 9 +- .../{basic => concepts}/opening-modals.md | 0 .../select-menu-options.md} | 2 +- .../current/{basic => concepts}/shortcuts.md | 11 +- .../{basic => concepts}/socket-mode.md | 9 +- .../{advanced => concepts}/token-rotation.md | 0 .../updating-pushing-views.md | 0 .../view-submissions.md} | 0 .../current/{basic => concepts}/web-api.md | 0 .../current/getting-started.md | 4 - .../current/legacy/steps-from-apps.md | 193 +++++++++++ .../current/steps/adding-editing-steps.md | 52 --- .../current/steps/creating-steps.md | 48 --- .../current/steps/executing-steps.md | 35 -- .../current/steps/saving-steps.md | 53 --- .../current/steps/steps.md | 17 - .../current/tutorial/getting-started-http.md | 1 - docs/sidebars.js | 109 +++--- docs/src/css/custom.css | 6 + 80 files changed, 906 insertions(+), 1225 deletions(-) delete mode 100644 docs/content/basic/action-listening.md delete mode 100644 docs/content/basic/action-respond.md rename docs/content/{basic => concepts}/acknowledge.md (100%) create mode 100644 docs/content/concepts/actions.md rename docs/content/{advanced => concepts}/adapters.md (59%) rename docs/content/{basic => concepts}/app-home.md (69%) rename docs/content/{basic => concepts}/assistant.md (97%) rename docs/content/{advanced => concepts}/async.md (83%) rename docs/content/{basic => concepts}/authenticating-oauth.md (98%) rename docs/content/{advanced => concepts}/authorization.md (99%) rename docs/content/{basic => concepts}/commands.md (100%) rename docs/content/{advanced => concepts}/context.md (99%) rename docs/content/{advanced => concepts}/custom-adapters.md (99%) rename docs/content/{basic => concepts}/custom-steps.md (99%) rename docs/content/{advanced => concepts}/errors.md (99%) rename docs/content/{basic => concepts}/event-listening.md (95%) rename docs/content/{advanced => concepts}/global-middleware.md (99%) rename docs/content/{advanced => concepts}/lazy-listeners.md (95%) rename docs/content/{advanced => concepts}/listener-middleware.md (100%) rename docs/content/{advanced => concepts}/logging.md (99%) rename docs/content/{basic => concepts}/message-listening.md (93%) rename docs/content/{basic => concepts}/message-sending.md (96%) rename docs/content/{basic => concepts}/opening-modals.md (77%) rename docs/content/{basic/options.md => concepts/select-menu-options.md} (97%) rename docs/content/{basic => concepts}/shortcuts.md (94%) rename docs/content/{basic => concepts}/socket-mode.md (97%) create mode 100644 docs/content/concepts/steps-from-apps.md rename docs/content/{advanced => concepts}/token-rotation.md (92%) rename docs/content/{basic => concepts}/updating-pushing-views.md (66%) rename docs/content/{basic/view_submissions.md => concepts/view-submissions.md} (84%) rename docs/content/{basic => concepts}/web-api.md (100%) delete mode 100644 docs/content/steps/adding-editing-steps.md delete mode 100644 docs/content/steps/creating-steps.md delete mode 100644 docs/content/steps/executing-steps.md delete mode 100644 docs/content/steps/saving-steps.md delete mode 100644 docs/content/steps/steps.md delete mode 100644 docs/content/tutorial/getting-started-http.md delete mode 100644 docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/action-respond.md rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/acknowledge.md (99%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic/action-listening.md => concepts/actions.md} (51%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{advanced => concepts}/adapters.md (99%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/app-home.md (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/assistant.md (99%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{advanced => concepts}/async.md (96%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/authenticating-oauth.md (98%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{advanced => concepts}/authorization.md (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/commands.md (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{advanced => concepts}/context.md (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{advanced => concepts}/custom-adapters.md (99%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/custom-steps.md (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{advanced => concepts}/errors.md (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/event-listening.md (95%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{advanced => concepts}/global-middleware.md (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{advanced => concepts}/lazy-listeners.md (98%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{advanced => concepts}/listener-middleware.md (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{advanced => concepts}/logging.md (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/message-listening.md (94%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/message-sending.md (96%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/opening-modals.md (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic/options.md => concepts/select-menu-options.md} (99%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/shortcuts.md (97%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/socket-mode.md (98%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{advanced => concepts}/token-rotation.md (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/updating-pushing-views.md (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic/view_submissions.md => concepts/view-submissions.md} (100%) rename docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/{basic => concepts}/web-api.md (100%) create mode 100644 docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/legacy/steps-from-apps.md delete mode 100644 docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/adding-editing-steps.md delete mode 100644 docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/creating-steps.md delete mode 100644 docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/executing-steps.md delete mode 100644 docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/saving-steps.md delete mode 100644 docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/steps.md diff --git a/docs/README.md b/docs/README.md index 22a279f04..a1c9283ff 100644 --- a/docs/README.md +++ b/docs/README.md @@ -69,7 +69,6 @@ Then grab the latest version of Node. nvm install node ``` - If you are running this project locally for the first time, you'll need to install the packages with the following command: ``` diff --git a/docs/content/basic/action-listening.md b/docs/content/basic/action-listening.md deleted file mode 100644 index cd677d22d..000000000 --- a/docs/content/basic/action-listening.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Listening to actions -lang: en -slug: /concepts/action-listening ---- - -Your app can listen to user actions, like button clicks, and menu selects, using the `action` method. - -Actions can be filtered on an `action_id` of type `str` or `re.Pattern`. `action_id`s act as unique identifiers for interactive components on the Slack platform. - -You'll notice in all `action()` examples, `ack()` is used. It is required to call the `ack()` function within an action listener to acknowledge that the request was received from Slack. This is discussed in the [acknowledging requests section](/concepts/acknowledge). - -Refer to [the module document](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html) to learn the available listener arguments. -```python -# Your listener will be called every time a block element with the action_id "approve_button" is triggered -@app.action("approve_button") -def update_message(ack): - ack() - # Update the message to reflect the action -``` - -
- -Listening to actions using a constraint object - - -You can use a constraints object to listen to `block_id`s and `action_id`s (or any combination of them). Constraints in the object can be of type `str` or `re.Pattern`. - -```python -# Your function will only be called when the action_id matches 'select_user' AND the block_id matches 'assign_ticket' -@app.action({ - "block_id": "assign_ticket", - "action_id": "select_user" -}) -def update_message(ack, body, client): - ack() - - if "container" in body and "message_ts" in body["container"]: - client.reactions_add( - name="white_check_mark", - channel=body["channel"]["id"], - timestamp=body["container"]["message_ts"], - ) -``` - -
\ No newline at end of file diff --git a/docs/content/basic/action-respond.md b/docs/content/basic/action-respond.md deleted file mode 100644 index 7153f18bd..000000000 --- a/docs/content/basic/action-respond.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: Responding to actions -lang: en -slug: /concepts/action-respond ---- - -There are two main ways to respond to actions. The first (and most common) way is to use `say()`, which sends a message back to the conversation where the incoming request took place. - -The second way to respond to actions is using `respond()`, which is a utility to use the `response_url` associated with the action. - -Refer to [the module document](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html) to learn the available listener arguments. -```python -# Your listener will be called every time an interactive component with the action_id “approve_button” is triggered -@app.action("approve_button") -def approve_request(ack, say): - # Acknowledge action request - ack() - say("Request approved 👍") -``` - -
- -Using respond() - - -Since `respond()` is a utility for calling the `response_url`, it behaves in the same way. You can pass [all the message payload properties](https://api.slack.com/reference/messaging/payload) as keyword arguments along with optional properties like `response_type` (which has a value of `"in_channel"` or `"ephemeral"`), `replace_original`, `delete_original`, `unfurl_links`, and `unfurl_media`. With that, your app can send a new message payload that will be published back to the source of the original interaction. - -```python -# Listens to actions triggered with action_id of “user_select” -@app.action("user_select") -def select_user(ack, action, respond): - ack() - respond(f"You selected <@{action['selected_user']}>") -``` - -
\ No newline at end of file diff --git a/docs/content/basic/acknowledge.md b/docs/content/concepts/acknowledge.md similarity index 100% rename from docs/content/basic/acknowledge.md rename to docs/content/concepts/acknowledge.md diff --git a/docs/content/concepts/actions.md b/docs/content/concepts/actions.md new file mode 100644 index 000000000..b2ab27920 --- /dev/null +++ b/docs/content/concepts/actions.md @@ -0,0 +1,73 @@ +--- +title: Listening & responding to actions +lang: en +slug: /concepts/actions +--- + +Your app can listen and respond to user actions, like button clicks, and menu selects, using the `action` method. + +## Listening to actions + +Actions can be filtered on an `action_id` parameter of type `str` or `re.Pattern`. The `action_id` parameter acts as a unique identifier for interactive components on the Slack platform. + +You'll notice in all `action()` examples, `ack()` is used. It is required to call the `ack()` function within an action listener to acknowledge that the request was received from Slack. This is discussed in the [acknowledging requests guide](/concepts/acknowledge). + +Refer to [the module document](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html) to learn the available listener arguments. + +```python +# Your listener will be called every time a block element with the action_id "approve_button" is triggered +@app.action("approve_button") +def update_message(ack): + ack() + # Update the message to reflect the action +``` + +### Listening to actions using a constraint object + +You can use a constraints object to listen to `block_id`s and `action_id`s (or any combination of them). Constraints in the object can be of type `str` or `re.Pattern`. + +```python +# Your function will only be called when the action_id matches 'select_user' AND the block_id matches 'assign_ticket' +@app.action({ + "block_id": "assign_ticket", + "action_id": "select_user" +}) +def update_message(ack, body, client): + ack() + + if "container" in body and "message_ts" in body["container"]: + client.reactions_add( + name="white_check_mark", + channel=body["channel"]["id"], + timestamp=body["container"]["message_ts"], + ) +``` + +## Responding to actions + +There are two main ways to respond to actions. The first (and most common) way is to use `say()`, which sends a message back to the conversation where the incoming request took place. + +The second way to respond to actions is using `respond()`, which is a utility to use the `response_url` associated with the action. + +Refer to [the module document](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html) to learn the available listener arguments. + +```python +# Your listener will be called every time an interactive component with the action_id “approve_button” is triggered +@app.action("approve_button") +def approve_request(ack, say): + # Acknowledge action request + ack() + say("Request approved 👍") +``` + +### Using `respond()` method + +Since `respond()` is a utility for calling the `response_url`, it behaves in the same way. You can pass [all the message payload properties](https://api.slack.com/reference/messaging/payload) as keyword arguments along with optional properties like `response_type` (which has a value of `"in_channel"` or `"ephemeral"`), `replace_original`, `delete_original`, `unfurl_links`, and `unfurl_media`. With that, your app can send a new message payload that will be published back to the source of the original interaction. + +```python +# Listens to actions triggered with action_id of “user_select” +@app.action("user_select") +def select_user(ack, action, respond): + ack() + respond(f"You selected <@{action['selected_user']}>") +``` \ No newline at end of file diff --git a/docs/content/advanced/adapters.md b/docs/content/concepts/adapters.md similarity index 59% rename from docs/content/advanced/adapters.md rename to docs/content/concepts/adapters.md index e8beb9c97..ad4303b15 100644 --- a/docs/content/advanced/adapters.md +++ b/docs/content/concepts/adapters.md @@ -4,15 +4,13 @@ lang: en slug: /concepts/adapters --- +Adapters are responsible for handling and parsing incoming requests from Slack to conform to [`BoltRequest`](https://github.com/slackapi/bolt-python/blob/main/slack_bolt/request/request.py), then dispatching those requests to your Bolt app. -Adapters are responsible for handling and parsing incoming requests from Slack to conform to `BoltRequest`, then dispatching those requests to your Bolt app. - -By default, Bolt will use the built-in `HTTPServer` adapter. While this is okay for local development, it is not recommended for production. Bolt for Python includes a collection of built-in adapters that can be imported and used with your app. The built-in adapters support a variety of popular Python frameworks including Flask, Django, and Starlette among others. Adapters support the use of any production-ready web server of your choice. +By default, Bolt will use the built-in [`HTTPServer`](https://docs.python.org/3/library/http.server.html) adapter. While this is okay for local development, **it is not recommended for production**. Bolt for Python includes a collection of built-in adapters that can be imported and used with your app. The built-in adapters support a variety of popular Python frameworks including Flask, Django, and Starlette among others. Adapters support the use of any production-ready web server of your choice. To use an adapter, you'll create an app with the framework of your choosing and import its corresponding adapter. Then you'll initialize the adapter instance and call its function that handles and parses incoming requests. -The full list adapters, as well as configuration and sample usage, can be found within the repository's `examples` folder. - +The full list adapters, as well as configuration and sample usage, can be found within the repository's [`examples`](https://github.com/slackapi/bolt-python/tree/main/examples) ```python from slack_bolt import App diff --git a/docs/content/basic/app-home.md b/docs/content/concepts/app-home.md similarity index 69% rename from docs/content/basic/app-home.md rename to docs/content/concepts/app-home.md index a7a6a1f02..887279a5d 100644 --- a/docs/content/basic/app-home.md +++ b/docs/content/concepts/app-home.md @@ -4,9 +4,9 @@ lang: en slug: /concepts/app-home --- -Home tabs are customizable surfaces accessible via the sidebar and search that allow apps to display views on a per-user basis. After enabling App Home within your app configuration, home tabs can be published and updated by passing a `user_id` and view payload to the `views.publish` method. +[Home tabs](https://api.slack.com/surfaces/tabs/using) are customizable surfaces accessible via the sidebar and search that allow apps to display views on a per-user basis. After enabling App Home within your app configuration, home tabs can be published and updated by passing a `user_id` and [view payload](https://api.slack.com/reference/block-kit/views) to the [`views.publish`](https://api.slack.com/methods/views.publish) method. -You can subscribe to the `app_home_opened` event to listen for when users open your App Home. +You can subscribe to the [`app_home_opened`](https://api.slack.com/events/app_home_opened) event to listen for when users open your App Home. Refer to [the module document](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html) to learn the available listener arguments. ```python diff --git a/docs/content/basic/assistant.md b/docs/content/concepts/assistant.md similarity index 97% rename from docs/content/basic/assistant.md rename to docs/content/concepts/assistant.md index 6b39a9b62..e2aabebab 100644 --- a/docs/content/basic/assistant.md +++ b/docs/content/concepts/assistant.md @@ -90,11 +90,9 @@ assistant = Assistant(thread_context_store=FileAssistantThreadContextStore()) Since this reference implementation relies on local files, it's not advised for use in production. For production apps, we recommend creating a class that inherits `AssistantThreadContextStore`. -
+If you want to check full working example app, you can check [our sample repository](https://github.com/slack-samples/bolt-python-assistant-template) on GitHub. - -Block Kit interactions in the assistant thread - +## Block Kit interactions in the assistant thread For advanced use cases, Block Kit buttons may be used instead of suggested prompts, as well as the sending of messages with structured [metadata](https://api.slack.com/metadata) to trigger subsequent interactions with the user. @@ -230,12 +228,6 @@ def respond_to_user_messages(logger: logging.Logger, set_status: SetStatus, say: logger.exception(f"Failed to respond to an inquiry: {e}") say(f":warning: Sorry, something went wrong during processing your request (error: {e})") - # Enable this assistant middleware in your Bolt app app.use(assistant) -``` - -
- - -Lastly, if you want to check full working example app, you can check [our sample repository](https://github.com/slack-samples/bolt-python-assistant-template) on GitHub. \ No newline at end of file +``` \ No newline at end of file diff --git a/docs/content/advanced/async.md b/docs/content/concepts/async.md similarity index 83% rename from docs/content/advanced/async.md rename to docs/content/concepts/async.md index 9544ad810..197377f93 100644 --- a/docs/content/advanced/async.md +++ b/docs/content/concepts/async.md @@ -4,11 +4,9 @@ lang: en slug: /concepts/async --- +To use the async version of Bolt, you can import and initialize an `AsyncApp` instance (rather than `App`). `AsyncApp` relies on [AIOHTTP](https://docs.aiohttp.org) to make API requests, which means you'll need to install `aiohttp` (by adding to `requirements.txt` or running `pip install aiohttp`). -To use the async version of Bolt, you can import and initialize an `AsyncApp` instance (rather than `App`). `AsyncApp` relies on AIOHTTP to make API requests, which means you'll need to install `aiohttp` (by adding to `requirements.txt` or running `pip install aiohttp`). - -Sample async projects can be found within the repository's `examples` folder. - +Sample async projects can be found within the repository's [examples](https://github.com/slackapi/bolt-python/tree/main/examples) folder. ```python # Requirement: install aiohttp @@ -28,12 +26,7 @@ if __name__ == "__main__": app.start(3000) ``` -
- -Using other frameworks - - - +## Using other frameworks Internally `AsyncApp#start()` implements a [`AIOHTTP`](https://docs.aiohttp.org/) web server. If you prefer, you can use a framework other than `AIOHTTP` to handle incoming requests. @@ -48,7 +41,6 @@ pip install slack_bolt sanic uvicorn uvicorn async_app:api --reload --port 3000 --log-level debug ``` - ```python from slack_bolt.async_app import AsyncApp app = AsyncApp() @@ -76,5 +68,4 @@ async def endpoint(req: Request): if __name__ == "__main__": api.run(host="0.0.0.0", port=int(os.environ.get("PORT", 3000))) -``` -
+``` \ No newline at end of file diff --git a/docs/content/basic/authenticating-oauth.md b/docs/content/concepts/authenticating-oauth.md similarity index 98% rename from docs/content/basic/authenticating-oauth.md rename to docs/content/concepts/authenticating-oauth.md index 321803497..734a727b2 100644 --- a/docs/content/basic/authenticating-oauth.md +++ b/docs/content/concepts/authenticating-oauth.md @@ -35,10 +35,7 @@ app = App( ) ``` -
- -Customizing OAuth defaults - +## Customizing OAuth defaults You can override the default OAuth using `oauth_settings`, which can be passed in during the initialization of App. You can override the following: @@ -90,6 +87,4 @@ app = App( callback_options=callback_options, ), ) -``` - -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/content/advanced/authorization.md b/docs/content/concepts/authorization.md similarity index 99% rename from docs/content/advanced/authorization.md rename to docs/content/concepts/authorization.md index 7a67d79ca..4c293b5c2 100644 --- a/docs/content/advanced/authorization.md +++ b/docs/content/concepts/authorization.md @@ -4,7 +4,6 @@ lang: en slug: /concepts/authorization --- - Authorization is the process of determining which Slack credentials should be available while processing an incoming Slack request. Apps installed on a single workspace can simply pass their bot token into the `App` constructor using the `token` parameter. However, if your app will be installed on multiple workspaces, you have two options. The easier option is to use the built-in OAuth support. This will handle setting up OAuth routes and verifying state. Read the section on [authenticating with OAuth](/concepts/authenticating-oauth) for details. @@ -17,7 +16,6 @@ For a more custom solution, you can set the `authorize` parameter to a function - **`enterprise_id`** and **`team_id`**, which can be found in requests sent to your app. - **`user_id`** only when using `user_token`. - ```python import os from slack_bolt import App diff --git a/docs/content/basic/commands.md b/docs/content/concepts/commands.md similarity index 100% rename from docs/content/basic/commands.md rename to docs/content/concepts/commands.md diff --git a/docs/content/advanced/context.md b/docs/content/concepts/context.md similarity index 99% rename from docs/content/advanced/context.md rename to docs/content/concepts/context.md index 34d7819f7..cf7fa45f1 100644 --- a/docs/content/advanced/context.md +++ b/docs/content/concepts/context.md @@ -4,12 +4,10 @@ lang: en slug: /concepts/context --- - All listeners have access to a `context` dictionary, which can be used to enrich requests with additional information. Bolt automatically attaches information that is included in the incoming request, like `user_id`, `team_id`, `channel_id`, and `enterprise_id`. `context` is just a dictionary, so you can directly modify it. - ```python # Listener middleware to fetch tasks from external system using user ID def fetch_tasks(context, event, next): diff --git a/docs/content/advanced/custom-adapters.md b/docs/content/concepts/custom-adapters.md similarity index 99% rename from docs/content/advanced/custom-adapters.md rename to docs/content/concepts/custom-adapters.md index 313173750..55c73130d 100644 --- a/docs/content/advanced/custom-adapters.md +++ b/docs/content/concepts/custom-adapters.md @@ -4,7 +4,6 @@ lang: en slug: /concepts/custom-adapters --- - [Adapters](/concepts/adapters) are flexible and can be adjusted based on the framework you prefer. There are two necessary components of adapters: - `__init__(app: App)`: Constructor that accepts and stores an instance of the Bolt `App`. @@ -23,7 +22,6 @@ Your adapter will return [an instance of `BoltResponse`](https://github.com/slac For more in-depth examples of custom adapters, look at the implementations of the [built-in adapters](https://github.com/slackapi/bolt-python/tree/main/slack_bolt/adapter). - ```python # Necessary imports for Flask from flask import Request, Response, make_response diff --git a/docs/content/basic/custom-steps.md b/docs/content/concepts/custom-steps.md similarity index 99% rename from docs/content/basic/custom-steps.md rename to docs/content/concepts/custom-steps.md index 1eedf9f5d..f91fac33c 100644 --- a/docs/content/basic/custom-steps.md +++ b/docs/content/concepts/custom-steps.md @@ -1,5 +1,6 @@ --- title: Listening and responding to custom steps +sidebar_label: Custom steps lang: en slug: /concepts/custom-steps --- diff --git a/docs/content/advanced/errors.md b/docs/content/concepts/errors.md similarity index 99% rename from docs/content/advanced/errors.md rename to docs/content/concepts/errors.md index 59601f47b..d0e5cccad 100644 --- a/docs/content/advanced/errors.md +++ b/docs/content/concepts/errors.md @@ -4,12 +4,10 @@ lang: en slug: /concepts/errors --- - If an error occurs in a listener, you can handle it directly using a try/except block. Errors associated with your app will be of type `BoltError`. Errors associated with calling Slack APIs will be of type `SlackApiError`. By default, the global error handler will log all non-handled exceptions to the console. To handle global errors yourself, you can attach a global error handler to your app using the `app.error(fn)` function. - ```python @app.error def custom_error_handler(error, body, logger): diff --git a/docs/content/basic/event-listening.md b/docs/content/concepts/event-listening.md similarity index 95% rename from docs/content/basic/event-listening.md rename to docs/content/concepts/event-listening.md index 95c6e84ea..79317b07a 100644 --- a/docs/content/basic/event-listening.md +++ b/docs/content/concepts/event-listening.md @@ -18,11 +18,8 @@ def ask_for_introduction(event, say): text = f"Welcome to the team, <@{user_id}>! 🎉 You can introduce yourself in this channel." say(text=text, channel=welcome_channel_id) ``` -
- - Filtering on message subtypes - +## Filtering on message subtypes The `message()` listener is equivalent to `event("message")`. @@ -38,5 +35,4 @@ You can explicitly filter for events without a subtype by explicitly setting `No def log_message_change(logger, event): user, text = event["user"], event["text"] logger.info(f"The user {user} changed the message to {text}") -``` -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/content/advanced/global-middleware.md b/docs/content/concepts/global-middleware.md similarity index 99% rename from docs/content/advanced/global-middleware.md rename to docs/content/concepts/global-middleware.md index 61aa97066..ec748c000 100644 --- a/docs/content/advanced/global-middleware.md +++ b/docs/content/concepts/global-middleware.md @@ -4,13 +4,10 @@ lang: en slug: /concepts/global-middleware --- - Global middleware is run for all incoming requests, before any listener middleware. You can add any number of global middleware to your app by passing middleware functions to `app.use()`. Middleware functions are called with the same arguments as listeners, with an additional `next()` function. Both global and listener middleware must call `next()` to pass control of the execution chain to the next middleware. - - Refer to [the module document](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html) to learn the available listener arguments. ```python @app.use diff --git a/docs/content/advanced/lazy-listeners.md b/docs/content/concepts/lazy-listeners.md similarity index 95% rename from docs/content/advanced/lazy-listeners.md rename to docs/content/concepts/lazy-listeners.md index e179c6afc..d72c2f9c0 100644 --- a/docs/content/advanced/lazy-listeners.md +++ b/docs/content/concepts/lazy-listeners.md @@ -4,7 +4,6 @@ lang: en slug: /concepts/lazy-listeners --- - Lazy Listeners are a feature which make it easier to deploy Slack apps to FaaS (Function-as-a-Service) environments. Please note that this feature is only available in Bolt for Python, and we are not planning to add the same to other Bolt frameworks. Typically when handling actions, commands, shortcuts, options and view submissions, you must acknowledge the request from Slack by calling `ack()` within 3 seconds. Calling `ack()` results in sending an HTTP 200 OK response to Slack, letting Slack know that you're handling the response. We normally encourage you to do this as the very first step in your handler function. @@ -15,7 +14,6 @@ To allow you to still run more time-consuming processes as part of your handler, * `ack: Callable`: Responsible for calling `ack()` within 3 seconds * `lazy: List[Callable]`: Responsible for handling time-consuming processes related to the request. The lazy function does not have access to `ack()`. - ```python def respond_to_slack_within_3_seconds(body, ack): text = body.get("text") @@ -37,13 +35,9 @@ app.command("/start-process")( ) ``` -
- -Example with AWS Lambda - - +## Example with AWS Lambda -This example deploys the code to [AWS Lambda](https://aws.amazon.com/lambda/). There are more examples within the [`examples` folder](https://github.com/slackapi/bolt-python/tree/main/examples/aws_lambda). +This example deploys the code to [AWS Lambda](https://aws.amazon.com/lambda/). There are more examples within the [`examples`](https://github.com/slackapi/bolt-python/tree/main/examples/aws_lambda) folder. ```bash pip install slack_bolt @@ -61,7 +55,6 @@ echo 'slack_bolt' > requirements.txt lambda deploy --config-file config.yaml --requirements requirements.txt ``` - ```python from slack_bolt import App from slack_bolt.adapter.aws_lambda import SlackRequestHandler @@ -108,5 +101,4 @@ Please note that the following IAM permissions would be required for running thi } ] } -``` -
+``` \ No newline at end of file diff --git a/docs/content/advanced/listener-middleware.md b/docs/content/concepts/listener-middleware.md similarity index 100% rename from docs/content/advanced/listener-middleware.md rename to docs/content/concepts/listener-middleware.md diff --git a/docs/content/advanced/logging.md b/docs/content/concepts/logging.md similarity index 99% rename from docs/content/advanced/logging.md rename to docs/content/concepts/logging.md index 900484b7a..5f82d168a 100644 --- a/docs/content/advanced/logging.md +++ b/docs/content/concepts/logging.md @@ -4,12 +4,10 @@ lang: en slug: /concepts/logging --- - By default, Bolt will log information from your app to the output destination. After you've imported the `logging` module, you can customize the root log level by passing the `level` parameter to `basicConfig()`. The available log levels in order of least to most severe are `debug`, `info`, `warning`, `error`, and `critical`. Outside of a global context, you can also log a single message corresponding to a specific level. Because Bolt uses Python’s [standard logging module](https://docs.python.org/3/library/logging.html), you can use any its features. - ```python import logging diff --git a/docs/content/basic/message-listening.md b/docs/content/concepts/message-listening.md similarity index 93% rename from docs/content/basic/message-listening.md rename to docs/content/concepts/message-listening.md index 0243b1537..3527dc226 100644 --- a/docs/content/basic/message-listening.md +++ b/docs/content/concepts/message-listening.md @@ -22,10 +22,7 @@ def say_hello(message, say): say(f"Hi there, <@{user}>!") ``` -
- -Using a regular expression pattern - +## Using a regular expression pattern The `re.compile()` method can be used instead of a string for more granular matching. @@ -37,6 +34,4 @@ def say_hello_regex(say, context): # regular expression matches are inside of context.matches greeting = context['matches'][0] say(f"{greeting}, how are you?") -``` - -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/content/basic/message-sending.md b/docs/content/concepts/message-sending.md similarity index 96% rename from docs/content/basic/message-sending.md rename to docs/content/concepts/message-sending.md index d7b5d2da9..b44f8848f 100644 --- a/docs/content/basic/message-sending.md +++ b/docs/content/concepts/message-sending.md @@ -16,10 +16,7 @@ def ask_who(message, say): say("_Who's there?_") ``` -
- -Sending a message with blocks - +## Sending a message with blocks `say()` accepts more complex message payloads to make it easy to add functionality and structure to your messages. @@ -45,6 +42,4 @@ def show_datepicker(event, say): blocks=blocks, text="Pick a date for me to remind you" ) -``` - -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/content/basic/opening-modals.md b/docs/content/concepts/opening-modals.md similarity index 77% rename from docs/content/basic/opening-modals.md rename to docs/content/concepts/opening-modals.md index 9049a5bdb..a686eec63 100644 --- a/docs/content/basic/opening-modals.md +++ b/docs/content/concepts/opening-modals.md @@ -4,9 +4,9 @@ lang: en slug: /concepts/opening-modals --- -[Modals](https://api.slack.com/block-kit/surfaces/modal) are focused surfaces that allow you to collect user data and display dynamic information. You can open a modal by passing a valid `trigger_id` and a [view payload](https://api.slack.com/reference/block-kit/views) to the built-in client's [`views.open`](https://api.slack.com/methods/views.open) method. +[Modals](https://api.slack.com/block-kit/surfaces/modals) are focused surfaces that allow you to collect user data and display dynamic information. You can open a modal by passing a valid `trigger_id` and a [view payload](https://api.slack.com/reference/block-kit/views) to the built-in client's [`views.open`](https://api.slack.com/methods/views.open) method. -Your app receives `trigger_id`s in payloads sent to your Request URL that are triggered by user invocations, like a shortcut, button press, or interaction with a select menu. +Your app receives `trigger_id` parameters in payloads sent to your Request URL triggered user invocation like a slash command, button press, or interaction with a select menu. Read more about modal composition in the [API documentation](https://api.slack.com/surfaces/modals/using#composing_views). diff --git a/docs/content/basic/options.md b/docs/content/concepts/select-menu-options.md similarity index 97% rename from docs/content/basic/options.md rename to docs/content/concepts/select-menu-options.md index e7c1e1243..835ae15c7 100644 --- a/docs/content/basic/options.md +++ b/docs/content/concepts/select-menu-options.md @@ -1,5 +1,5 @@ --- -title: Listening and responding to options +title: Listening & responding to select menu options lang: en slug: /concepts/options --- diff --git a/docs/content/basic/shortcuts.md b/docs/content/concepts/shortcuts.md similarity index 94% rename from docs/content/basic/shortcuts.md rename to docs/content/concepts/shortcuts.md index 6f469c20f..d9f02c2a1 100644 --- a/docs/content/basic/shortcuts.md +++ b/docs/content/concepts/shortcuts.md @@ -53,11 +53,9 @@ def open_modal(ack, shortcut, client): ) ``` -
- - Listening to shortcuts using a constraint object - - You can use a constraints object to listen to `callback_id`s, and `type`s. Constraints in the object can be of type `str` or `re.Pattern`. +## Listening to shortcuts using a constraint object + +You can use a constraints object to listen to `callback_id`s, and `type`s. Constraints in the object can be of type `str` or `re.Pattern`. ```python # Your listener will only be called when the callback_id matches 'open_modal' AND the type matches 'message_action' @@ -92,5 +90,4 @@ def open_modal(ack, shortcut, client): ] } ) -``` -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/content/basic/socket-mode.md b/docs/content/concepts/socket-mode.md similarity index 97% rename from docs/content/basic/socket-mode.md rename to docs/content/concepts/socket-mode.md index 61be345de..72a2b7982 100644 --- a/docs/content/basic/socket-mode.md +++ b/docs/content/concepts/socket-mode.md @@ -17,7 +17,6 @@ While we recommend using [the built-in Socket Mode adapter](https://github.com/s |[aiohttp](https://pypi.org/project/aiohttp/) (asyncio-based)|[slack_bolt.adapter.socket_mode.aiohttp](https://github.com/slackapi/bolt-python/tree/main/slack_bolt/adapter/socket_mode/aiohttp)| |[websockets](https://pypi.org/project/websockets/) (asyncio-based)|[slack_bolt.adapter.socket_mode.websockets](https://github.com/slackapi/bolt-python/tree/main/slack_bolt/adapter/socket_mode/websockets)| - ```python import os from slack_bolt import App @@ -35,10 +34,7 @@ if __name__ == "__main__": handler.start() ``` -
- -Using Async (asyncio) - +## Using Async (asyncio) To use the asyncio-based adapters such as aiohttp, your whole app needs to be compatible with asyncio's async/await programming model. `AsyncSocketModeHandler` is available for running `AsyncApp` and its async middleware and listeners. @@ -60,5 +56,4 @@ async def main(): if __name__ == "__main__": import asyncio asyncio.run(main()) -``` -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/content/concepts/steps-from-apps.md b/docs/content/concepts/steps-from-apps.md new file mode 100644 index 000000000..728ec8e65 --- /dev/null +++ b/docs/content/concepts/steps-from-apps.md @@ -0,0 +1,205 @@ +--- +title: Steps from apps +lang: en +slug: /concepts/steps-from-apps +--- + +:::danger + +Steps from apps are a deprecated feature. + +Steps from apps are different than, and not interchangeable with, Slack automation workflows. We encourage those who are currently publishing steps from apps to consider the new [Slack automation features](https://api.slack.com/automation), such as [custom steps for Bolt](https://api.slack.com/automation/functions/custom-bolt), + +Please [read the Slack API changelog entry](https://api.slack.com/changelog/2023-08-workflow-steps-from-apps-step-back) for more information. + +::: + +Steps from apps allow your app to create and process steps that users can add using [Workflow Builder](https://api.slack.com/workflows). + +Steps from apps are made up of three distinct user events: + +- Adding or editing the step in a Workflow +- Saving or updating the step's configuration +- The end user's execution of the step + +All three events must be handled for a step from app to function. + +Read more about steps from apps in the [API documentation](https://api.slack.com/workflows/steps). + +## Creating steps from apps + +To create a step from app, Bolt provides the `WorkflowStep` class. + +When instantiating a new `WorkflowStep`, pass in the step's `callback_id` and a configuration object. + +The configuration object contains three keys: `edit`, `save`, and `execute`. Each of these keys must be a single callback or a list of callbacks. All callbacks have access to a `step` object that contains information about the step from app event. + +After instantiating a `WorkflowStep`, you can pass it into `app.step()`. Behind the scenes, your app will listen and respond to the step’s events using the callbacks provided in the configuration object. + +Alternatively, steps from apps can also be created using the `WorkflowStepBuilder` class alongside a decorator pattern. For more information, including an example of this approach, [refer to the documentation](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/workflows/step/step.html#slack_bolt.workflows.step.step.WorkflowStepBuilder). + +Refer to the module documents ([common](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html) / [step-specific](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/workflows/step/utilities/index.html)) to learn the available arguments. + +```python +import os +from slack_bolt import App +from slack_bolt.workflows.step import WorkflowStep + +# Initiate the Bolt app as you normally would +app = App( + token=os.environ.get("SLACK_BOT_TOKEN"), + signing_secret=os.environ.get("SLACK_SIGNING_SECRET") +) + +def edit(ack, step, configure): + pass + +def save(ack, view, update): + pass + +def execute(step, complete, fail): + pass + +# Create a new WorkflowStep instance +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) + +# Pass Step to set up listeners +app.step(ws) +``` + +## Adding or editing steps from apps + +When a builder adds (or later edits) your step in their workflow, your app will receive a [`workflow_step_edit` event](https://api.slack.com/reference/workflows/workflow_step_edit). The `edit` callback in your `WorkflowStep` configuration will be run when this event is received. + +Whether a builder is adding or editing a step, you need to send them a [step from app configuration modal](https://api.slack.com/reference/workflows/configuration-view). This modal is where step-specific settings are chosen, and it has more restrictions than typical modals—most notably, it cannot include `title`, `submit`, or `close` properties. By default, the configuration modal's `callback_id` will be the same as the step from app. + +Within the `edit` callback, the `configure()` utility can be used to easily open your step's configuration modal by passing in the view's blocks with the corresponding `blocks` argument. To disable saving the configuration before certain conditions are met, you can also pass in `submit_disabled` with a value of `True`. + +To learn more about opening configuration modals, [read the documentation](https://api.slack.com/workflows/steps#handle_config_view). + +Refer to the module documents ([common](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html) / [step-specific](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/workflows/step/utilities/index.html)) to learn the available arguments. + +```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"}, + }, + { + "type": "input", + "block_id": "task_description_input", + "element": { + "type": "plain_text_input", + "action_id": "description", + "placeholder": {"type": "plain_text", "text": "Add a task description"}, + }, + "label": {"type": "plain_text", "text": "Task description"}, + }, + ] + configure(blocks=blocks) + +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +## Saving step configurations + +After the configuration modal is opened, your app will listen for the `view_submission` event. The `save` callback in your `WorkflowStep` configuration will be run when this event is received. + +Within the `save` callback, the `update()` method can be used to save the builder's step configuration by passing in the following arguments: + +- `inputs` is a dictionary representing the data your app expects to receive from the user upon step execution. +- `outputs` is a list of objects containing data that your app will provide upon the step's completion. Outputs can then be used in subsequent steps of the workflow. +- `step_name` overrides the default Step name +- `step_image_url` overrides the default Step image + +To learn more about how to structure these parameters, [read the documentation](https://api.slack.com/reference/workflows/workflow_step). + +Refer to the module documents ([common](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html) / [step-specific](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/workflows/step/utilities/index.html)) to learn the available arguments. + +```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) +``` + +## Executing steps from app + +When your step from app is executed by an end user, your app will receive a [`workflow_step_execute` event](https://api.slack.com/events/workflow_step_execute). The `execute` callback in your `WorkflowStep` configuration will be run when this event is received. + +Using the `inputs` from the `save` callback, this is where you can make third-party API calls, save information to a database, update the user's Home tab, or decide the outputs that will be available to subsequent steps from apps by mapping values to the `outputs` object. + +Within the `execute` callback, your app must either call `complete()` to indicate that the step's execution was successful, or `fail()` to indicate that the step's execution failed. + +Refer to the module documents ([common](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html) / [step-specific](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/workflows/step/utilities/index.html)) to learn the available arguments. + +```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) + + # 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) +``` diff --git a/docs/content/advanced/token-rotation.md b/docs/content/concepts/token-rotation.md similarity index 92% rename from docs/content/advanced/token-rotation.md rename to docs/content/concepts/token-rotation.md index 1f278c3aa..ca690dd28 100644 --- a/docs/content/advanced/token-rotation.md +++ b/docs/content/concepts/token-rotation.md @@ -4,12 +4,10 @@ lang: en slug: /concepts/token-rotation --- - Supported in Bolt for Python as of [v1.7.0](https://github.com/slackapi/bolt-python/releases/tag/v1.7.0), token rotation provides an extra layer of security for your access tokens and is defined by the [OAuth V2 RFC](https://datatracker.ietf.org/doc/html/rfc6749#section-10.4). Instead of an access token representing an existing installation of your Slack app indefinitely, with token rotation enabled, access tokens expire. A refresh token acts as a long-lived way to refresh your access tokens. Bolt for Python supports and will handle token rotation automatically so long as the [built-in OAuth](/concepts/authenticating-oauth) functionality is used. -For more information about token rotation, please see the [documentation](https://api.slack.com/authentication/rotation). - +For more information about token rotation, please see the [documentation](https://api.slack.com/authentication/rotation). \ No newline at end of file diff --git a/docs/content/basic/updating-pushing-views.md b/docs/content/concepts/updating-pushing-views.md similarity index 66% rename from docs/content/basic/updating-pushing-views.md rename to docs/content/concepts/updating-pushing-views.md index 8cc45d49a..d7a9e3a3e 100644 --- a/docs/content/basic/updating-pushing-views.md +++ b/docs/content/concepts/updating-pushing-views.md @@ -4,17 +4,17 @@ lang: en slug: /concepts/updating-pushing-views --- -Modals contain a stack of views. When you call `views_open`, you add the root view to the modal. After the initial call, you can dynamically update a view by calling `views_update`, or stack a new view on top of the root view by calling `views_push`. +Modals contain a stack of views. When you call [`views_open`](https://api.slack.com/methods/views.open), you add the root view to the modal. After the initial call, you can dynamically update a view by calling [`views_update`](https://api.slack.com/methods/views.update), or stack a new view on top of the root view by calling [`views_push`](https://api.slack.com/methods/views.push) -**`views_update`** +## The `views_update` method To update a view, you can use the built-in client to call `views_update` with the `view_id` that was generated when you opened the view, and a new `view` including the updated `blocks` list. If you're updating the view when a user interacts with an element inside of an existing view, the `view_id` will be available in the `body` of the request. -**`views_push`** +## The `views_push` method -To push a new view onto the view stack, you can use the built-in client to call `views_push` with a valid `trigger_id` a new view payload. The arguments for `views_push` is the same as opening modals. After you open a modal, you may only push two additional views onto the view stack. +To push a new view onto the view stack, you can use the built-in client to call `views_push` with a valid `trigger_id` a new [view payload](https://api.slack.com/reference/block-kit/views). The arguments for `views_push` is the same as [opening modals](/concepts/creating-models). After you open a modal, you may only push two additional views onto the view stack. -Learn more about updating and pushing views in our API documentation. +Learn more about updating and pushing views in our [API documentation](https://api.slack.com/surfaces/modals/using#modifying) Refer to [the module document](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html) to learn the available listener arguments. ```python diff --git a/docs/content/basic/view_submissions.md b/docs/content/concepts/view-submissions.md similarity index 84% rename from docs/content/basic/view_submissions.md rename to docs/content/concepts/view-submissions.md index b1c3e7cef..a22911e71 100644 --- a/docs/content/basic/view_submissions.md +++ b/docs/content/concepts/view-submissions.md @@ -4,9 +4,7 @@ lang: en slug: /concepts/view_submissions --- - - -If a view payload contains any input blocks, you must listen to `view_submission` requests to receive their values. To listen to `view_submission` requests, you can use the built-in `view()` method. `view()` requires a `callback_id` of type `str` or `re.Pattern`. +If a [view payload](https://api.slack.com/reference/block-kit/views) contains any input blocks, you must listen to `view_submission` requests to receive their values. To listen to `view_submission` requests, you can use the built-in `view()` method. `view()` requires a `callback_id` of type `str` or `re.Pattern`. You can access the value of the `input` blocks by accessing the `state` object. `state` contains a `values` object that uses the `block_id` and unique `action_id` to store the input values. @@ -26,7 +24,8 @@ def handle_submission(ack, body): ack(response_action="update", view=build_new_view(body)) ``` Similarly, there are options for [displaying errors](https://api.slack.com/surfaces/modals/using#displaying_errors) in response to view submissions. -Read more about view submissions in our API documentation. + +Read more about view submissions in our [API documentation](https://api.slack.com/surfaces/modals/using#handling_submissions) --- @@ -34,7 +33,7 @@ Read more about view submissions in our API documentation for more information about view_closed. +See the [API documentation](https://api.slack.com/surfaces/modals/using#modal_cancellations) for more information about `view_closed`. ```python @@ -63,9 +62,6 @@ def handle_view_closed(ack, body, logger): logger.info(body) ``` - - - Refer to [the module document](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html) to learn the available listener arguments. ```python # Handle a view_submission request diff --git a/docs/content/basic/web-api.md b/docs/content/concepts/web-api.md similarity index 100% rename from docs/content/basic/web-api.md rename to docs/content/concepts/web-api.md diff --git a/docs/content/getting-started.md b/docs/content/getting-started.md index 79ccfff61..f86572391 100644 --- a/docs/content/getting-started.md +++ b/docs/content/getting-started.md @@ -1,30 +1,25 @@ --- -title: Getting started +title: Getting started with Bolt for Python +sidebar_label: Getting started slug: getting-started lang: en --- -# Getting started with Bolt for Python - This guide is meant to walk you through getting up and running with a Slack app using Bolt for Python. Along the way, we’ll create a new Slack app, set up your local environment, and develop an app that listens and responds to messages from a Slack workspace. - -When you're finished, you'll have this ⚡️[Getting Started with Slack app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started) to run, modify, and make your own. The possibilities are endless! - -:::info - -For this guide, we are going to be using [Socket Mode](https://api.slack.com/apis/connections/socket), our recommended option for those just getting started and building something for their team. If you already know you're going to want to use HTTP as your app's communication protocol, head over to our parallel guide, [Getting Started over HTTP](/tutorial/getting-started-http). - -::: +When you're finished, you'll have this ⚡️[Getting Started with Slack app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started) to run, modify, and make your own. --- -### Create an app {#create-an-app} -First thing's first: before you start developing with Bolt, you'll want to [create a Slack app](https://api.slack.com/apps/new). +## Create an app {#create-an-app} + +Before you start developing with Bolt, you'll want to [create a Slack app](https://api.slack.com/apps/new). + +[`chat.message`](https://api.slack.com/scopes) :::tip -We recommend using a workspace where you won't disrupt real work getting done — [you can create a new one for free](https://slack.com/get-started#create). +We recommend using a workspace where you won't disrupt real work getting done. Join the [Developer Program](https://api.slack.com/developer-program) and provision a sandbox with access to all Slack features for free. ::: @@ -38,7 +33,8 @@ Look around, add an app icon and description, and then let's start configuring y --- -### Tokens and installing apps {#tokens-and-installing-apps} +## Tokens and installing apps {#tokens-and-installing-apps} + Slack apps use [OAuth to manage access to Slack's APIs](https://api.slack.com/docs/oauth). When an app is installed, you'll receive a token that the app can use to call API methods. There are three main token types available to a Slack app: user (`xoxp`), bot (`xoxb`), and app-level (`xapp`) tokens. @@ -46,7 +42,7 @@ There are three main token types available to a Slack app: user (`xoxp`), bot (` - [Bot tokens](https://api.slack.com/authentication/token-types#bot) are associated with bot users, and are only granted once in a workspace where someone installs the app. The bot token your app uses will be the same no matter which user performed the installation. Bot tokens are the token type that _most_ apps use. - [App-level tokens](https://api.slack.com/authentication/token-types#app) represent your app across organizations, including installations by all individual users on all workspaces in a given organization and are commonly used for creating WebSocket connections to your app. -We're going to use bot and app-level tokens for this guide. +We're going to use bot tokens for this guide. 1. Navigate to the **OAuth & Permissions** on the left sidebar and scroll down to the **Bot Token Scopes** section. Click **Add an OAuth Scope**. @@ -54,24 +50,47 @@ We're going to use bot and app-level tokens for this guide. 3. Scroll up to the top of the **OAuth & Permissions** page and click **Install App to Workspace**. You'll be led through Slack's OAuth UI, where you should allow your app to be installed to your development workspace. -4. Once you authorize the installation, you'll land on the **OAuth & Permissions** page and see a **Bot User OAuth Access Token**. +4. Once you authorize the installation, you'll land on the **OAuth & Permissions** page and see a **Bot User OAuth Access Token**. Save it for later. ![OAuth Tokens](/img/boltpy/bot-token.png "Bot OAuth Token") -5. Then head over to **Basic Information** and scroll down under the App Token section and click **Generate Token and Scopes** to generate an app-level token. Add the `connections:write` scope to this token and save the generated `xapp` token, we'll use both these tokens in just a moment. +:::info -6. Navigate to **Socket Mode** on the left side menu and toggle to enable. +Treat your token like a password and [keep it safe](https://api.slack.com/docs/oauth-safety). Your app uses it to post and retrieve information from Slack workspaces. +::: -:::tip +### Using Socket Mode or HTTP -Treat your tokens like passwords and [keep them safe](https://api.slack.com/docs/oauth-safety). Your app uses tokens to post and retrieve information from Slack workspaces. +To listen for events happening in a Slack workspace (like when a message is posted or when a reaction is posted to a message) you'll use the [Events API to subscribe to event types](https://api.slack.com/events-api). -::: +For those just starting, we recommend using [Socket Mode](https://api.slack.com/apis/connections/socket). Socket Mode allows your app to use the Events API and interactive features without exposing a public HTTP Request URL. This can be helpful during development, or if you're receiving requests from behind a firewall. ---- +That being said, you're welcome to set up an app with a public HTTP Request URL. HTTP is more useful for apps being deployed to hosting environments (like [AWS](/deployments/aws-lambda) or [Heroku](/deployments/heroku) to stably respond within a large corporate Slack workspaces/organization, or apps intended for distribution via the Slack Marketplace. + +We've provided instructions for both ways in this guide. + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + + +If you're using Socket Mode, you'll also need an app-level token. + +Head over to **Basic Information** and scroll down under the App Token section and click **Generate Token and Scopes** to generate an app-level token. Add the `connections:write` scope to this token and save the generated `xapp` token — you'll need it for later. -### Setting up your project {#setting-up-your-project} + + + +If you're using HTTP, you'll also need a _signing secret_ that was generated when you configured your app. + +Head over to **Basic Information** and save your _signing Secret_ — you'll need it for later. + + + + +## Setting up your project {#setting-up-your-project} With the initial configuration handled, it's time to set up a new Bolt project. This is where you'll write the code that handles the logic for your app. If you don’t already have a project, let’s create a new one. Create an empty directory: @@ -95,18 +114,33 @@ which python3 # Output: /path/to/first-bolt-app/.venv/bin/python3 ``` -Before we install the Bolt for Python package to your new project, let's save the **bot token** and **app-level token** that were generated when you configured your app. +Copy your _bot (xoxb) token_ from the **OAuth & Permissions** page and store it as a new environment variable. -1. **Copy your bot (xoxb) token from the OAuth & Permissions page** and store it in a new environment variable. The following example works on Linux and macOS; but [similar commands are available on Windows](https://superuser.com/questions/212150/how-to-set-env-variable-in-windows-cmd-line/212153#212153). ```shell -export SLACK_BOT_TOKEN=xoxb- +export SLACK_BOT_TOKEN= ``` -2. **Copy your app-level (xapp) token from the Basic Information page** and then store it in a new environment variable. + + + +Store your _app-level (xapp) token_ as a new environment variable. + ```shell export SLACK_APP_TOKEN= ``` + + + +Store your _signing secret_ as a new environment variable. + +```shell +export SLACK_SIGNING_SECRET= +``` + + + + :::warning Keep all tokens secure. At a minimum, you should avoid checking them into public version control, and access them via environment variables as we've done above. Checkout the API documentation for more on [best practices for app security](https://api.slack.com/authentication/best-practices). @@ -121,6 +155,9 @@ pip install slack_bolt Create a new file called `app.py` in this directory and add the following code: + + + ```python import os from slack_bolt import App @@ -134,7 +171,28 @@ if __name__ == "__main__": SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start() ``` -Your tokens are enough to create your first Bolt app. Save your `app.py` file then on the command line run the following: + + + +```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") +) + +# Start your app +if __name__ == "__main__": + app.start(port=int(os.environ.get("PORT", 3000))) +``` + + + + +Save your `app.py` file then on the command line run the following: ```script python3 app.py @@ -144,22 +202,41 @@ Your app should let you know that it's up and running. 🎉 --- -### Setting up events {#setting-up-events} -Your app behaves similarly to people on your team — it can post messages, add emoji reactions, and listen and respond to events. +## Setting up events {#setting-up-events} -To listen for events happening in a Slack workspace (like when a message is posted or when a reaction is posted to a message) you'll use the [Events API to subscribe to event types](https://api.slack.com/events-api). +Your app behaves similarly to people on your team — it can post messages, add emoji reactions, and listen and respond to events. It's time to tell Slack what events we'd like to listen for. -:::info +When an event occurs, Slack will send your app some information about the event, like the user that triggered it and the channel it occurred in. Your app will process the details and can respond accordingly. + +Let's enable events for your app. -Earlier in this tutorial we enabled Socket Mode. Socket Mode lets apps use the Events API and interactive components without exposing a public HTTP endpoint. This can be helpful during development, or if you're receiving requests from behind a firewall. HTTP is more useful for apps being deployed to hosting environments, or apps intended for distribution via the Slack App Directory. To follow this getting started guide with HTTP instead, head over [here](/tutorial/getting-started-http). + + + +1. Head to your app's app settings page (click on the app [from the app settings page](https://api.slack.com/apps)). Navigate to **Socket Mode** on the left side menu and toggle to enable. + +2. Go to **Basic Information** and scroll down under the App Token section and click **Generate Token and Scopes** to generate an app token. Add the `connections:write` scope to this token and save the generated `xapp` token, we'll use that in just a moment. + +3. Go to **Event Subscriptions** via the left sidebar. Toggle the switch labeled **Enable Events**. + + + + +1. Go to **Event Subscriptions** via the left sidebar. Toggle the switch labeled **Enable Events**. + +2. Add your Request URL. Slack will send HTTP POST requests corresponding to events to this [Request URL](https://api.slack.com/apis/connections/events-api#the-events-api__subscribing-to-event-types__events-api-request-urls) endpoint. Bolt uses the `/slack/events` path to listen to all incoming requests (whether shortcuts, events, or interactivity payloads). When configuring your Request URL within your app configuration, you'll append `/slack/events`, e.g. `https:///slack/events`. 💡 As long as your Bolt app is still running, your URL should become verified. + +:::info + +For local development, you can use a proxy service like [ngrok](https://ngrok.com/) to create a public URL and tunnel requests to your development environment. Refer to [ngrok's getting started guide](https://ngrok.com/docs#getting-started-expose) on how to create this tunnel. ::: -It's time to tell Slack what events we'd like to listen for. + + -When an event occurs, Slack will send your app some information about the event, like the user that triggered it and the channel it occurred in. Your app will process the details and can respond accordingly. +Under **Subscribe to Bot Events**, you can add events for your bot to respond to. There are four events related to messages: -Navigate to **Event Subscriptions** on the left sidebar and toggle to enable. Under **Subscribe to Bot Events**, you can add events for your bot to respond to. There are four events related to messages: - [`message.channels`](https://api.slack.com/events/message.channels) listens for messages in public channels that your app is added to - [`message.groups`](https://api.slack.com/events/message.groups) listens for messages in 🔒 private channels that your app is added to - [`message.im`](https://api.slack.com/events/message.im) listens for messages in your app's DMs with users @@ -169,11 +246,14 @@ If you want your bot to listen to messages from everywhere it is added to, choos --- -### Listening and responding to a message {#listening-and-responding-to-a-message} +## Listening and responding to a message {#listening-and-responding-to-a-message} Your app is now ready for some logic. Let's start by using the `message()` method to attach a listener for messages. The following example listens and responds to all messages in channels/DMs where your app has been added that contain the word "hello": + + + ```python import os from slack_bolt import App @@ -195,21 +275,61 @@ if __name__ == "__main__": SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start() ``` + + + +```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" +# To learn available listener arguments, +# visit https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html +@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))) +``` + + + + If you restart your app, so long as your bot user has been added to the channel/DM, when you send any message that contains "hello", it will respond. -This is a basic example, but it gives you a place to start customizing your app based on your own goals. Let's try something a little more interactive by sending a button rather than plain text. +This is a short example, but it gives you a place to start customizing your app based on your own goals. Let's try something a little more interactive by sending a button rather than plain text. --- -### Sending and responding to actions {#sending-and-responding-to-actions} +## Sending and responding to actions {#sending-and-responding-to-actions} -To use features like buttons, select menus, datepickers, modals, and shortcuts, you’ll need to enable interactivity. Head over to **Interactivity & Shortcuts** in your app configuration. +To use features like buttons, select menus, datepickers, modals, and shortcuts, you’ll need to enable interactivity. Head over to **Interactivity & Shortcuts** in your app settings. -:::tip + + -You’ll notice that with Socket Mode on, basic interactivity is enabled for us by default, so no further action here is needed. If you’re using HTTP, you’ll need to supply a Request URL for Slack to send events to. +With Socket Mode on, basic interactivity is enabled for us by default, so no further action here is needed -::: + + + +Similar to events, you'll need to specify a Request URL for Slack to send the action (such as *user clicked a button*). + +By default, Bolt is configured to use the same endpoint for interactive components that it uses for events, so use the same request URL as above (for example, `https://8e8ec2d7.ngrok.io/slack/events`). Press the **Save Changes** button in the lower right hand corner. Your app is now set up to handle interactivity! + +![Configuring a Request URL](/img/boltpy/request-url-config.png "Configuring a Request URL") + + + When interactivity is enabled, interactions with shortcuts, modals, or interactive components (such as buttons, select menus, and datepickers) will be sent to your app as events. @@ -219,6 +339,9 @@ Now, let's go back to your app's code and add logic to handle those events: Below, the code from the last section is modified to send a message containing a button rather than just a string: + + + ```python import os from slack_bolt import App @@ -255,6 +378,46 @@ if __name__ == "__main__": ``` + + + +```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( + blocks=[ + { + "type": "section", + "text": {"type": "mrkdwn", "text": f"Hey there <@{message['user']}>!"}, + "accessory": { + "type": "button", + "text": {"type": "plain_text", "text": "Click Me"}, + "action_id": "button_click" + } + } + ], + text=f"Hey there <@{message['user']}>!" + ) + +# Start your app +if __name__ == "__main__": + app.start(port=int(os.environ.get("PORT", 3000))) +``` + + + + The value inside of `say()` is now an object that contains an array of `blocks`. Blocks are the building components of a Slack message and can range from text to images to datepickers. In this case, your app will respond with a section block that includes a button as an accessory. Since we're using `blocks`, the `text` is a fallback for notifications and accessibility. You'll notice in the button `accessory` object, there is an `action_id`. This will act as a unique identifier for the button so your app can specify what action it wants to respond to. @@ -269,6 +432,9 @@ Now, if you restart your app and say "hello" in a channel your app is in, you'll Let's add a handler to send a followup message when someone clicks the button: + + + ```python import os from slack_bolt import App @@ -307,19 +473,65 @@ if __name__ == "__main__": SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start() ``` + + + +```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( + blocks=[ + { + "type": "section", + "text": {"type": "mrkdwn", "text": f"Hey there <@{message['user']}>!"}, + "accessory": { + "type": "button", + "text": {"type": "plain_text", "text": "Click Me"}, + "action_id": "button_click" + } + } + ], + text=f"Hey there <@{message['user']}>!" + ) + +@app.action("button_click") +def action_button_click(body, ack, say): + # Acknowledge the action + ack() + say(f"<@{body['user']['id']}> clicked the button") + +# Start your app +if __name__ == "__main__": + app.start(port=int(os.environ.get("PORT", 3000))) +``` + + + + You can see that we used `app.action()` to listen for the `action_id` that we named `button_click`. If you restart your app and click the button, you'll see a new message from your app that says you clicked the button. --- -### Next steps {#next-steps} -You just built your first [Bolt for Python app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started) with Socket Mode! 🎉 +## Next steps {#next-steps} +You just built your first [Bolt for Python app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started)! Now that you have a basic app up and running, you can start exploring how to make your Bolt app stand out. Here are some ideas about what to explore next: -* Read through the _Basic concepts_ to learn about the different methods and features your Bolt app has access to. +* Read through the site to learn about the different methods and features your Bolt app has access to. * Explore the different events your bot can listen to with the [`app.event()`](/concepts/event-listening) method. All of the events are listed [on the API site](https://api.slack.com/events). -* Bolt allows you to [call Web API methods](/concepts/web-api) with the client attached to your app. There are [over 220 methods](https://api.slack.com/methods) on our API site. +* Bolt allows you to [call Web API methods](/concepts/web-api) with the client attached to your app. There are [over 200 methods](https://api.slack.com/methods) on our API site. -* Learn more about the different token types [on our API site](https://api.slack.com/docs/token-types). Your app may need different tokens depending on the actions you want it to perform. For apps that do not use Socket Mode, typically only the bot (`xoxb`) token and Signing Secret are required. For example of this, see our parallel guide [Getting Started with HTTP](/tutorial/getting-started-http). \ No newline at end of file +* Learn more about the different token types [on our API site](https://api.slack.com/docs/token-types). Your app may need different tokens depending on the actions you want it to perform. \ No newline at end of file diff --git a/docs/content/steps/adding-editing-steps.md b/docs/content/steps/adding-editing-steps.md deleted file mode 100644 index 99ca6d587..000000000 --- a/docs/content/steps/adding-editing-steps.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Adding or editing steps from apps -lang: en -slug: /concepts/adding-editing-steps ---- - -:::danger - -Steps from apps are a deprecated feature. - -Steps from apps are different than, and not interchangeable with, Slack automation workflows. We encourage those who are currently publishing steps from apps to consider the new [Slack automation features](https://api.slack.com/automation), such as custom steps for Bolt. - -Please [read the Slack API changelog entry](https://api.slack.com/changelog/2023-08-workflow-steps-from-apps-step-back) for more information. - -::: - -When a builder adds (or later edits) your step in their workflow, your app will receive a [`workflow_step_edit` event](https://api.slack.com/reference/workflows/workflow_step_edit). The `edit` callback in your `WorkflowStep` configuration will be run when this event is received. - -Whether a builder is adding or editing a step, you need to send them a [step from app configuration modal](https://api.slack.com/reference/workflows/configuration-view). This modal is where step-specific settings are chosen, and it has more restrictions than typical modals—most notably, it cannot include `title`, `submit`, or `close` properties. By default, the configuration modal's `callback_id` will be the same as the step from app. - -Within the `edit` callback, the `configure()` utility can be used to easily open your step's configuration modal by passing in the view's blocks with the corresponding `blocks` argument. To disable saving the configuration before certain conditions are met, you can also pass in `submit_disabled` with a value of `True`. - -To learn more about opening configuration modals, [read the documentation](https://api.slack.com/workflows/steps#handle_config_view). - -Refer to the module documents (common / step-specific) to learn the available arguments. - -```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"}, - }, - { - "type": "input", - "block_id": "task_description_input", - "element": { - "type": "plain_text_input", - "action_id": "description", - "placeholder": {"type": "plain_text", "text": "Add a task description"}, - }, - "label": {"type": "plain_text", "text": "Task description"}, - }, - ] - configure(blocks=blocks) - -ws = WorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, -) -app.step(ws) -``` diff --git a/docs/content/steps/creating-steps.md b/docs/content/steps/creating-steps.md deleted file mode 100644 index 6728a77e1..000000000 --- a/docs/content/steps/creating-steps.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Creating steps from apps -lang: en -slug: /concepts/creating-steps ---- - -:::danger - -Steps from apps are a deprecated feature. - -Steps from apps are different than, and not interchangeable with, Slack automation workflows. We encourage those who are currently publishing steps from apps to consider the new [Slack automation features](https://api.slack.com/automation), such as custom steps for Bolt. - -Please [read the Slack API changelog entry](https://api.slack.com/changelog/2023-08-workflow-steps-from-apps-step-back) for more information. - -::: - -To create a step from app, Bolt provides the `WorkflowStep` class. - -When instantiating a new `WorkflowStep`, pass in the step's `callback_id` and a configuration object. - -The configuration object contains three keys: `edit`, `save`, and `execute`. Each of these keys must be a single callback or a list of callbacks. All callbacks have access to a `step` object that contains information about the step from app event. - -After instantiating a `WorkflowStep`, you can pass it into `app.step()`. Behind the scenes, your app will listen and respond to the step’s events using the callbacks provided in the configuration object. - -Alternatively, steps from apps can also be created using the `WorkflowStepBuilder` class alongside a decorator pattern. For more information, including an example of this approach, [refer to the documentation](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/workflows/step/step.html#slack_bolt.workflows.step.step.WorkflowStepBuilder). - -Refer to the module documents (common / step-specific) to learn the available arguments. - -```python -import os -from slack_bolt import App -from slack_bolt.workflows.step import WorkflowStep - -# Initiate the Bolt app as you normally would -app = App( - token=os.environ.get("SLACK_BOT_TOKEN"), - signing_secret=os.environ.get("SLACK_SIGNING_SECRET") -) - -def edit(ack, step, configure): - pass - -def save(ack, view, update): - pass - -def execute(step, complete, fail): - pass - -# Create a new WorkflowStep instance -ws = WorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, -) - -# Pass Step to set up listeners -app.step(ws) -``` diff --git a/docs/content/steps/executing-steps.md b/docs/content/steps/executing-steps.md deleted file mode 100644 index 12d557cd0..000000000 --- a/docs/content/steps/executing-steps.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Executing steps from apps -lang: en -slug: /concepts/executing-steps ---- - -:::danger - -Steps from apps are a deprecated feature. - -Steps from apps are different than, and not interchangeable with, Slack automation workflows. We encourage those who are currently publishing steps from apps to consider the new [Slack automation features](https://api.slack.com/automation), such as custom steps for Bolt. - -Please [read the Slack API changelog entry](https://api.slack.com/changelog/2023-08-workflow-steps-from-apps-step-back) for more information. - -::: - -When your step from app is executed by an end user, your app will receive a [`workflow_step_execute` event](https://api.slack.com/events/workflow_step_execute). The `execute` callback in your `WorkflowStep` configuration will be run when this event is received. - -Using the `inputs` from the `save` callback, this is where you can make third-party API calls, save information to a database, update the user's Home tab, or decide the outputs that will be available to subsequent steps from apps by mapping values to the `outputs` object. - -Within the `execute` callback, your app must either call `complete()` to indicate that the step's execution was successful, or `fail()` to indicate that the step's execution failed. - -Refer to the module documents (common / step-specific) to learn the available arguments. -```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) - - # 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) -``` diff --git a/docs/content/steps/saving-steps.md b/docs/content/steps/saving-steps.md deleted file mode 100644 index 079cf5d71..000000000 --- a/docs/content/steps/saving-steps.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Saving step configurations -lang: en -slug: /concepts/saving-steps ---- - -:::danger - -Steps from apps are a deprecated feature. - -Steps from apps are different than, and not interchangeable with, Slack automation workflows. We encourage those who are currently publishing steps from apps to consider the new [Slack automation features](https://api.slack.com/automation), such as custom steps for Bolt. - -Please [read the Slack API changelog entry](https://api.slack.com/changelog/2023-08-workflow-steps-from-apps-step-back) for more information. - -::: - -After the configuration modal is opened, your app will listen for the `view_submission` event. The `save` callback in your `WorkflowStep` configuration will be run when this event is received. - -Within the `save` callback, the `update()` method can be used to save the builder's step configuration by passing in the following arguments: - -- `inputs` is a dictionary representing the data your app expects to receive from the user upon step execution. -- `outputs` is a list of objects containing data that your app will provide upon the step's completion. Outputs can then be used in subsequent steps of the workflow. -- `step_name` overrides the default Step name -- `step_image_url` overrides the default Step image - -To learn more about how to structure these parameters, [read the documentation](https://api.slack.com/reference/workflows/workflow_step). - -Refer to the module documents (common / step-specific) to learn the available arguments. -```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) -``` diff --git a/docs/content/steps/steps.md b/docs/content/steps/steps.md deleted file mode 100644 index 64604ba78..000000000 --- a/docs/content/steps/steps.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Overview of steps from apps -lang: en -slug: /concepts/steps ---- - -:::danger - -Steps from apps are a deprecated feature. - -Steps from apps are different than, and not interchangeable with, Slack automation workflows. We encourage those who are currently publishing steps from apps to consider the new [Slack automation features](https://api.slack.com/automation), such as custom steps for Bolt. - -Please [read the Slack API changelog entry](https://api.slack.com/changelog/2023-08-workflow-steps-from-apps-step-back) for more information. - -::: - -Steps from apps for legacy workflows are now deprecated. Use new [custom steps](https://api.slack.com/automation/functions/custom-bolt). - -Steps from apps allow your app to create and process steps that users can add using [Workflow Builder](https://api.slack.com/workflows). - -Steps from apps are made up of three distinct user events: - -- Adding or editing the step in a Workflow -- Saving or updating the step's configuration -- The end user's execution of the step - -All three events must be handled for a step from app to function. - -Read more about steps from apps in the [API documentation](https://api.slack.com/workflows/steps). diff --git a/docs/content/tutorial/ai-chatbot.md b/docs/content/tutorial/ai-chatbot.md index 9fec871a0..9f4038f36 100644 --- a/docs/content/tutorial/ai-chatbot.md +++ b/docs/content/tutorial/ai-chatbot.md @@ -12,7 +12,7 @@ In this tutorial, you'll learn how to bring the power of AI into your Slack work Before getting started, you will need the following: -* a development workspace where you have permissions to install apps. If you don’t have a workspace, go ahead and set that up now—you can [go here](https://slack.com/get-started#create) to create one, or you can join the [Developer Program](https://api.slack.com/developer-program) and provision a sandbox with access to all Slack features for free. +* a development workspace where you have permissions to install apps. If you don’t have a workspace, go ahead and set that up now — you can [go here](https://slack.com/get-started#create) to create one, or you can join the [Developer Program](https://api.slack.com/developer-program) and provision a sandbox with access to all Slack features for free. * a development environment with [Python 3.6](https://www.python.org/downloads/) or later. * an Anthropic or OpenAI account with sufficient credits, and in which you have generated a secret key. @@ -144,7 +144,7 @@ When finished, click **Finish Up**, then click **Publish** to make the workflow In order for Bolty to provide summaries of recent conversation in a channel, Bolty _must_ be a member of that channel. -1. Invite Bolty to a channel that you are able to leave and rejoin (for example, not the **#general** channel or a private channel someone else created) by mentioning the app in the channel—i.e., tagging **@Bolty** in the channel and sending your message. +1. Invite Bolty to a channel that you are able to leave and rejoin (for example, not the **#general** channel or a private channel someone else created) by mentioning the app in the channel — i.e., tagging **@Bolty** in the channel and sending your message. 2. Slackbot will prompt you to either invite Bolty to the channel, or do nothing. Click **Invite Them**. Now when new users join the channel, the workflow you just created will be kicked off. To test this, leave the channel you just invited Bolty to and rejoin it. This will kick off your workflow and you'll receive a direct message from **Welcome to the channel**. Click the **Yes, give me a summary** button, and Bolty will summarize the recent conversations in the channel you joined. @@ -167,7 +167,6 @@ It retrieves the conversation history, parses it, generates a summary using an A and completes the workflow with the summary or fails if an error occurs. """ - def handle_summary_function_callback( ack: Ack, inputs: dict, fail: Fail, logger: Logger, client: WebClient, complete: Complete ): diff --git a/docs/content/tutorial/getting-started-http.md b/docs/content/tutorial/getting-started-http.md deleted file mode 100644 index 6cd4a8ae6..000000000 --- a/docs/content/tutorial/getting-started-http.md +++ /dev/null @@ -1,322 +0,0 @@ ---- -title: Getting started over HTTP -slug: getting-started-http -lang: en ---- - -# Getting started with Bolt for Python over HTTP - -This guide is meant to walk you through getting up and running with a Slack app using **Bolt for Python over HTTP**. Along the way, we’ll create a new Slack app, set up your local environment, and develop an app that listens and responds to messages from a Slack workspace. - - -When you're finished, you'll have this ⚡️[Getting Started with Slack app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started) to run, modify, and make your own. - ---- - -### Create an app {#create-an-app} -First thing's first: before you start developing with Bolt, you'll want to [create a Slack app](https://api.slack.com/apps/new). - -:::tip - -We recommend using a workspace where you won't disrupt real work getting done — [you can create a new one for free](https://slack.com/get-started#create). - -::: - -After you fill out an app name (_you can change it later_) and pick a workspace to install it to, hit the `Create App` button and you'll land on your app's **Basic Information** page. - -This page contains an overview of your app in addition to important credentials you'll need later, like the `Signing Secret` under the **App Credentials** header. - -![Basic Information page](/img/boltpy/basic-information-page.png "Basic Information page") - -Look around, add an app icon and description, and then let's start configuring your app 🔩 - ---- - -### Tokens and installing apps {#tokens-and-installing-apps} -Slack apps use [OAuth to manage access to Slack's APIs](https://api.slack.com/docs/oauth). When an app is installed, you'll receive a token that the app can use to call API methods. - -There are three main token types available to a Slack app: user (`xoxp`), bot (`xoxb`), and app-level (`xapp`) tokens. -- [User tokens](https://api.slack.com/authentication/token-types#user) allow you to call API methods on behalf of users after they install or authenticate the app. There may be several user tokens for a single workspace. -- [Bot tokens](https://api.slack.com/authentication/token-types#bot) are associated with bot users, and are only granted once in a workspace where someone installs the app. The bot token your app uses will be the same no matter which user performed the installation. Bot tokens are the token type that _most_ apps use. -- [App-level tokens](https://api.slack.com/authentication/token-types#app) represent your app across organizations, including installations by all individual users on all workspaces in a given organization and are commonly used for creating websocket connections to your app. - -For brevity, we're going to use bot tokens for this guide. - -1. Navigate to the **OAuth & Permissions** on the left sidebar and scroll down to the **Bot Token Scopes** section. Click **Add an OAuth Scope**. - -2. For now, we'll just add one scope: [`chat:write`](https://api.slack.com/scopes/chat:write). This grants your app the permission to post messages in channels it's a member of. - -3. Scroll up to the top of the OAuth & Permissions page and click **Install App to Workspace**. You'll be led through Slack's OAuth UI, where you should allow your app to be installed to your development workspace. - -4. Once you authorize the installation, you'll land on the **OAuth & Permissions** page and see a **Bot User OAuth Access Token**. We'll use that in just a moment. - -![OAuth Tokens](/img/boltpy/bot-token.png "Bot OAuth Token") - -:::info - -Treat your token like a password and [keep it safe](https://api.slack.com/docs/oauth-safety). Your app uses it to post and retrieve information from Slack workspaces. - -::: - ---- - -### Setting up your project {#setting-up-your-project} -With the initial configuration handled, it's time to set up a new Bolt project. This is where you'll write the code that handles the logic for your app. - -If you don’t already have a project, let’s create a new one. Create an empty directory: - -```shell -mkdir first-bolt-app -cd first-bolt-app -``` - -Next, we recommend using a [Python virtual environment](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/#creating-a-virtual-environment) to manage your project's dependencies. This is a great way to prevent conflicts with your system's Python packages. Let's create and activate a new virtual environment with [Python 3.6 or later](https://www.python.org/downloads/): - -```shell -python3 -m venv .venv -source .venv/bin/activate -``` - -We can confirm that the virtual environment is active by checking that the path to `python3` is _inside_ your project ([a similar command is available on Windows](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/#activating-a-virtual-environment)): - -```shell -which python3 -# Output: /path/to/first-bolt-app/.venv/bin/python3 -``` - -Before we install the Bolt for Python package to your new project, let's save the **bot token** and **signing secret** that were generated when you configured your app. - -1. **Copy your Signing Secret from the Basic Information page** and then store it in a new environment variable. The following example works on Linux and macOS; but [similar commands are available on Windows](https://superuser.com/questions/212150/how-to-set-env-variable-in-windows-cmd-line/212153#212153). -```shell -export SLACK_SIGNING_SECRET= -``` - -2. **Copy your bot (xoxb) token from the OAuth & Permissions page** and store it in another environment variable. -```shell -export SLACK_BOT_TOKEN=xoxb- -``` -> 🔒 Remember to keep your tokens and signing secret secure. At a minimum, you should avoid checking them into public version control, and access them via environment variables as we've done above. Checkout the API documentation for more on [best practices for app security](https://api.slack.com/authentication/best-practices). - -Now, let's create your app. Install the `slack_bolt` Python package to your virtual environment using the following command: - -```shell -pip install slack_bolt -``` - -Create a new file called `app.py` in this directory and add the following code: - -```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") -) - -# Start your app -if __name__ == "__main__": - app.start(port=int(os.environ.get("PORT", 3000))) -``` - -Your token and signing secret are enough to create your first Bolt app. Save your `app.py` file then on the command line run the following: - -```script -python3 app.py -``` - -Your app should let you know that it's up and running. 🎉 - ---- - -### Setting up events over HTTP {#setting-up-events} -Your app behaves similarly to people on your team — it can post messages, add emoji reactions, and listen and respond to events. - -To listen for events happening in a Slack workspace (like when a message is posted or when a reaction is posted to a message) you'll use the [Events API to subscribe to event types](https://api.slack.com/events-api). - -Let's enable events for your app: -1. Go back to your app configuration page (click on the app [from your app management page](https://api.slack.com/apps)). Click **Event Subscriptions** on the left sidebar. Toggle the switch labeled **Enable Events**. - -2. Add your Request URL. Slack will send HTTP POST requests corresponding to events to this [Request URL](https://api.slack.com/apis/connections/events-api#the-events-api__subscribing-to-event-types__events-api-request-urls) endpoint. Bolt uses the `/slack/events` path to listen to all incoming requests (whether shortcuts, events, or interactivity payloads). When configuring your Request URL within your app configuration, you'll append `/slack/events`, e.g. `https:///slack/events`. 💡 As long as your Bolt app is still running, your URL should become verified. - -:::tip - -For local development, you can use a proxy service like ngrok to create a public URL and tunnel requests to your development environment. Refer to [ngrok's getting started guide](https://ngrok.com/docs#getting-started-expose) on how to create this tunnel. And when you get to hosting your app, we've collected some of the most common hosting providers Slack developers use to host their apps [on our API site](https://api.slack.com/docs/hosting). - -::: - -Finally, it's time to tell Slack what events we'd like to listen for. - -When an event occurs, Slack will send your app some information about the event, like the user that triggered it and the channel it occurred in. Your app will process the details and can respond accordingly. - -Navigate to **Event Subscriptions** on the left sidebar and toggle to enable. Under **Subscribe to Bot Events**, you can add events for your bot to respond to. There are four events related to messages: -- [`message.channels`](https://api.slack.com/events/message.channels) listens for messages in public channels that your app is added to -- [`message.groups`](https://api.slack.com/events/message.groups) listens for messages in 🔒 private channels that your app is added to -- [`message.im`](https://api.slack.com/events/message.im) listens for messages in your app's DMs with users -- [`message.mpim`](https://api.slack.com/events/message.mpim) listens for messages in multi-person DMs that your app is added to - -If you want your bot to listen to messages from everywhere it is added to, choose all four message events. After you’ve selected the events you want your bot to listen to, click the green **Save Changes** button. - ---- - -### Listening and responding to a message {#listening-and-responding-to-a-message} -Your app is now ready for some logic. Let's start by using the `message()` method to attach a listener for messages. - -The following example listens and responds to all messages in channels/DMs where your app has been added that contain the word "hello": - -```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" -# To learn available listener arguments, -# visit https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html -@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))) -``` - -If you restart your app, so long as your bot user has been added to the channel/DM, when you send any message that contains "hello", it will respond. - -This is a basic example, but it gives you a place to start customizing your app based on your own goals. Let's try something a little more interactive by sending a button rather than plain text. - ---- - -### Sending and responding to actions {#sending-and-responding-to-actions} - -To use features like buttons, select menus, datepickers, modals, and shortcuts, you’ll need to enable interactivity. Similar to events, you'll need to specify a URL for Slack to send the action (such as *user clicked a button*). - -Back on your app configuration page, click on **Interactivity & Shortcuts** on the left side. You'll see that there's another **Request URL** box. - -:::tip - -By default, Bolt is configured to use the same endpoint for interactive components that it uses for events, so use the same request URL as above (for example, `https://8e8ec2d7.ngrok.io/slack/events`). Press the **Save Changes** button in the lower right hand corner, and that's it. Your app is set up to handle interactivity! - -::: - -![Configuring a Request URL](/img/boltpy/request-url-config.png "Configuring a Request URL") - -When interactivity is enabled, interactions with shortcuts, modals, or interactive components (such as buttons, select menus, and datepickers) will be sent to your app as events. - -Now, let's go back to your app's code and add logic to handle those events: -- First, we'll send a message that contains an interactive component (in this case a button) -- Next, we'll listen for the action of a user clicking the button before responding - -Below, the code from the last section is modified to send a message containing a button rather than just a string: - -```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( - blocks=[ - { - "type": "section", - "text": {"type": "mrkdwn", "text": f"Hey there <@{message['user']}>!"}, - "accessory": { - "type": "button", - "text": {"type": "plain_text", "text": "Click Me"}, - "action_id": "button_click" - } - } - ], - text=f"Hey there <@{message['user']}>!" - ) - -# Start your app -if __name__ == "__main__": - app.start(port=int(os.environ.get("PORT", 3000))) -``` - -The value inside of `say()` is now an object that contains an array of `blocks`. Blocks are the building components of a Slack message and can range from text to images to datepickers. In this case, your app will respond with a section block that includes a button as an accessory. Since we're using `blocks`, the `text` is a fallback for notifications and accessibility. - -You'll notice in the button `accessory` object, there is an `action_id`. This will act as a unique identifier for the button so your app can specify what action it wants to respond to. - -:::tip - -The [Block Kit Builder](https://app.slack.com/block-kit-builder) is an simple way to prototype your interactive messages. The builder lets you (or anyone on your team) mockup messages and generates the corresponding JSON that you can paste directly in your app. - -::: - -Now, if you restart your app and say "hello" in a channel your app is in, you'll see a message with a button. But if you click the button, nothing happens (*yet!*). - -Let's add a handler to send a followup message when someone clicks the button: - -```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( - blocks=[ - { - "type": "section", - "text": {"type": "mrkdwn", "text": f"Hey there <@{message['user']}>!"}, - "accessory": { - "type": "button", - "text": {"type": "plain_text", "text": "Click Me"}, - "action_id": "button_click" - } - } - ], - text=f"Hey there <@{message['user']}>!" - ) - -@app.action("button_click") -def action_button_click(body, ack, say): - # Acknowledge the action - ack() - say(f"<@{body['user']['id']}> clicked the button") - -# Start your app -if __name__ == "__main__": - app.start(port=int(os.environ.get("PORT", 3000))) -``` - -You can see that we used `app.action()` to listen for the `action_id` that we named `button_click`. If you restart your app and click the button, you'll see a new message from your app that says you clicked the button. - ---- - -### Next steps {#next-steps} -You just built your first [Bolt for Python app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started)! 🎉 - -Now that you have a basic app up and running, you can start exploring how to make your Bolt app stand out. Here are some ideas about what to explore next: - -* Read through the _Basic concepts_ to learn about the different methods and features your Bolt app has access to. - -* Explore the different events your bot can listen to with the [`app.event()` method](/concepts/event-listening). All of the events are listed [on the API site](https://api.slack.com/events). - -* Bolt allows you to [call Web API methods](/concepts/web-api) with the client attached to your app. There are [over 220 methods](https://api.slack.com/methods) on our API site. - -* Learn more about the different token types [on our API site](https://api.slack.com/docs/token-types). Your app may need different tokens depending on the actions you want it to perform. If you are using Socket Mode instead of HTTP, an additional (`xapp`) token with `connections:write` scopes is required. \ No newline at end of file diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 51b9e06c7..49df821ce 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -1,9 +1,3 @@ -// @ts-check -// `@type` JSDoc annotations allow editor autocompletion and type checking -// (when paired with `@ts-check`). -// There are various equivalent ways to declare your Docusaurus config. -// See: https://docusaurus.io/docs/api/docusaurus-config - import { themes as prismThemes } from "prism-react-renderer"; /** @type {import('@docusaurus/types').Config} */ @@ -57,12 +51,29 @@ const config = { redirects: [ { to: "/getting-started", - from: ["/tutorial/getting-started"], + from: ["/tutorial/getting-started", "/tutorial/getting-started-http"], }, { to: "/", from: ["/concepts", "/concepts/basic", "/concepts/advanced"], }, + { + to: '/concepts/actions', + from: [ + '/concepts/action-listening', + '/concepts/action-responding' + ], + }, + { + to: '/legacy/steps-from-apps', + from: [ + '/concepts/steps', + '/concepts/creating-steps', + '/concepts/adding-editing-steps', + '/concepts/saving-steps', + '/concepts/executing-steps' + ], + }, ], }, ], diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/action-respond.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/action-respond.md deleted file mode 100644 index 3a31a05c5..000000000 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/action-respond.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: アクションへの応答 -lang: ja-jp -slug: /concepts/action-respond ---- - -アクションへの応答には、主に 2 つの方法があります。1 つ目の最も一般的なやり方は `say()` を使用する方法です。そのリクエストが発生した会話(チャンネルや DM)にメッセージを返します。 - -2 つ目は、`respond()` を使用する方法です。これは、アクションに関連づけられた `response_url` を使ったメッセージ送信を行うためのユーティリティです。 - -指定可能な引数の一覧はモジュールドキュメントを参考にしてください。 -```python -# 'approve_button' という action_id のインタラクティブコンポーネントがトリガーされると、このリスナーが呼ばれる -@app.action("approve_button") -def approve_request(ack, say): - # アクションのリクエストを確認 - ack() - say("Request approved 👍") -``` - -
- -respond() の利用 - - -`respond()` は `response_url` を使って送信するときに便利なメソッドで、これらと同じような動作をします。投稿するメッセージのペイロードには、全ての[メッセージペイロードのプロパティ](https://api.slack.com/reference/messaging/payload)とオプションのプロパティとして `response_type`(値は `"in_channel"` または `"ephemeral"`)、`replace_original`、`delete_original`、`unfurl_links`、`unfurl_media` などを指定できます。こうすることによってアプリから送信されるメッセージは、やり取りの発生元に反映されます。 - -```python -# 'user_select' という action_id を持つアクションのトリガーをリッスン -@app.action("user_select") -def select_user(ack, action, respond): - ack() - respond(f"You selected <@{action['selected_user']}>") -``` - -
\ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/acknowledge.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/acknowledge.md similarity index 99% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/acknowledge.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/acknowledge.md index d180a966d..3e3523417 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/acknowledge.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/acknowledge.md @@ -4,8 +4,6 @@ lang: ja-jp slug: /concepts/acknowledge --- - - アクション(action)、コマンド(command)、ショートカット(shortcut)、オプション(options)、およびモーダルからのデータ送信(view_submission)の各リクエストは、**必ず** `ack()` 関数を使って確認を行う必要があります。これによってリクエストが受信されたことが Slack に認識され、Slack のユーザーインターフェイスが適切に更新されます。 リクエストの種類によっては、確認で通知方法が異なる場合があります。例えば、外部データソースを使用する選択メニューのオプションのリクエストに対する確認では、適切な[オプション](https://api.slack.com/reference/block-kit/composition-objects#option)のリストとともに `ack()` を呼び出します。モーダルからのデータ送信に対する確認では、 `response_action` を渡すことで[モーダルの更新](/concepts/view_submissions)などを行えます。 @@ -14,8 +12,6 @@ slug: /concepts/acknowledge FaaS / serverless 環境を使う場合、 `ack()` するタイミングが異なります。 これに関する詳細は [Lazy listeners (FaaS)](/concepts/lazy-listeners) を参照してください。 - - 指定可能な引数の一覧はモジュールドキュメントを参考にしてください。 ```python # 外部データを使用する選択メニューオプションに応答するサンプル diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/action-listening.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/actions.md similarity index 51% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/action-listening.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/actions.md index 7be3340d6..799436854 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/action-listening.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/actions.md @@ -1,9 +1,11 @@ --- -title: アクションのリスニング +title: アクション lang: ja-jp -slug: /concepts/action-listening +slug: /concepts/actions --- +## アクションのリスニング + Bolt アプリは `action` メソッドを用いて、ボタンのクリック、メニューの選択、メッセージショートカットなどのユーザーのアクションをリッスンすることができます。 アクションは `str` 型または `re.Pattern` 型の `action_id` でフィルタリングできます。`action_id` は、Slack プラットフォーム上のインタラクティブコンポーネントを区別する一意の識別子として機能します。 @@ -19,10 +21,7 @@ def update_message(ack): # アクションへの反応としてメッセージを更新 ``` -
- -

制約付きオブジェクトを使用したアクションのリスニング

-
+### 制約付きオブジェクトを使用したアクションのリスニング 制約付きのオブジェクトを使用すると、`block_id` と `action_id` をそれぞれ、または任意に組み合わせてリッスンできます。オブジェクト内の制約は、`str` 型または `re.Pattern` 型で指定できます。 @@ -44,4 +43,30 @@ def update_message(ack, body, client): ) ``` -
\ No newline at end of file +## アクションへの応答 + +アクションへの応答には、主に 2 つの方法があります。1 つ目の最も一般的なやり方は `say()` を使用する方法です。そのリクエストが発生した会話(チャンネルや DM)にメッセージを返します。 + +2 つ目は、`respond()` を使用する方法です。これは、アクションに関連づけられた `response_url` を使ったメッセージ送信を行うためのユーティリティです。 + +指定可能な引数の一覧はモジュールドキュメントを参考にしてください。 +```python +# 'approve_button' という action_id のインタラクティブコンポーネントがトリガーされると、このリスナーが呼ばれる +@app.action("approve_button") +def approve_request(ack, say): + # アクションのリクエストを確認 + ack() + say("Request approved 👍") +``` + +### respond() の利用 + +`respond()` は `response_url` を使って送信するときに便利なメソッドで、これらと同じような動作をします。投稿するメッセージのペイロードには、全ての[メッセージペイロードのプロパティ](https://api.slack.com/reference/messaging/payload)とオプションのプロパティとして `response_type`(値は `"in_channel"` または `"ephemeral"`)、`replace_original`、`delete_original`、`unfurl_links`、`unfurl_media` などを指定できます。こうすることによってアプリから送信されるメッセージは、やり取りの発生元に反映されます。 + +```python +# 'user_select' という action_id を持つアクションのトリガーをリッスン +@app.action("user_select") +def select_user(ack, action, respond): + ack() + respond(f"You selected <@{action['selected_user']}>") +``` diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/adapters.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/adapters.md similarity index 99% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/adapters.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/adapters.md index 4dfd0f9a1..78c94fca4 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/adapters.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/adapters.md @@ -12,7 +12,6 @@ slug: /concepts/adapters すべてのアダプターの一覧と、設定や使い方のサンプルは、リポジトリの `examples` フォルダをご覧ください。 - ```python from slack_bolt import App app = App( diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/app-home.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/app-home.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/app-home.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/app-home.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/assistant.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/assistant.md similarity index 99% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/assistant.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/assistant.md index c09f7979e..d3b54e760 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/assistant.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/assistant.md @@ -74,7 +74,6 @@ app.use(assistant) リスナーに指定可能な引数の一覧はモジュールドキュメントを参考にしてください。 - ユーザーがチャンネルの横でアシスタントスレッドを開いた場合、そのチャンネルの情報は、そのスレッドの `AssistantThreadContext` データとして保持され、 `get_thread_context` ユーティリティを使ってアクセスすることができます。Bolt がこのユーティリティを提供している理由は、後続のユーザーメッセージ投稿のイベントペイロードに最新のスレッドのコンテキスト情報は含まれないためです。そのため、アプリはコンテキスト情報が変更されたタイミングでそれを何らかの方法で保存し、後続のメッセージイベントのリスナーコードから参照できるようにする必要があります。 そのユーザーがチャンネルを切り替えた場合、`assistant_thread_context_changed` イベントがあなたのアプリに送信されます。(上記のコード例のように)組み込みの `Assistant` ミドルウェアをカスタム設定なしで利用している場合、この更新されたチャンネル情報は、自動的にこのアシスタントボットからの最初の返信のメッセージメタデータとして保存されます。これは、組み込みの仕組みを使う場合は、このコンテキスト情報を自前で用意したデータストアに保存する必要はないということです。この組み込みの仕組みの唯一の短所は、追加の Slack API 呼び出しによる処理時間のオーバーヘッドです。具体的には `get_thread_context` を実行したときに、この保存されたメッセージメタデータにアクセスするために `conversations.history` API が呼び出されます。 @@ -89,11 +88,9 @@ assistant = Assistant(thread_context_store=FileAssistantThreadContextStore()) このリファレンス実装はローカルファイルに依存しており、本番環境での利用は推奨しません。本番アプリでは `AssistantThreadContextStore` を継承した自前のクラスを使うようにしてください。 -
+最後に、動作する完全なサンプルコード例を確認したい場合は、私たちが GitHub 上で提供している[サンプルアプリのリポジトリ](https://github.com/slack-samples/bolt-python-assistant-template)をチェックしてみてください。 - -アシスタントスレッドでの Block Kit インタラクション - +## アシスタントスレッドでの Block Kit インタラクション より高度なユースケースでは、上のようなプロンプト例の提案ではなく Block Kit のボタンなどを使いたいという場合があるかもしれません。そして、後続の処理のために[構造化されたメッセージメタデータ](https://api.slack.com/metadata)を含むメッセージを送信したいという場合もあるでしょう。 @@ -229,11 +226,6 @@ def respond_to_user_messages(logger: logging.Logger, set_status: SetStatus, say: logger.exception(f"Failed to respond to an inquiry: {e}") say(f":warning: Sorry, something went wrong during processing your request (error: {e})") - # このミドルウェアを Bolt アプリに追加します app.use(assistant) -``` - -
- -最後に、動作する完全なサンプルコード例を確認したい場合は、私たちが GitHub 上で提供している[サンプルアプリのリポジトリ](https://github.com/slack-samples/bolt-python-assistant-template)をチェックしてみてください。 \ No newline at end of file +``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/async.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/async.md similarity index 96% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/async.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/async.md index 7ea6c7dc9..19609be89 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/async.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/async.md @@ -8,7 +8,6 @@ slug: /concepts/async 非同期バージョンのプロジェクトのサンプルは、リポジトリの `examples` フォルダにあります。 - ```python # aiohttp のインストールが必要です from slack_bolt.async_app import AsyncApp @@ -27,11 +26,7 @@ if __name__ == "__main__": app.start(3000) ``` -
- ->他のフレームワークを使用する - - +## 他のフレームワークを使用する `AsyncApp#start()` では内部的に [`AIOHTTP`](https://docs.aiohttp.org/) のWebサーバーが実装されています。必要に応じて、受信リクエストの処理に `AIOHTTP` 以外のフレームワークを使用することができます。 @@ -46,7 +41,6 @@ pip install slack_bolt sanic uvicorn uvicorn async_app:api --reload --port 3000 --log-level debug ``` - ```python from slack_bolt.async_app import AsyncApp app = AsyncApp() @@ -74,5 +68,4 @@ async def endpoint(req: Request): if __name__ == "__main__": api.run(host="0.0.0.0", port=int(os.environ.get("PORT", 3000))) -``` -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/authenticating-oauth.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/authenticating-oauth.md similarity index 98% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/authenticating-oauth.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/authenticating-oauth.md index b1478ee3b..e72f27146 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/authenticating-oauth.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/authenticating-oauth.md @@ -35,10 +35,7 @@ app = App( ) ``` -
- -OAuth デフォルト設定をカスタマイズ - +## OAuth デフォルト設定をカスタマイズ `oauth_settings` を使って OAuth モジュールのデフォルト設定を上書きすることができます。このカスタマイズされた設定は App の初期化時に渡します。以下の情報を変更可能です: @@ -90,6 +87,4 @@ app = App( callback_options=callback_options, ), ) -``` - -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/authorization.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/authorization.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/authorization.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/authorization.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/commands.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/commands.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/commands.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/commands.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/context.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/context.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/context.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/context.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/custom-adapters.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/custom-adapters.md similarity index 99% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/custom-adapters.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/custom-adapters.md index 7d2e63a91..b72d48ded 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/custom-adapters.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/custom-adapters.md @@ -22,7 +22,6 @@ slug: /concepts/custom-adapters カスタムのアダプターに関連した詳しいサンプルについては、[組み込みのアダプター](https://github.com/slackapi/bolt-python/tree/main/slack_bolt/adapter)の実装を参考にしてください。 - ```python # Flask で必要なパッケージをインポートします from flask import Request, Response, make_response diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/custom-steps.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/custom-steps.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/custom-steps.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/custom-steps.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/errors.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/errors.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/errors.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/errors.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/event-listening.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/event-listening.md similarity index 95% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/event-listening.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/event-listening.md index 6d0409bb0..e54989255 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/event-listening.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/event-listening.md @@ -19,17 +19,12 @@ def ask_for_introduction(event, say): say(text=text, channel=welcome_channel_id) ``` -
- - -メッセージのサブタイプのフィルタリング - +## メッセージのサブタイプのフィルタリング `message()` リスナーは `event("message")` と等価の機能を提供します。 `subtype` という追加のキーを指定して、イベントのサブタイプでフィルタリングすることもできます。よく使われるサブタイプには、`bot_message` や `message_replied` があります。詳しくは[メッセージイベントページ](https://api.slack.com/events/message#message_subtypes)を参照してください。サブタイプなしのイベントだけにフィルターするために明に `None` を指定することもできます。 - ```python # 変更されたすべてのメッセージに一致 @app.event({ @@ -39,5 +34,4 @@ def ask_for_introduction(event, say): def log_message_change(logger, event): user, text = event["user"], event["text"] logger.info(f"The user {user} changed the message to {text}") -``` -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/global-middleware.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/global-middleware.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/global-middleware.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/global-middleware.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/lazy-listeners.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/lazy-listeners.md similarity index 98% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/lazy-listeners.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/lazy-listeners.md index de5f538e8..25eb6294c 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/lazy-listeners.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/lazy-listeners.md @@ -14,7 +14,6 @@ Lazy リスナー関数は、FaaS 環境への Slack アプリのデプロイを * `ack: Callable`: 3 秒以内での `ack()` メソッドの呼び出しを担当します。 * `lazy: List[Callable]` : リクエストに関する時間のかかる処理のハンドリングを担当します。Lazy 関数からは `ack()` にアクセスすることはできません。 - ```python def respond_to_slack_within_3_seconds(body, ack): text = body.get("text") @@ -36,11 +35,7 @@ app.command("/start-process")( ) ``` -
- -AWS Lambda を使用した例 - - +## AWS Lambda を使用した例 このサンプルは、[AWS Lambda](https://aws.amazon.com/lambda/) にコードをデプロイします。[`examples` フォルダ](https://github.com/slackapi/bolt-python/tree/main/examples/aws_lambda)にはほかにもサンプルが用意されています。 @@ -60,7 +55,6 @@ echo 'slack_bolt' > requirements.txt lambda deploy --config-file config.yaml --requirements requirements.txt ``` - ```python from slack_bolt import App from slack_bolt.adapter.aws_lambda import SlackRequestHandler @@ -107,5 +101,4 @@ def handler(event, context): } ] } -``` -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/listener-middleware.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/listener-middleware.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/listener-middleware.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/listener-middleware.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/logging.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/logging.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/logging.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/logging.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/message-listening.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/message-listening.md similarity index 94% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/message-listening.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/message-listening.md index a30620abd..f9ccf7d17 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/message-listening.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/message-listening.md @@ -17,10 +17,7 @@ def say_hello(message, say): say(f"Hi there, <@{user}>!") ``` -
- -正規表現パターンの利用 - +## 正規表現パターンの利用 文字列の代わりに `re.compile()` メソッドを使用すれば、より細やかな条件指定ができます。 @@ -32,5 +29,4 @@ def say_hello_regex(say, context): # 正規表現のマッチ結果は context.matches に設定される greeting = context['matches'][0] say(f"{greeting}, how are you?") -``` -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/message-sending.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/message-sending.md similarity index 96% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/message-sending.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/message-sending.md index 8b5c9e7e5..e109a0f4d 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/message-sending.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/message-sending.md @@ -15,10 +15,8 @@ slug: /concepts/message-sending def ask_who(message, say): say("_Who's there?_") ``` -
- -ブロックを用いたメッセージの送信 - + +## ブロックを用いたメッセージの送信 `say()` は、より複雑なメッセージペイロードを受け付けるので、メッセージに機能やリッチな構造を与えることが容易です。 @@ -44,5 +42,4 @@ def show_datepicker(event, say): blocks=blocks, text="Pick a date for me to remind you" ) -``` -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/opening-modals.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/opening-modals.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/opening-modals.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/opening-modals.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/options.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/select-menu-options.md similarity index 99% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/options.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/select-menu-options.md index 4838b2a75..78f7dcdb4 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/options.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/select-menu-options.md @@ -33,4 +33,4 @@ def show_options(ack, payload): if keyword is not None and len(keyword) > 0: options = [o for o in options if keyword in o["text"]["text"]] ack(options=options) -``` \ No newline at end of file +``` diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/shortcuts.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/shortcuts.md similarity index 97% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/shortcuts.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/shortcuts.md index 5824fbb65..e12b576ca 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/shortcuts.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/shortcuts.md @@ -53,13 +53,7 @@ def open_modal(ack, shortcut, client): ) ``` -
- - -制約付きオブジェクトを使用したショートカットのリスニング - - - +## 制約付きオブジェクトを使用したショートカットのリスニング 制約付きオブジェクトを使って `callback_id` や `type` によるリッスンできます。オブジェクト内の制約は `str` 型または `re.Pattern` オブジェクトを使用できます。 @@ -97,5 +91,4 @@ def open_modal(ack, shortcut, client): ] } ) -``` -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/socket-mode.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/socket-mode.md similarity index 98% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/socket-mode.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/socket-mode.md index a4c486cbd..ad4f6c8f0 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/socket-mode.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/socket-mode.md @@ -36,16 +36,12 @@ if __name__ == "__main__": handler.start() ``` -
- -Async (asyncio) の利用 - +## Async (asyncio) の利用 aiohttp のような asyncio をベースとしたアダプターを使う場合、アプリケーション全体が asyncio の async/await プログラミングモデルで実装されている必要があります。`AsyncApp` を動作させるためには `AsyncSocketModeHandler` とその async なミドルウェアやリスナーを利用します。 `AsyncApp` の使い方についての詳細は、[Async (asyncio) の利用](/concepts/async)や、関連する[サンプルコード例](https://github.com/slackapi/bolt-python/tree/main/examples)を参考にしてください。 - ```python from slack_bolt.app.async_app import AsyncApp # デフォルトは aiohttp を使った実装 @@ -62,5 +58,4 @@ async def main(): if __name__ == "__main__": import asyncio asyncio.run(main()) -``` -
\ No newline at end of file +``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/token-rotation.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/token-rotation.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/advanced/token-rotation.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/token-rotation.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/updating-pushing-views.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/updating-pushing-views.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/updating-pushing-views.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/updating-pushing-views.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/view_submissions.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/view-submissions.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/view_submissions.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/view-submissions.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/web-api.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/web-api.md similarity index 100% rename from docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/basic/web-api.md rename to docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/concepts/web-api.md diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/getting-started.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/getting-started.md index 41aecf6ef..c31957e36 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/getting-started.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/getting-started.md @@ -4,11 +4,8 @@ slug: getting-started lang: ja-jp --- -# Bolt 入門ガイド - このガイドでは、Bolt for Python を使った Slack アプリの設定と起動の方法について説明します。ここで説明する手順では、まず新しい Slack アプリを作成し、ローカルの開発環境をセットアップし、Slack ワークスペースからのメッセージをリッスンして応答するアプリを開発するという流れになります。 - この手順を全て終わらせたら、あなたはきっと ⚡️[Slack アプリのはじめ方](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started)のサンプルアプリを動作させたり、それに変更を加えたり、自分のアプリを作ったりすることができるようになるでしょう。 :::tip @@ -108,7 +105,6 @@ export SLACK_APP_TOKEN=<アプリレベルトークン> > 🔒 全てのトークンは安全に保管してください。少なくともパブリックなバージョン管理にチェックインするようなことは避けるべきでしょう。また、上にあった例のように環境変数を介してアクセスするようにしてください。詳細な情報は [アプリのセキュリティのベストプラクティス](https://api.slack.com/authentication/best-practices)のドキュメントを参照してください。 - 完了したら、いよいよアプリを作っていきましょう。以下のコマンドを使って、仮想環境に Python の `slack_bolt` パッケージをインストールします。 ```shell diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/legacy/steps-from-apps.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/legacy/steps-from-apps.md new file mode 100644 index 000000000..4717de480 --- /dev/null +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/legacy/steps-from-apps.md @@ -0,0 +1,193 @@ +--- +title: ワークフローステップの概要 +lang: ja-jp +slug: /concepts/steps-from-apps +--- + +(アプリによる)ワークフローステップでは、処理をアプリ側で行うカスタムのワークフローステップを提供することができます。ユーザーは[ワークフロービルダー](https://api.slack.com/workflows)を使ってこれらのステップをワークフローに追加できます。 + +ワークフローステップは、次の 3 つのユーザーイベントで構成されます。 + +- ワークフローステップをワークフローに追加・変更する +- ワークフロー内のステップの設定内容を更新する +- エンドユーザーがそのステップを実行する + +ワークフローステップを機能させるためには、これら 3 つのイベントすべてに対応する必要があります。 + +アプリを使ったワークフローステップに関する詳細は、[API ドキュメント](https://api.slack.com/workflows/steps)を参照してください。 + +## ステップの定義 + +ワークフローステップの作成には、Bolt が提供する `WorkflowStep` クラスを利用します。 + +ステップの `callback_id` と設定オブジェクトを指定して、`WorkflowStep` の新しいインスタンスを作成します。 + +設定オブジェクトは、`edit`、`save`、`execute` という 3 つのキーを持ちます。それぞれのキーは、単一のコールバック、またはコールバックのリストである必要があります。すべてのコールバックは、ワークフローステップのイベントに関する情報を保持する `step` オブジェクトにアクセスできます。 + +`WorkflowStep` のインスタンスを作成したら、それを`app.step()` メソッドに渡します。これによって、アプリがワークフローステップのイベントをリッスンし、設定オブジェクトで指定されたコールバックを使ってそれに応答できるようになります。 + +また、デコレーターとして利用できる `WorkflowStepBuilder` クラスを使ってワークフローステップを定義することもできます。 詳細は、[こちらのドキュメント](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/workflows/step/step.html#slack_bolt.workflows.step.step.WorkflowStepBuilder)のコード例などを参考にしてください。 + +指定可能な引数の一覧はモジュールドキュメントを参考にしてください(共通 / ステップ用 + +```python +import os +from slack_bolt import App +from slack_bolt.workflows.step import WorkflowStep + +# いつも通りBolt アプリを起動する +app = App( + token=os.environ.get("SLACK_BOT_TOKEN"), + signing_secret=os.environ.get("SLACK_SIGNING_SECRET") +) + +def edit(ack, step, configure): + pass + +def save(ack, view, update): + pass + +def execute(step, complete, fail): + pass + +# WorkflowStep の新しいインスタンスを作成する +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +# ワークフローステップを渡してリスナーを設定する +app.step(ws) +``` + +## ステップの追加・編集 + +作成したワークフローステップがワークフローに追加またはその設定を変更されるタイミングで、[`workflow_step_edit` イベントがアプリに送信されます](https://api.slack.com/reference/workflows/workflow_step_edit)。このイベントがアプリに届くと、`WorkflowStep` で設定した `edit` コールバックが実行されます。 + +ステップの追加と編集のどちらが行われるときも、[ワークフローステップの設定モーダル](https://api.slack.com/reference/workflows/configuration-view)をビルダーに送信する必要があります。このモーダルは、そのステップ独自の設定を選択するための場所です。通常のモーダルより制限が強く、例えば `title`、`submit`、`close` のプロパティを含めることができません。設定モーダルの `callback_id` は、デフォルトではワークフローステップと同じものになります。 + +`edit` コールバック内で `configure()` ユーティリティを使用すると、対応する `blocks` 引数にビューのblocks 部分だけを渡して、ステップの設定モーダルを簡単に表示させることができます。必要な入力内容が揃うまで設定の保存を無効にするには、`True` の値をセットした `submit_disabled` を渡します。 + +設定モーダルの開き方に関する詳細は、[こちらのドキュメント](https://api.slack.com/workflows/steps#handle_config_view)を参照してください。 + +指定可能な引数の一覧はモジュールドキュメントを参考にしてください(共通 / ステップ用 + +```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"}, + }, + { + "type": "input", + "block_id": "task_description_input", + "element": { + "type": "plain_text_input", + "action_id": "description", + "placeholder": {"type": "plain_text", "text":"Add a task description"}, + }, + "label": {"type": "plain_text", "text":"Task description"}, + }, + ] + configure(blocks=blocks) + +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` + +## ステップの設定の保存 + +設定モーダルを開いた後、アプリは `view_submission` イベントをリッスンします。このイベントがアプリに届くと、`WorkflowStep` で設定した `save` コールバックが実行されます。 + +`save` コールバック内では、`update()` メソッドを使って、ワークフローに追加されたステップの設定を保存することができます。このメソッドには次の引数を指定します。 + +- `inputs` : ユーザーがワークフローステップを実行したときにアプリが受け取る予定のデータを表す辞書型の値です。 +- `outputs` : ワークフローステップの完了時にアプリが出力するデータが設定されたオブジェクトのリストです。この outputs は、ワークフローの後続のステップで利用することができます。 +- `step_name` : ステップのデフォルトの名前をオーバーライドします。 +- `step_image_url` : ステップのデフォルトの画像をオーバーライドします。 + +これらのパラメータの構成方法に関する詳細は、[こちらのドキュメント](https://api.slack.com/reference/workflows/workflow_step)を参照してください。 + +指定可能な引数の一覧はモジュールドキュメントを参考にしてください(共通 / ステップ用 + +```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) +``` + +## ステップの実行 + +エンドユーザーがワークフローステップを実行すると、アプリに [`workflow_step_execute` イベントが送信されます](https://api.slack.com/events/workflow_step_execute)。このイベントがアプリに届くと、`WorkflowStep` で設定した `execute` コールバックが実行されます。 + +`save` コールバックで取り出した `inputs` を使って、サードパーティの API を呼び出す、情報をデータベースに保存する、ユーザーのホームタブを更新するといった処理を実行することができます。また、ワークフローの後続のステップで利用する出力値を `outputs` オブジェクトに設定します。 + +`execute` コールバック内では、`complete()` を呼び出してステップの実行が成功したことを示すか、`fail()` を呼び出してステップの実行が失敗したことを示す必要があります。 + +指定可能な引数の一覧はモジュールドキュメントを参考にしてください(共通 / ステップ用 +```python +def execute(step, complete, fail): + inputs = step["inputs"] + # すべての処理が成功した場合 + outputs = { + "task_name": inputs["task_name"]["value"], + "task_description": inputs["task_description"]["value"], + } + complete(outputs=outputs) + + # 失敗した処理がある場合 + error = {"message":"Just testing step failure!"} + fail(error=error) + +ws = WorkflowStep( + callback_id="add_task", + edit=edit, + save=save, + execute=execute, +) +app.step(ws) +``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/adding-editing-steps.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/adding-editing-steps.md deleted file mode 100644 index 24b85bfa7..000000000 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/adding-editing-steps.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: ステップの追加・編集 -lang: ja-jp -slug: /concepts/adding-editing-steps ---- - -作成したワークフローステップがワークフローに追加またはその設定を変更されるタイミングで、[`workflow_step_edit` イベントがアプリに送信されます](https://api.slack.com/reference/workflows/workflow_step_edit)。このイベントがアプリに届くと、`WorkflowStep` で設定した `edit` コールバックが実行されます。 - -ステップの追加と編集のどちらが行われるときも、[ワークフローステップの設定モーダル](https://api.slack.com/reference/workflows/configuration-view)をビルダーに送信する必要があります。このモーダルは、そのステップ独自の設定を選択するための場所です。通常のモーダルより制限が強く、例えば `title`、`submit`、`close` のプロパティを含めることができません。設定モーダルの `callback_id` は、デフォルトではワークフローステップと同じものになります。 - -`edit` コールバック内で `configure()` ユーティリティを使用すると、対応する `blocks` 引数にビューのblocks 部分だけを渡して、ステップの設定モーダルを簡単に表示させることができます。必要な入力内容が揃うまで設定の保存を無効にするには、`True` の値をセットした `submit_disabled` を渡します。 - -設定モーダルの開き方に関する詳細は、[こちらのドキュメント](https://api.slack.com/workflows/steps#handle_config_view)を参照してください。 - -指定可能な引数の一覧はモジュールドキュメントを参考にしてください(共通 / ステップ用 - -```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"}, - }, - { - "type": "input", - "block_id": "task_description_input", - "element": { - "type": "plain_text_input", - "action_id": "description", - "placeholder": {"type": "plain_text", "text":"Add a task description"}, - }, - "label": {"type": "plain_text", "text":"Task description"}, - }, - ] - configure(blocks=blocks) - -ws = WorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, -) -app.step(ws) -``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/creating-steps.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/creating-steps.md deleted file mode 100644 index 889543767..000000000 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/creating-steps.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: ステップの定義 -lang: ja-jp -slug: /concepts/creating-steps ---- - -ワークフローステップの作成には、Bolt が提供する `WorkflowStep` クラスを利用します。 - -ステップの `callback_id` と設定オブジェクトを指定して、`WorkflowStep` の新しいインスタンスを作成します。 - -設定オブジェクトは、`edit`、`save`、`execute` という 3 つのキーを持ちます。それぞれのキーは、単一のコールバック、またはコールバックのリストである必要があります。すべてのコールバックは、ワークフローステップのイベントに関する情報を保持する `step` オブジェクトにアクセスできます。 - -`WorkflowStep` のインスタンスを作成したら、それを`app.step()` メソッドに渡します。これによって、アプリがワークフローステップのイベントをリッスンし、設定オブジェクトで指定されたコールバックを使ってそれに応答できるようになります。 - -また、デコレーターとして利用できる `WorkflowStepBuilder` クラスを使ってワークフローステップを定義することもできます。 詳細は、[こちらのドキュメント](https://tools.slack.dev/bolt-python/api-docs/slack_bolt/workflows/step/step.html#slack_bolt.workflows.step.step.WorkflowStepBuilder)のコード例などを参考にしてください。 - -指定可能な引数の一覧はモジュールドキュメントを参考にしてください(共通 / ステップ用 - -```python -import os -from slack_bolt import App -from slack_bolt.workflows.step import WorkflowStep - -# いつも通りBolt アプリを起動する -app = App( - token=os.environ.get("SLACK_BOT_TOKEN"), - signing_secret=os.environ.get("SLACK_SIGNING_SECRET") -) - -def edit(ack, step, configure): - pass - -def save(ack, view, update): - pass - -def execute(step, complete, fail): - pass - -# WorkflowStep の新しいインスタンスを作成する -ws = WorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, -) -# ワークフローステップを渡してリスナーを設定する -app.step(ws) -``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/executing-steps.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/executing-steps.md deleted file mode 100644 index e10c7eec3..000000000 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/executing-steps.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: ステップの実行 -lang: ja-jp -slug: /concepts/executing-steps ---- - -エンドユーザーがワークフローステップを実行すると、アプリに [`workflow_step_execute` イベントが送信されます](https://api.slack.com/events/workflow_step_execute)。このイベントがアプリに届くと、`WorkflowStep` で設定した `execute` コールバックが実行されます。 - -`save` コールバックで取り出した `inputs` を使って、サードパーティの API を呼び出す、情報をデータベースに保存する、ユーザーのホームタブを更新するといった処理を実行することができます。また、ワークフローの後続のステップで利用する出力値を `outputs` オブジェクトに設定します。 - -`execute` コールバック内では、`complete()` を呼び出してステップの実行が成功したことを示すか、`fail()` を呼び出してステップの実行が失敗したことを示す必要があります。 - -指定可能な引数の一覧はモジュールドキュメントを参考にしてください(共通 / ステップ用 -```python -def execute(step, complete, fail): - inputs = step["inputs"] - # すべての処理が成功した場合 - outputs = { - "task_name": inputs["task_name"]["value"], - "task_description": inputs["task_description"]["value"], - } - complete(outputs=outputs) - - # 失敗した処理がある場合 - error = {"message":"Just testing step failure!"} - fail(error=error) - -ws = WorkflowStep( - callback_id="add_task", - edit=edit, - save=save, - execute=execute, -) -app.step(ws) -``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/saving-steps.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/saving-steps.md deleted file mode 100644 index 94ad32934..000000000 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/saving-steps.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: ステップの設定の保存 -lang: ja-jp -slug: /concepts/saving-steps ---- - -設定モーダルを開いた後、アプリは `view_submission` イベントをリッスンします。このイベントがアプリに届くと、`WorkflowStep` で設定した `save` コールバックが実行されます。 - -`save` コールバック内では、`update()` メソッドを使って、ワークフローに追加されたステップの設定を保存することができます。このメソッドには次の引数を指定します。 - -- `inputs` : ユーザーがワークフローステップを実行したときにアプリが受け取る予定のデータを表す辞書型の値です。 -- `outputs` : ワークフローステップの完了時にアプリが出力するデータが設定されたオブジェクトのリストです。この outputs は、ワークフローの後続のステップで利用することができます。 -- `step_name` : ステップのデフォルトの名前をオーバーライドします。 -- `step_image_url` : ステップのデフォルトの画像をオーバーライドします。 - -これらのパラメータの構成方法に関する詳細は、[こちらのドキュメント](https://api.slack.com/reference/workflows/workflow_step)を参照してください。 - -指定可能な引数の一覧はモジュールドキュメントを参考にしてください(共通 / ステップ用 - -```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) -``` \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/steps.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/steps.md deleted file mode 100644 index 881d791b2..000000000 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/steps/steps.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: ワークフローステップの概要 -lang: ja-jp -slug: /concepts/steps ---- - -(アプリによる)ワークフローステップでは、処理をアプリ側で行うカスタムのワークフローステップを提供することができます。ユーザーは[ワークフロービルダー](https://api.slack.com/workflows)を使ってこれらのステップをワークフローに追加できます。 - -ワークフローステップは、次の 3 つのユーザーイベントで構成されます。 - -- ワークフローステップをワークフローに追加・変更する -- ワークフロー内のステップの設定内容を更新する -- エンドユーザーがそのステップを実行する - -ワークフローステップを機能させるためには、これら 3 つのイベントすべてに対応する必要があります。 - -アプリを使ったワークフローステップに関する詳細は、[API ドキュメント](https://api.slack.com/workflows/steps)を参照してください。 \ No newline at end of file diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/tutorial/getting-started-http.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/tutorial/getting-started-http.md index b6c461de2..5550464a3 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/tutorial/getting-started-http.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/tutorial/getting-started-http.md @@ -97,7 +97,6 @@ export SLACK_BOT_TOKEN=xoxb- > 🔒 全てのトークンは安全に保管してください。最低限、パブリックなバージョンコントロールにチェックインすることは避けてください。また、上記の例のように環境変数を介してアクセスするようにしてください。詳細な情報は [best practices for app security](https://api.slack.com/authentication/best-practices).のドキュメントを参照してください。 - 完了したら、アプリを作ってみましょう。以下のコマンドを使って、仮想環境に Python の `slack_bolt` パッケージをインストールします。 ```shell diff --git a/docs/sidebars.js b/docs/sidebars.js index 2fed41a3c..a03e2f6fb 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -1,22 +1,5 @@ -/** - * Creating a sidebar enables you to: - - create an ordered group of docs - - render a sidebar for each doc of that group - - provide next/previous navigation - - The sidebars can be generated from the filesystem, or explicitly defined here. - - Create as many sidebars as you want. - */ - -// @ts-check - /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ const sidebars = { - // By default, Docusaurus generates a sidebar from the docs folder structure - // tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], - - // But you can create a sidebar manually sidebarBoltPy: [ { type: 'doc', @@ -26,55 +9,68 @@ const sidebars = { }, 'getting-started', { - type: 'category', - label: 'Basic concepts', + type: "category", + label: "Slack API calls", + items: ["concepts/message-sending", "concepts/web-api"], + }, + { + type: "category", + label: "Events API", + items: ["concepts/message-listening", "concepts/event-listening"], + }, + { + type: "category", + label: "App UI & Interactivity", items: [ - 'basic/assistant', - 'basic/message-listening', - 'basic/message-sending', - 'basic/event-listening', - 'basic/web-api', - 'basic/action-listening', - 'basic/action-respond', - 'basic/acknowledge', - 'basic/shortcuts', - 'basic/commands', - 'basic/opening-modals', - 'basic/updating-pushing-views', - 'basic/view_submissions', - 'basic/app-home', - 'basic/options', - 'basic/custom-steps', - 'basic/authenticating-oauth', - 'basic/socket-mode' + "concepts/acknowledge", + "concepts/shortcuts", + "concepts/commands", + "concepts/actions", + "concepts/opening-modals", + "concepts/updating-pushing-views", + "concepts/view-submissions", + "concepts/select-menu-options", + "concepts/app-home", ], }, + 'concepts/assistant', + 'concepts/custom-steps', { - type: 'category', - label: 'Advanced concepts', + type: "category", + label: "App Configuration", + items: [ + "concepts/socket-mode", + "concepts/errors", + "concepts/logging", + 'concepts/async', + ], + }, + { + type: "category", + label: "Middleware & Adaptors", + items: [ + "concepts/global-middleware", + "concepts/listener-middleware", + 'concepts/lazy-listeners', + 'concepts/context', + 'concepts/adapters', + 'concepts/custom-adapters', + ], + }, + { + type: "category", + label: "Authorization & Security", items: [ - 'advanced/adapters', - 'advanced/custom-adapters', - 'advanced/async', - 'advanced/errors', - 'advanced/logging', - 'advanced/authorization', - 'advanced/token-rotation', - 'advanced/listener-middleware', - 'advanced/global-middleware', - 'advanced/context', - 'advanced/lazy-listeners', + "concepts/authenticating-oauth", + "concepts/authorization", + "concepts/token-rotation", ], }, { type: 'category', - label: 'Steps from apps (Deprecated)', + label: 'Legacy', items: [ - 'steps/steps', - 'steps/executing-steps', - 'steps/creating-steps', - 'steps/adding-editing-steps', - 'steps/saving-steps', + 'concepts/steps-from-apps', ], }, { type: 'html', value: '
' }, @@ -82,7 +78,6 @@ const sidebars = { type: 'category', label: 'Tutorials', items: [ - 'tutorial/getting-started-http', 'tutorial/ai-chatbot' ], }, diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index be9fbdc1f..3831229a1 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -120,4 +120,10 @@ html[data-theme="dark"] .navbar-github-link::before { font-size: 1.25em; /* Adjust the size as needed */ font-weight: bold; color: #000; +} + +.tabs-container { + border: 2px solid var(--ifm-hr-background-color); /* Adjust the color and thickness as needed */ + border-radius: 5px; /* To give rounded corners */ + padding: 0.5em; /* To add spacing inside the tab */ } \ No newline at end of file From 8eca905cf6fd44ee4b217024745b94e0df806cfe Mon Sep 17 00:00:00 2001 From: Luke Russell Date: Wed, 18 Dec 2024 17:25:50 -0800 Subject: [PATCH 2/4] stashing --- docs/content/getting-started.md | 3 +- .../current/getting-started.md | 3 +- .../current/tutorial/getting-started-http.md | 31 ----- docs/src/css/custom.css | 115 +++++++++++------- 4 files changed, 73 insertions(+), 79 deletions(-) diff --git a/docs/content/getting-started.md b/docs/content/getting-started.md index f86572391..32e8a2172 100644 --- a/docs/content/getting-started.md +++ b/docs/content/getting-started.md @@ -15,8 +15,6 @@ When you're finished, you'll have this ⚡️[Getting Started with Slack app](ht Before you start developing with Bolt, you'll want to [create a Slack app](https://api.slack.com/apps/new). -[`chat.message`](https://api.slack.com/scopes) - :::tip We recommend using a workspace where you won't disrupt real work getting done. Join the [Developer Program](https://api.slack.com/developer-program) and provision a sandbox with access to all Slack features for free. @@ -524,6 +522,7 @@ You can see that we used `app.action()` to listen for the `action_id` that we na --- ## Next steps {#next-steps} + You just built your first [Bolt for Python app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started)! Now that you have a basic app up and running, you can start exploring how to make your Bolt app stand out. Here are some ideas about what to explore next: diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/getting-started.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/getting-started.md index c31957e36..5fedf19b2 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/getting-started.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/getting-started.md @@ -10,6 +10,7 @@ lang: ja-jp :::tip +REMOVE このガイドでは[ソケットモード](https://api.slack.com/apis/connections/socket) を利用します。ソケットモードは、Slack アプリ開発をとりあえず始めてみるときやあなたのチームだけのためのアプリをつくるときにおすすめのやり方です。もしすでに HTTP をアプリのコミュニケーションプロトコルとするとわかっている場合は、HTTP の方式に対応した同様のドキュメントである [Bolt 入門ガイド(HTTP)](/tutorial/getting-started-http) を参照してください。 ::: @@ -21,7 +22,7 @@ lang: ja-jp :::tip -通常の業務の妨げにならないよう、別の開発用のワークスペースを使用することをおすすめします。[新しいワークスペースは無料で作成できます](https://slack.com/get-started#create) +通常の業務の妨げにならないよう、別の開発用のワークスペースを使用することをおすすめします。[新しいワークスペースは無料で作成できます](https://api.slack.com/developer-program) :::。 diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/tutorial/getting-started-http.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/tutorial/getting-started-http.md index 5550464a3..129729bc5 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/tutorial/getting-started-http.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/tutorial/getting-started-http.md @@ -3,41 +3,10 @@ title: Bolt 入門ガイド(HTTP) slug: getting-started-http lang: ja-jp --- - -# Bolt 入門ガイド(HTTP) - -このガイドでは、**HTTP上で Bolt for Python** を使った Slack アプリの設定と起動する方法について説明します。ここで説明する手順は、新しい Slack アプリを作成し、ローカルの開発環境をセットアップし、Slack ワークスペースからのメッセージをリッスンして応答するアプリを開発するという流れになります。 - -この手順を全て終わらせたら、あなたはきっと ⚡️[Slack アプリのはじめ方](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started)のサンプルアプリを動作させたり、それに変更を加えたり、自分のアプリを作ったりすることができるようになるでしょう。 - --- -### アプリを作成する {#create-an-app} -最初にやるべきこと : Bolt での開発を始める前に、[Slack アプリを作成](https://api.slack.com/apps/new)します。 - -:::tip - -いつもの仕事のさまたげにならないように、別の開発用のワークスペースを使用することをおすすめします。[新しいワークスペースは無料で作成できます](https://slack.com/get-started#create)。 - -::: - -アプリ名を入力し(_後で変更可能_)、インストール先のワークスペースを選択したら、「`Create App`」ボタンをクリックすると、アプリの **Basic Information** ページが表示されます。 - -このページでは、アプリの概要を確認できます。また、「**App Credentials**」ヘッダーの下では「`Signing Secret`」などの重要な認証情報も確認できます。これらの認証情報は後で必要になります。 - -![Basic Information ページ](/img/boltpy/basic-information-page.png "Basic Information ページ") - -ひと通り確認し、アプリのアイコンと説明を追加したら、アプリの構成 🔩 を始めましょう。 - --- -### トークンとアプリのインストール {#tokens-and-installing-apps} -Slack アプリでは、[Slack API へのアクセスの管理に OAuth を使用します](https://api.slack.com/docs/oauth)。アプリがインストールされると、トークンが発行されます。アプリはそのトークンを使って API メソッドを呼び出すことができます。 - -Slack アプリで使用できるトークンには、ユーザートークン(`xoxp`)とボットトークン(`xoxb`)、アプリレベルトークン(`xapp`)の 3 種類があります。 -- [ユーザートークン](https://api.slack.com/authentication/token-types#user) を使用すると、ユーザーがアプリをインストールまたは認証した後、アプリがそのユーザーを代理して API メソッドを呼び出すことができます。1 つのワークスペースに複数のユーザートークンが存在する可能性があります。 -- [ボットトークン](https://api.slack.com/authentication/token-types#bot) はボットユーザーに関連づけられ、1 つのワークスペースでは最初に誰かがそのアプリをインストールした際に一度だけ発行されます。どのユーザーがインストールを実行しても、アプリが使用するボットトークンは同じになります。_ほとんど_のアプリで使用されるのは、ボットトークンです。 -- [アプリレベルトークン](https://api.slack.com/authentication/token-types#app) は、組織に渡ってあなたのアプリを表すものです。所属する組織内の全てのワークスペースに、全ての個人ユーザによってインストールされたアプリについても同様です。アプリレベルトークンは WebSocket 通信を行うアプリを作る際に通常使われます。 説明を簡潔にするために、このガイドではボットトークンを使用します。 diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css index 3831229a1..e89449bde 100644 --- a/docs/src/css/custom.css +++ b/docs/src/css/custom.css @@ -1,31 +1,19 @@ -/** - * Any CSS included here will be global. The classic template - * bundles Infima by default. Infima is a CSS framework designed to - * work well for content-centric websites. - */ - :root { /* set hex colors here pls */ --aubergine: #4a154b; - /* aubergine-active is used in light mode. use something like #853c8c if you use as a link vs black text ( 3:1 contr) */ --aubergine-active: #7c3085; - /* aubergine-light is used in dark mode. #b681b5 is another one. i just made both up */ --aubergine-light: #ce70cc; - /* horchata is that beige color we use a lot */ --horchata: #f4ede4; - - /* slack-blue is 36C5F0. used for dark-mode links */ - --slack-link: #36c5f0; - --slack-blue: #36c5f0; + /* cloud blue from slack.dev. used for dark-mode links */ + --slack-cloud-blue: #1ab9ff; /* slack marketing color for links 1264A3. used for light-mode links */ --slack-dark-blue: #1264a3; - --grey: #868686; - --white: #FFFFFF; + --dim: #eef2f6; } /* resets striped tables that hurt me eyes */ @@ -33,28 +21,32 @@ table tr:nth-child(even) { background-color: inherit; } -p a { - text-decoration: underline; - color: var(--slack-link); +/* changing the links to blue for accessibility */ +p a, .markdown a { + color: var(--slack-cloud-blue); } -.markdown a { - color: var(--slack-link); - text-decoration: underline; +/* a footer { + color: var(--slack-cloud-blue); +} */ + +a:hover { + color: var(--slack-cloud-blue); } /* adjusting for light and dark modes */ [data-theme="light"] { + --docusaurus-highlighted-code-line-bg: var(--dim); + --slack-cloud-blue: var(--slack-dark-blue); --ifm-color-primary: var(--aubergine-active); - --ifm-footer-background-color: var(--horchata); - --slack-link: var(--slack-dark-blue); } [data-theme="dark"] { - --ifm-color-primary: var(--aubergine-light); - --ifm-navbar-background-color: var(--aubergine); - --ifm-footer-background-color: var(--aubergine); - --slack-link: var(--slack-blue); + --ifm-color-primary: var(--slack-cloud-blue); + --ifm-navbar-background-color: black; + --method-link-text: white; + --scope-link-text: white; + --event-link-text: white; } html[data-theme="dark"] { @@ -66,10 +58,12 @@ html[data-theme="dark"] { font-weight: bold; } -/* only uncomment for home page -- colors white space on v tall screens */ -/* .main-wrapper { - background: var(--horchata); -} */ +/* increasing name of sdk in sidebar */ +.sidebar-title { + font-size: 1.25em; /* Adjust the size as needed */ + font-weight: bold; + color: #000; +} /* announcement bar up top */ div[class^="announcementBar_"] { @@ -79,16 +73,6 @@ div[class^="announcementBar_"] { } /* navbar */ - -.sidebar-item-overview a { - font-size: 1.2em; /* Adjust size as needed */ - font-weight: bold; -} - -html[data-theme='light'] .sidebar-item-overview a { - --ifm-menu-color: #000; -} - .navbar-github-link { width: 32px; height: 32px; @@ -116,12 +100,53 @@ html[data-theme="dark"] .navbar-github-link::before { no-repeat; } -.sidebar-title { - font-size: 1.25em; /* Adjust the size as needed */ - font-weight: bold; - color: #000; +/* Docs code bubbles */ +[data-theme="light"] { + --code-link-background: #CFE9FE; + --code-link-text: rgb(21, 50, 59); + + --method-link-background: #CDEFC4; + --method-link-text: rgb(0, 41, 0); + + --scope-link-background: #FBF3E0; + --scope-link-text: rgb(63, 46, 0); + + --event-link-background: #FDDDE3; + --event-link-text: rgb(74, 21, 75); +} + +[data-theme="dark"] { + --code-link-text: white; + --method-link-text: white; + --scope-link-text: white; + --event-link-text: white; + --code-link-background: #1AB9FF50; + --method-link-background: #41B65850; + --scope-link-background: #FCC00350; + --event-link-background: #E3066A50; +} + +a code { + background-color: var(--code-link-background); + color: var(--code-link-text); +} + +a[href^="https://api.slack.com/methods"] > code { + background-color: var(--method-link-background); + color: var(--method-link-text); +} + +a[href^="https://api.slack.com/scopes"] > code { + background-color: var(--scope-link-background); + color: var(--scope-link-text); +} + +a[href^="https://api.slack.com/events"] > code { + background-color: var(--event-link-background); + color: var(--event-link-text); } +/* Delineate tab blocks */ .tabs-container { border: 2px solid var(--ifm-hr-background-color); /* Adjust the color and thickness as needed */ border-radius: 5px; /* To give rounded corners */ From a24205771ebc68de90124ce7b0307538f9295a26 Mon Sep 17 00:00:00 2001 From: Luke Russell Date: Fri, 31 Jan 2025 07:54:21 -0800 Subject: [PATCH 3/4] docs- tweak sidebar --- docs/sidebars.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/sidebars.js b/docs/sidebars.js index a03e2f6fb..9d3a80d43 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -47,16 +47,22 @@ const sidebars = { }, { type: "category", - label: "Middleware & Adaptors", + label: "Middleware & Context", items: [ "concepts/global-middleware", "concepts/listener-middleware", - 'concepts/lazy-listeners', 'concepts/context', - 'concepts/adapters', - 'concepts/custom-adapters', ], }, + 'concepts/lazy-listeners', + { + type: "category", + label: "Adaptors", + items: [ + 'concepts/adapters', + 'concepts/custom-adapters', + ], + }, { type: "category", label: "Authorization & Security", From df42514c7c983f10a4a77dd36997a2b29d55aded Mon Sep 17 00:00:00 2001 From: Luke Russell Date: Fri, 31 Jan 2025 08:21:48 -0800 Subject: [PATCH 4/4] docs - only finished reorg ideas --- docs/content/concepts/steps-from-apps.md | 2 +- docs/content/getting-started.md | 309 +++-------------- docs/content/tutorial/getting-started-http.md | 322 ++++++++++++++++++ docs/docusaurus.config.js | 2 +- .../current/getting-started.md | 7 +- .../current/tutorial/getting-started-http.md | 32 ++ docs/sidebars.js | 219 ++++++------ 7 files changed, 519 insertions(+), 374 deletions(-) create mode 100644 docs/content/tutorial/getting-started-http.md diff --git a/docs/content/concepts/steps-from-apps.md b/docs/content/concepts/steps-from-apps.md index 728ec8e65..84315143b 100644 --- a/docs/content/concepts/steps-from-apps.md +++ b/docs/content/concepts/steps-from-apps.md @@ -1,7 +1,7 @@ --- title: Steps from apps lang: en -slug: /concepts/steps-from-apps +slug: /legacy/steps-from-apps --- :::danger diff --git a/docs/content/getting-started.md b/docs/content/getting-started.md index 32e8a2172..79ccfff61 100644 --- a/docs/content/getting-started.md +++ b/docs/content/getting-started.md @@ -1,23 +1,30 @@ --- -title: Getting started with Bolt for Python -sidebar_label: Getting started +title: Getting started slug: getting-started lang: en --- +# Getting started with Bolt for Python + This guide is meant to walk you through getting up and running with a Slack app using Bolt for Python. Along the way, we’ll create a new Slack app, set up your local environment, and develop an app that listens and responds to messages from a Slack workspace. -When you're finished, you'll have this ⚡️[Getting Started with Slack app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started) to run, modify, and make your own. + +When you're finished, you'll have this ⚡️[Getting Started with Slack app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started) to run, modify, and make your own. The possibilities are endless! + +:::info + +For this guide, we are going to be using [Socket Mode](https://api.slack.com/apis/connections/socket), our recommended option for those just getting started and building something for their team. If you already know you're going to want to use HTTP as your app's communication protocol, head over to our parallel guide, [Getting Started over HTTP](/tutorial/getting-started-http). + +::: --- -## Create an app {#create-an-app} - -Before you start developing with Bolt, you'll want to [create a Slack app](https://api.slack.com/apps/new). +### Create an app {#create-an-app} +First thing's first: before you start developing with Bolt, you'll want to [create a Slack app](https://api.slack.com/apps/new). :::tip -We recommend using a workspace where you won't disrupt real work getting done. Join the [Developer Program](https://api.slack.com/developer-program) and provision a sandbox with access to all Slack features for free. +We recommend using a workspace where you won't disrupt real work getting done — [you can create a new one for free](https://slack.com/get-started#create). ::: @@ -31,8 +38,7 @@ Look around, add an app icon and description, and then let's start configuring y --- -## Tokens and installing apps {#tokens-and-installing-apps} - +### Tokens and installing apps {#tokens-and-installing-apps} Slack apps use [OAuth to manage access to Slack's APIs](https://api.slack.com/docs/oauth). When an app is installed, you'll receive a token that the app can use to call API methods. There are three main token types available to a Slack app: user (`xoxp`), bot (`xoxb`), and app-level (`xapp`) tokens. @@ -40,7 +46,7 @@ There are three main token types available to a Slack app: user (`xoxp`), bot (` - [Bot tokens](https://api.slack.com/authentication/token-types#bot) are associated with bot users, and are only granted once in a workspace where someone installs the app. The bot token your app uses will be the same no matter which user performed the installation. Bot tokens are the token type that _most_ apps use. - [App-level tokens](https://api.slack.com/authentication/token-types#app) represent your app across organizations, including installations by all individual users on all workspaces in a given organization and are commonly used for creating WebSocket connections to your app. -We're going to use bot tokens for this guide. +We're going to use bot and app-level tokens for this guide. 1. Navigate to the **OAuth & Permissions** on the left sidebar and scroll down to the **Bot Token Scopes** section. Click **Add an OAuth Scope**. @@ -48,47 +54,24 @@ We're going to use bot tokens for this guide. 3. Scroll up to the top of the **OAuth & Permissions** page and click **Install App to Workspace**. You'll be led through Slack's OAuth UI, where you should allow your app to be installed to your development workspace. -4. Once you authorize the installation, you'll land on the **OAuth & Permissions** page and see a **Bot User OAuth Access Token**. Save it for later. +4. Once you authorize the installation, you'll land on the **OAuth & Permissions** page and see a **Bot User OAuth Access Token**. ![OAuth Tokens](/img/boltpy/bot-token.png "Bot OAuth Token") -:::info - -Treat your token like a password and [keep it safe](https://api.slack.com/docs/oauth-safety). Your app uses it to post and retrieve information from Slack workspaces. - -::: - -### Using Socket Mode or HTTP - -To listen for events happening in a Slack workspace (like when a message is posted or when a reaction is posted to a message) you'll use the [Events API to subscribe to event types](https://api.slack.com/events-api). - -For those just starting, we recommend using [Socket Mode](https://api.slack.com/apis/connections/socket). Socket Mode allows your app to use the Events API and interactive features without exposing a public HTTP Request URL. This can be helpful during development, or if you're receiving requests from behind a firewall. - -That being said, you're welcome to set up an app with a public HTTP Request URL. HTTP is more useful for apps being deployed to hosting environments (like [AWS](/deployments/aws-lambda) or [Heroku](/deployments/heroku) to stably respond within a large corporate Slack workspaces/organization, or apps intended for distribution via the Slack Marketplace. - -We've provided instructions for both ways in this guide. - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - - +5. Then head over to **Basic Information** and scroll down under the App Token section and click **Generate Token and Scopes** to generate an app-level token. Add the `connections:write` scope to this token and save the generated `xapp` token, we'll use both these tokens in just a moment. -If you're using Socket Mode, you'll also need an app-level token. +6. Navigate to **Socket Mode** on the left side menu and toggle to enable. -Head over to **Basic Information** and scroll down under the App Token section and click **Generate Token and Scopes** to generate an app-level token. Add the `connections:write` scope to this token and save the generated `xapp` token — you'll need it for later. - - +:::tip -If you're using HTTP, you'll also need a _signing secret_ that was generated when you configured your app. +Treat your tokens like passwords and [keep them safe](https://api.slack.com/docs/oauth-safety). Your app uses tokens to post and retrieve information from Slack workspaces. -Head over to **Basic Information** and save your _signing Secret_ — you'll need it for later. +::: - - +--- -## Setting up your project {#setting-up-your-project} +### Setting up your project {#setting-up-your-project} With the initial configuration handled, it's time to set up a new Bolt project. This is where you'll write the code that handles the logic for your app. If you don’t already have a project, let’s create a new one. Create an empty directory: @@ -112,33 +95,18 @@ which python3 # Output: /path/to/first-bolt-app/.venv/bin/python3 ``` -Copy your _bot (xoxb) token_ from the **OAuth & Permissions** page and store it as a new environment variable. +Before we install the Bolt for Python package to your new project, let's save the **bot token** and **app-level token** that were generated when you configured your app. +1. **Copy your bot (xoxb) token from the OAuth & Permissions page** and store it in a new environment variable. The following example works on Linux and macOS; but [similar commands are available on Windows](https://superuser.com/questions/212150/how-to-set-env-variable-in-windows-cmd-line/212153#212153). ```shell -export SLACK_BOT_TOKEN= +export SLACK_BOT_TOKEN=xoxb- ``` - - - -Store your _app-level (xapp) token_ as a new environment variable. - +2. **Copy your app-level (xapp) token from the Basic Information page** and then store it in a new environment variable. ```shell export SLACK_APP_TOKEN= ``` - - - -Store your _signing secret_ as a new environment variable. - -```shell -export SLACK_SIGNING_SECRET= -``` - - - - :::warning Keep all tokens secure. At a minimum, you should avoid checking them into public version control, and access them via environment variables as we've done above. Checkout the API documentation for more on [best practices for app security](https://api.slack.com/authentication/best-practices). @@ -153,9 +121,6 @@ pip install slack_bolt Create a new file called `app.py` in this directory and add the following code: - - - ```python import os from slack_bolt import App @@ -169,28 +134,7 @@ if __name__ == "__main__": SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start() ``` - - - -```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") -) - -# Start your app -if __name__ == "__main__": - app.start(port=int(os.environ.get("PORT", 3000))) -``` - - - - -Save your `app.py` file then on the command line run the following: +Your tokens are enough to create your first Bolt app. Save your `app.py` file then on the command line run the following: ```script python3 app.py @@ -200,41 +144,22 @@ Your app should let you know that it's up and running. 🎉 --- -## Setting up events {#setting-up-events} - -Your app behaves similarly to people on your team — it can post messages, add emoji reactions, and listen and respond to events. It's time to tell Slack what events we'd like to listen for. - -When an event occurs, Slack will send your app some information about the event, like the user that triggered it and the channel it occurred in. Your app will process the details and can respond accordingly. - -Let's enable events for your app. - - - +### Setting up events {#setting-up-events} +Your app behaves similarly to people on your team — it can post messages, add emoji reactions, and listen and respond to events. -1. Head to your app's app settings page (click on the app [from the app settings page](https://api.slack.com/apps)). Navigate to **Socket Mode** on the left side menu and toggle to enable. - -2. Go to **Basic Information** and scroll down under the App Token section and click **Generate Token and Scopes** to generate an app token. Add the `connections:write` scope to this token and save the generated `xapp` token, we'll use that in just a moment. - -3. Go to **Event Subscriptions** via the left sidebar. Toggle the switch labeled **Enable Events**. - - - - -1. Go to **Event Subscriptions** via the left sidebar. Toggle the switch labeled **Enable Events**. - -2. Add your Request URL. Slack will send HTTP POST requests corresponding to events to this [Request URL](https://api.slack.com/apis/connections/events-api#the-events-api__subscribing-to-event-types__events-api-request-urls) endpoint. Bolt uses the `/slack/events` path to listen to all incoming requests (whether shortcuts, events, or interactivity payloads). When configuring your Request URL within your app configuration, you'll append `/slack/events`, e.g. `https:///slack/events`. 💡 As long as your Bolt app is still running, your URL should become verified. +To listen for events happening in a Slack workspace (like when a message is posted or when a reaction is posted to a message) you'll use the [Events API to subscribe to event types](https://api.slack.com/events-api). -:::info +:::info -For local development, you can use a proxy service like [ngrok](https://ngrok.com/) to create a public URL and tunnel requests to your development environment. Refer to [ngrok's getting started guide](https://ngrok.com/docs#getting-started-expose) on how to create this tunnel. +Earlier in this tutorial we enabled Socket Mode. Socket Mode lets apps use the Events API and interactive components without exposing a public HTTP endpoint. This can be helpful during development, or if you're receiving requests from behind a firewall. HTTP is more useful for apps being deployed to hosting environments, or apps intended for distribution via the Slack App Directory. To follow this getting started guide with HTTP instead, head over [here](/tutorial/getting-started-http). ::: - - +It's time to tell Slack what events we'd like to listen for. -Under **Subscribe to Bot Events**, you can add events for your bot to respond to. There are four events related to messages: +When an event occurs, Slack will send your app some information about the event, like the user that triggered it and the channel it occurred in. Your app will process the details and can respond accordingly. +Navigate to **Event Subscriptions** on the left sidebar and toggle to enable. Under **Subscribe to Bot Events**, you can add events for your bot to respond to. There are four events related to messages: - [`message.channels`](https://api.slack.com/events/message.channels) listens for messages in public channels that your app is added to - [`message.groups`](https://api.slack.com/events/message.groups) listens for messages in 🔒 private channels that your app is added to - [`message.im`](https://api.slack.com/events/message.im) listens for messages in your app's DMs with users @@ -244,14 +169,11 @@ If you want your bot to listen to messages from everywhere it is added to, choos --- -## Listening and responding to a message {#listening-and-responding-to-a-message} +### Listening and responding to a message {#listening-and-responding-to-a-message} Your app is now ready for some logic. Let's start by using the `message()` method to attach a listener for messages. The following example listens and responds to all messages in channels/DMs where your app has been added that contain the word "hello": - - - ```python import os from slack_bolt import App @@ -273,61 +195,21 @@ if __name__ == "__main__": SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start() ``` - - - -```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" -# To learn available listener arguments, -# visit https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html -@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))) -``` - - - - If you restart your app, so long as your bot user has been added to the channel/DM, when you send any message that contains "hello", it will respond. -This is a short example, but it gives you a place to start customizing your app based on your own goals. Let's try something a little more interactive by sending a button rather than plain text. +This is a basic example, but it gives you a place to start customizing your app based on your own goals. Let's try something a little more interactive by sending a button rather than plain text. --- -## Sending and responding to actions {#sending-and-responding-to-actions} - -To use features like buttons, select menus, datepickers, modals, and shortcuts, you’ll need to enable interactivity. Head over to **Interactivity & Shortcuts** in your app settings. - - - +### Sending and responding to actions {#sending-and-responding-to-actions} -With Socket Mode on, basic interactivity is enabled for us by default, so no further action here is needed +To use features like buttons, select menus, datepickers, modals, and shortcuts, you’ll need to enable interactivity. Head over to **Interactivity & Shortcuts** in your app configuration. - - - -Similar to events, you'll need to specify a Request URL for Slack to send the action (such as *user clicked a button*). - -By default, Bolt is configured to use the same endpoint for interactive components that it uses for events, so use the same request URL as above (for example, `https://8e8ec2d7.ngrok.io/slack/events`). Press the **Save Changes** button in the lower right hand corner. Your app is now set up to handle interactivity! +:::tip -![Configuring a Request URL](/img/boltpy/request-url-config.png "Configuring a Request URL") +You’ll notice that with Socket Mode on, basic interactivity is enabled for us by default, so no further action here is needed. If you’re using HTTP, you’ll need to supply a Request URL for Slack to send events to. - - +::: When interactivity is enabled, interactions with shortcuts, modals, or interactive components (such as buttons, select menus, and datepickers) will be sent to your app as events. @@ -337,9 +219,6 @@ Now, let's go back to your app's code and add logic to handle those events: Below, the code from the last section is modified to send a message containing a button rather than just a string: - - - ```python import os from slack_bolt import App @@ -376,46 +255,6 @@ if __name__ == "__main__": ``` - - - -```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( - blocks=[ - { - "type": "section", - "text": {"type": "mrkdwn", "text": f"Hey there <@{message['user']}>!"}, - "accessory": { - "type": "button", - "text": {"type": "plain_text", "text": "Click Me"}, - "action_id": "button_click" - } - } - ], - text=f"Hey there <@{message['user']}>!" - ) - -# Start your app -if __name__ == "__main__": - app.start(port=int(os.environ.get("PORT", 3000))) -``` - - - - The value inside of `say()` is now an object that contains an array of `blocks`. Blocks are the building components of a Slack message and can range from text to images to datepickers. In this case, your app will respond with a section block that includes a button as an accessory. Since we're using `blocks`, the `text` is a fallback for notifications and accessibility. You'll notice in the button `accessory` object, there is an `action_id`. This will act as a unique identifier for the button so your app can specify what action it wants to respond to. @@ -430,9 +269,6 @@ Now, if you restart your app and say "hello" in a channel your app is in, you'll Let's add a handler to send a followup message when someone clicks the button: - - - ```python import os from slack_bolt import App @@ -471,66 +307,19 @@ if __name__ == "__main__": SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start() ``` - - - -```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( - blocks=[ - { - "type": "section", - "text": {"type": "mrkdwn", "text": f"Hey there <@{message['user']}>!"}, - "accessory": { - "type": "button", - "text": {"type": "plain_text", "text": "Click Me"}, - "action_id": "button_click" - } - } - ], - text=f"Hey there <@{message['user']}>!" - ) - -@app.action("button_click") -def action_button_click(body, ack, say): - # Acknowledge the action - ack() - say(f"<@{body['user']['id']}> clicked the button") - -# Start your app -if __name__ == "__main__": - app.start(port=int(os.environ.get("PORT", 3000))) -``` - - - - You can see that we used `app.action()` to listen for the `action_id` that we named `button_click`. If you restart your app and click the button, you'll see a new message from your app that says you clicked the button. --- -## Next steps {#next-steps} - -You just built your first [Bolt for Python app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started)! +### Next steps {#next-steps} +You just built your first [Bolt for Python app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started) with Socket Mode! 🎉 Now that you have a basic app up and running, you can start exploring how to make your Bolt app stand out. Here are some ideas about what to explore next: -* Read through the site to learn about the different methods and features your Bolt app has access to. +* Read through the _Basic concepts_ to learn about the different methods and features your Bolt app has access to. * Explore the different events your bot can listen to with the [`app.event()`](/concepts/event-listening) method. All of the events are listed [on the API site](https://api.slack.com/events). -* Bolt allows you to [call Web API methods](/concepts/web-api) with the client attached to your app. There are [over 200 methods](https://api.slack.com/methods) on our API site. +* Bolt allows you to [call Web API methods](/concepts/web-api) with the client attached to your app. There are [over 220 methods](https://api.slack.com/methods) on our API site. -* Learn more about the different token types [on our API site](https://api.slack.com/docs/token-types). Your app may need different tokens depending on the actions you want it to perform. \ No newline at end of file +* Learn more about the different token types [on our API site](https://api.slack.com/docs/token-types). Your app may need different tokens depending on the actions you want it to perform. For apps that do not use Socket Mode, typically only the bot (`xoxb`) token and Signing Secret are required. For example of this, see our parallel guide [Getting Started with HTTP](/tutorial/getting-started-http). \ No newline at end of file diff --git a/docs/content/tutorial/getting-started-http.md b/docs/content/tutorial/getting-started-http.md new file mode 100644 index 000000000..6cd4a8ae6 --- /dev/null +++ b/docs/content/tutorial/getting-started-http.md @@ -0,0 +1,322 @@ +--- +title: Getting started over HTTP +slug: getting-started-http +lang: en +--- + +# Getting started with Bolt for Python over HTTP + +This guide is meant to walk you through getting up and running with a Slack app using **Bolt for Python over HTTP**. Along the way, we’ll create a new Slack app, set up your local environment, and develop an app that listens and responds to messages from a Slack workspace. + + +When you're finished, you'll have this ⚡️[Getting Started with Slack app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started) to run, modify, and make your own. + +--- + +### Create an app {#create-an-app} +First thing's first: before you start developing with Bolt, you'll want to [create a Slack app](https://api.slack.com/apps/new). + +:::tip + +We recommend using a workspace where you won't disrupt real work getting done — [you can create a new one for free](https://slack.com/get-started#create). + +::: + +After you fill out an app name (_you can change it later_) and pick a workspace to install it to, hit the `Create App` button and you'll land on your app's **Basic Information** page. + +This page contains an overview of your app in addition to important credentials you'll need later, like the `Signing Secret` under the **App Credentials** header. + +![Basic Information page](/img/boltpy/basic-information-page.png "Basic Information page") + +Look around, add an app icon and description, and then let's start configuring your app 🔩 + +--- + +### Tokens and installing apps {#tokens-and-installing-apps} +Slack apps use [OAuth to manage access to Slack's APIs](https://api.slack.com/docs/oauth). When an app is installed, you'll receive a token that the app can use to call API methods. + +There are three main token types available to a Slack app: user (`xoxp`), bot (`xoxb`), and app-level (`xapp`) tokens. +- [User tokens](https://api.slack.com/authentication/token-types#user) allow you to call API methods on behalf of users after they install or authenticate the app. There may be several user tokens for a single workspace. +- [Bot tokens](https://api.slack.com/authentication/token-types#bot) are associated with bot users, and are only granted once in a workspace where someone installs the app. The bot token your app uses will be the same no matter which user performed the installation. Bot tokens are the token type that _most_ apps use. +- [App-level tokens](https://api.slack.com/authentication/token-types#app) represent your app across organizations, including installations by all individual users on all workspaces in a given organization and are commonly used for creating websocket connections to your app. + +For brevity, we're going to use bot tokens for this guide. + +1. Navigate to the **OAuth & Permissions** on the left sidebar and scroll down to the **Bot Token Scopes** section. Click **Add an OAuth Scope**. + +2. For now, we'll just add one scope: [`chat:write`](https://api.slack.com/scopes/chat:write). This grants your app the permission to post messages in channels it's a member of. + +3. Scroll up to the top of the OAuth & Permissions page and click **Install App to Workspace**. You'll be led through Slack's OAuth UI, where you should allow your app to be installed to your development workspace. + +4. Once you authorize the installation, you'll land on the **OAuth & Permissions** page and see a **Bot User OAuth Access Token**. We'll use that in just a moment. + +![OAuth Tokens](/img/boltpy/bot-token.png "Bot OAuth Token") + +:::info + +Treat your token like a password and [keep it safe](https://api.slack.com/docs/oauth-safety). Your app uses it to post and retrieve information from Slack workspaces. + +::: + +--- + +### Setting up your project {#setting-up-your-project} +With the initial configuration handled, it's time to set up a new Bolt project. This is where you'll write the code that handles the logic for your app. + +If you don’t already have a project, let’s create a new one. Create an empty directory: + +```shell +mkdir first-bolt-app +cd first-bolt-app +``` + +Next, we recommend using a [Python virtual environment](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/#creating-a-virtual-environment) to manage your project's dependencies. This is a great way to prevent conflicts with your system's Python packages. Let's create and activate a new virtual environment with [Python 3.6 or later](https://www.python.org/downloads/): + +```shell +python3 -m venv .venv +source .venv/bin/activate +``` + +We can confirm that the virtual environment is active by checking that the path to `python3` is _inside_ your project ([a similar command is available on Windows](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/#activating-a-virtual-environment)): + +```shell +which python3 +# Output: /path/to/first-bolt-app/.venv/bin/python3 +``` + +Before we install the Bolt for Python package to your new project, let's save the **bot token** and **signing secret** that were generated when you configured your app. + +1. **Copy your Signing Secret from the Basic Information page** and then store it in a new environment variable. The following example works on Linux and macOS; but [similar commands are available on Windows](https://superuser.com/questions/212150/how-to-set-env-variable-in-windows-cmd-line/212153#212153). +```shell +export SLACK_SIGNING_SECRET= +``` + +2. **Copy your bot (xoxb) token from the OAuth & Permissions page** and store it in another environment variable. +```shell +export SLACK_BOT_TOKEN=xoxb- +``` +> 🔒 Remember to keep your tokens and signing secret secure. At a minimum, you should avoid checking them into public version control, and access them via environment variables as we've done above. Checkout the API documentation for more on [best practices for app security](https://api.slack.com/authentication/best-practices). + +Now, let's create your app. Install the `slack_bolt` Python package to your virtual environment using the following command: + +```shell +pip install slack_bolt +``` + +Create a new file called `app.py` in this directory and add the following code: + +```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") +) + +# Start your app +if __name__ == "__main__": + app.start(port=int(os.environ.get("PORT", 3000))) +``` + +Your token and signing secret are enough to create your first Bolt app. Save your `app.py` file then on the command line run the following: + +```script +python3 app.py +``` + +Your app should let you know that it's up and running. 🎉 + +--- + +### Setting up events over HTTP {#setting-up-events} +Your app behaves similarly to people on your team — it can post messages, add emoji reactions, and listen and respond to events. + +To listen for events happening in a Slack workspace (like when a message is posted or when a reaction is posted to a message) you'll use the [Events API to subscribe to event types](https://api.slack.com/events-api). + +Let's enable events for your app: +1. Go back to your app configuration page (click on the app [from your app management page](https://api.slack.com/apps)). Click **Event Subscriptions** on the left sidebar. Toggle the switch labeled **Enable Events**. + +2. Add your Request URL. Slack will send HTTP POST requests corresponding to events to this [Request URL](https://api.slack.com/apis/connections/events-api#the-events-api__subscribing-to-event-types__events-api-request-urls) endpoint. Bolt uses the `/slack/events` path to listen to all incoming requests (whether shortcuts, events, or interactivity payloads). When configuring your Request URL within your app configuration, you'll append `/slack/events`, e.g. `https:///slack/events`. 💡 As long as your Bolt app is still running, your URL should become verified. + +:::tip + +For local development, you can use a proxy service like ngrok to create a public URL and tunnel requests to your development environment. Refer to [ngrok's getting started guide](https://ngrok.com/docs#getting-started-expose) on how to create this tunnel. And when you get to hosting your app, we've collected some of the most common hosting providers Slack developers use to host their apps [on our API site](https://api.slack.com/docs/hosting). + +::: + +Finally, it's time to tell Slack what events we'd like to listen for. + +When an event occurs, Slack will send your app some information about the event, like the user that triggered it and the channel it occurred in. Your app will process the details and can respond accordingly. + +Navigate to **Event Subscriptions** on the left sidebar and toggle to enable. Under **Subscribe to Bot Events**, you can add events for your bot to respond to. There are four events related to messages: +- [`message.channels`](https://api.slack.com/events/message.channels) listens for messages in public channels that your app is added to +- [`message.groups`](https://api.slack.com/events/message.groups) listens for messages in 🔒 private channels that your app is added to +- [`message.im`](https://api.slack.com/events/message.im) listens for messages in your app's DMs with users +- [`message.mpim`](https://api.slack.com/events/message.mpim) listens for messages in multi-person DMs that your app is added to + +If you want your bot to listen to messages from everywhere it is added to, choose all four message events. After you’ve selected the events you want your bot to listen to, click the green **Save Changes** button. + +--- + +### Listening and responding to a message {#listening-and-responding-to-a-message} +Your app is now ready for some logic. Let's start by using the `message()` method to attach a listener for messages. + +The following example listens and responds to all messages in channels/DMs where your app has been added that contain the word "hello": + +```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" +# To learn available listener arguments, +# visit https://tools.slack.dev/bolt-python/api-docs/slack_bolt/kwargs_injection/args.html +@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))) +``` + +If you restart your app, so long as your bot user has been added to the channel/DM, when you send any message that contains "hello", it will respond. + +This is a basic example, but it gives you a place to start customizing your app based on your own goals. Let's try something a little more interactive by sending a button rather than plain text. + +--- + +### Sending and responding to actions {#sending-and-responding-to-actions} + +To use features like buttons, select menus, datepickers, modals, and shortcuts, you’ll need to enable interactivity. Similar to events, you'll need to specify a URL for Slack to send the action (such as *user clicked a button*). + +Back on your app configuration page, click on **Interactivity & Shortcuts** on the left side. You'll see that there's another **Request URL** box. + +:::tip + +By default, Bolt is configured to use the same endpoint for interactive components that it uses for events, so use the same request URL as above (for example, `https://8e8ec2d7.ngrok.io/slack/events`). Press the **Save Changes** button in the lower right hand corner, and that's it. Your app is set up to handle interactivity! + +::: + +![Configuring a Request URL](/img/boltpy/request-url-config.png "Configuring a Request URL") + +When interactivity is enabled, interactions with shortcuts, modals, or interactive components (such as buttons, select menus, and datepickers) will be sent to your app as events. + +Now, let's go back to your app's code and add logic to handle those events: +- First, we'll send a message that contains an interactive component (in this case a button) +- Next, we'll listen for the action of a user clicking the button before responding + +Below, the code from the last section is modified to send a message containing a button rather than just a string: + +```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( + blocks=[ + { + "type": "section", + "text": {"type": "mrkdwn", "text": f"Hey there <@{message['user']}>!"}, + "accessory": { + "type": "button", + "text": {"type": "plain_text", "text": "Click Me"}, + "action_id": "button_click" + } + } + ], + text=f"Hey there <@{message['user']}>!" + ) + +# Start your app +if __name__ == "__main__": + app.start(port=int(os.environ.get("PORT", 3000))) +``` + +The value inside of `say()` is now an object that contains an array of `blocks`. Blocks are the building components of a Slack message and can range from text to images to datepickers. In this case, your app will respond with a section block that includes a button as an accessory. Since we're using `blocks`, the `text` is a fallback for notifications and accessibility. + +You'll notice in the button `accessory` object, there is an `action_id`. This will act as a unique identifier for the button so your app can specify what action it wants to respond to. + +:::tip + +The [Block Kit Builder](https://app.slack.com/block-kit-builder) is an simple way to prototype your interactive messages. The builder lets you (or anyone on your team) mockup messages and generates the corresponding JSON that you can paste directly in your app. + +::: + +Now, if you restart your app and say "hello" in a channel your app is in, you'll see a message with a button. But if you click the button, nothing happens (*yet!*). + +Let's add a handler to send a followup message when someone clicks the button: + +```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( + blocks=[ + { + "type": "section", + "text": {"type": "mrkdwn", "text": f"Hey there <@{message['user']}>!"}, + "accessory": { + "type": "button", + "text": {"type": "plain_text", "text": "Click Me"}, + "action_id": "button_click" + } + } + ], + text=f"Hey there <@{message['user']}>!" + ) + +@app.action("button_click") +def action_button_click(body, ack, say): + # Acknowledge the action + ack() + say(f"<@{body['user']['id']}> clicked the button") + +# Start your app +if __name__ == "__main__": + app.start(port=int(os.environ.get("PORT", 3000))) +``` + +You can see that we used `app.action()` to listen for the `action_id` that we named `button_click`. If you restart your app and click the button, you'll see a new message from your app that says you clicked the button. + +--- + +### Next steps {#next-steps} +You just built your first [Bolt for Python app](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started)! 🎉 + +Now that you have a basic app up and running, you can start exploring how to make your Bolt app stand out. Here are some ideas about what to explore next: + +* Read through the _Basic concepts_ to learn about the different methods and features your Bolt app has access to. + +* Explore the different events your bot can listen to with the [`app.event()` method](/concepts/event-listening). All of the events are listed [on the API site](https://api.slack.com/events). + +* Bolt allows you to [call Web API methods](/concepts/web-api) with the client attached to your app. There are [over 220 methods](https://api.slack.com/methods) on our API site. + +* Learn more about the different token types [on our API site](https://api.slack.com/docs/token-types). Your app may need different tokens depending on the actions you want it to perform. If you are using Socket Mode instead of HTTP, an additional (`xapp`) token with `connections:write` scopes is required. \ No newline at end of file diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index f7abced22..b7a5ad096 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -49,7 +49,7 @@ const config = { redirects: [ { to: "/getting-started", - from: ["/tutorial/getting-started", "/tutorial/getting-started-http"], + from: ["/tutorial/getting-started"], }, { to: "/", diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/getting-started.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/getting-started.md index 5fedf19b2..41aecf6ef 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/getting-started.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/getting-started.md @@ -4,13 +4,15 @@ slug: getting-started lang: ja-jp --- +# Bolt 入門ガイド + このガイドでは、Bolt for Python を使った Slack アプリの設定と起動の方法について説明します。ここで説明する手順では、まず新しい Slack アプリを作成し、ローカルの開発環境をセットアップし、Slack ワークスペースからのメッセージをリッスンして応答するアプリを開発するという流れになります。 + この手順を全て終わらせたら、あなたはきっと ⚡️[Slack アプリのはじめ方](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started)のサンプルアプリを動作させたり、それに変更を加えたり、自分のアプリを作ったりすることができるようになるでしょう。 :::tip -REMOVE このガイドでは[ソケットモード](https://api.slack.com/apis/connections/socket) を利用します。ソケットモードは、Slack アプリ開発をとりあえず始めてみるときやあなたのチームだけのためのアプリをつくるときにおすすめのやり方です。もしすでに HTTP をアプリのコミュニケーションプロトコルとするとわかっている場合は、HTTP の方式に対応した同様のドキュメントである [Bolt 入門ガイド(HTTP)](/tutorial/getting-started-http) を参照してください。 ::: @@ -22,7 +24,7 @@ REMOVE :::tip -通常の業務の妨げにならないよう、別の開発用のワークスペースを使用することをおすすめします。[新しいワークスペースは無料で作成できます](https://api.slack.com/developer-program) +通常の業務の妨げにならないよう、別の開発用のワークスペースを使用することをおすすめします。[新しいワークスペースは無料で作成できます](https://slack.com/get-started#create) :::。 @@ -106,6 +108,7 @@ export SLACK_APP_TOKEN=<アプリレベルトークン> > 🔒 全てのトークンは安全に保管してください。少なくともパブリックなバージョン管理にチェックインするようなことは避けるべきでしょう。また、上にあった例のように環境変数を介してアクセスするようにしてください。詳細な情報は [アプリのセキュリティのベストプラクティス](https://api.slack.com/authentication/best-practices)のドキュメントを参照してください。 + 完了したら、いよいよアプリを作っていきましょう。以下のコマンドを使って、仮想環境に Python の `slack_bolt` パッケージをインストールします。 ```shell diff --git a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/tutorial/getting-started-http.md b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/tutorial/getting-started-http.md index 129729bc5..b6c461de2 100644 --- a/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/tutorial/getting-started-http.md +++ b/docs/i18n/ja-jp/docusaurus-plugin-content-docs/current/tutorial/getting-started-http.md @@ -3,10 +3,41 @@ title: Bolt 入門ガイド(HTTP) slug: getting-started-http lang: ja-jp --- + +# Bolt 入門ガイド(HTTP) + +このガイドでは、**HTTP上で Bolt for Python** を使った Slack アプリの設定と起動する方法について説明します。ここで説明する手順は、新しい Slack アプリを作成し、ローカルの開発環境をセットアップし、Slack ワークスペースからのメッセージをリッスンして応答するアプリを開発するという流れになります。 + +この手順を全て終わらせたら、あなたはきっと ⚡️[Slack アプリのはじめ方](https://github.com/slackapi/bolt-python/tree/main/examples/getting_started)のサンプルアプリを動作させたり、それに変更を加えたり、自分のアプリを作ったりすることができるようになるでしょう。 + --- +### アプリを作成する {#create-an-app} +最初にやるべきこと : Bolt での開発を始める前に、[Slack アプリを作成](https://api.slack.com/apps/new)します。 + +:::tip + +いつもの仕事のさまたげにならないように、別の開発用のワークスペースを使用することをおすすめします。[新しいワークスペースは無料で作成できます](https://slack.com/get-started#create)。 + +::: + +アプリ名を入力し(_後で変更可能_)、インストール先のワークスペースを選択したら、「`Create App`」ボタンをクリックすると、アプリの **Basic Information** ページが表示されます。 + +このページでは、アプリの概要を確認できます。また、「**App Credentials**」ヘッダーの下では「`Signing Secret`」などの重要な認証情報も確認できます。これらの認証情報は後で必要になります。 + +![Basic Information ページ](/img/boltpy/basic-information-page.png "Basic Information ページ") + +ひと通り確認し、アプリのアイコンと説明を追加したら、アプリの構成 🔩 を始めましょう。 + --- +### トークンとアプリのインストール {#tokens-and-installing-apps} +Slack アプリでは、[Slack API へのアクセスの管理に OAuth を使用します](https://api.slack.com/docs/oauth)。アプリがインストールされると、トークンが発行されます。アプリはそのトークンを使って API メソッドを呼び出すことができます。 + +Slack アプリで使用できるトークンには、ユーザートークン(`xoxp`)とボットトークン(`xoxb`)、アプリレベルトークン(`xapp`)の 3 種類があります。 +- [ユーザートークン](https://api.slack.com/authentication/token-types#user) を使用すると、ユーザーがアプリをインストールまたは認証した後、アプリがそのユーザーを代理して API メソッドを呼び出すことができます。1 つのワークスペースに複数のユーザートークンが存在する可能性があります。 +- [ボットトークン](https://api.slack.com/authentication/token-types#bot) はボットユーザーに関連づけられ、1 つのワークスペースでは最初に誰かがそのアプリをインストールした際に一度だけ発行されます。どのユーザーがインストールを実行しても、アプリが使用するボットトークンは同じになります。_ほとんど_のアプリで使用されるのは、ボットトークンです。 +- [アプリレベルトークン](https://api.slack.com/authentication/token-types#app) は、組織に渡ってあなたのアプリを表すものです。所属する組織内の全てのワークスペースに、全ての個人ユーザによってインストールされたアプリについても同様です。アプリレベルトークンは WebSocket 通信を行うアプリを作る際に通常使われます。 説明を簡潔にするために、このガイドではボットトークンを使用します。 @@ -66,6 +97,7 @@ export SLACK_BOT_TOKEN=xoxb- > 🔒 全てのトークンは安全に保管してください。最低限、パブリックなバージョンコントロールにチェックインすることは避けてください。また、上記の例のように環境変数を介してアクセスするようにしてください。詳細な情報は [best practices for app security](https://api.slack.com/authentication/best-practices).のドキュメントを参照してください。 + 完了したら、アプリを作ってみましょう。以下のコマンドを使って、仮想環境に Python の `slack_bolt` パッケージをインストールします。 ```shell diff --git a/docs/sidebars.js b/docs/sidebars.js index 9d3a80d43..7b1db75c2 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -1,115 +1,114 @@ /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ const sidebars = { - sidebarBoltPy: [ - { - type: 'doc', - id: 'index', - label: 'Bolt for Python', - className: 'sidebar-title', - }, - 'getting-started', - { - type: "category", - label: "Slack API calls", - items: ["concepts/message-sending", "concepts/web-api"], - }, - { - type: "category", - label: "Events API", - items: ["concepts/message-listening", "concepts/event-listening"], - }, - { - type: "category", - label: "App UI & Interactivity", - items: [ - "concepts/acknowledge", - "concepts/shortcuts", - "concepts/commands", - "concepts/actions", - "concepts/opening-modals", - "concepts/updating-pushing-views", - "concepts/view-submissions", - "concepts/select-menu-options", - "concepts/app-home", - ], - }, - 'concepts/assistant', - 'concepts/custom-steps', - { - type: "category", - label: "App Configuration", - items: [ - "concepts/socket-mode", - "concepts/errors", - "concepts/logging", - 'concepts/async', - ], - }, - { - type: "category", - label: "Middleware & Context", - items: [ - "concepts/global-middleware", - "concepts/listener-middleware", - 'concepts/context', - ], - }, - 'concepts/lazy-listeners', - { - type: "category", - label: "Adaptors", - items: [ - 'concepts/adapters', - 'concepts/custom-adapters', - ], - }, - { - type: "category", - label: "Authorization & Security", - items: [ - "concepts/authenticating-oauth", - "concepts/authorization", - "concepts/token-rotation", - ], - }, - { - type: 'category', - label: 'Legacy', - items: [ - 'concepts/steps-from-apps', - ], - }, - { type: 'html', value: '
' }, - { - type: 'category', - label: 'Tutorials', - items: [ - 'tutorial/ai-chatbot' - ], - }, - { type: 'html', value: '
' }, - { - type: 'link', - label: 'Reference', - href: 'https://tools.slack.dev/bolt-python/api-docs/slack_bolt/', - }, - { type: 'html', value: '
' }, - { - type: 'link', - label: 'Release notes', - href: 'https://github.com/slackapi/bolt-python/releases', - }, - { - type: 'link', - label: 'Code on GitHub', - href: 'https://github.com/SlackAPI/bolt-python', - }, - { - type: 'link', - label: 'Contributors Guide', - href: 'https://github.com/SlackAPI/bolt-python/blob/main/.github/contributing.md', - }, - ], + sidebarBoltPy: [ + { + type: "category", + label: "Guides", + items: [ + { + type: "doc", + id: "index", + label: "Bolt for Python", + className: "sidebar-title", + }, + "getting-started", + { + type: "category", + label: "Slack API calls", + items: ["concepts/message-sending", "concepts/web-api"], + }, + { + type: "category", + label: "Events API", + items: ["concepts/message-listening", "concepts/event-listening"], + }, + { + type: "category", + label: "App UI & Interactivity", + items: [ + "concepts/acknowledge", + "concepts/shortcuts", + "concepts/commands", + "concepts/actions", + "concepts/opening-modals", + "concepts/updating-pushing-views", + "concepts/view-submissions", + "concepts/select-menu-options", + "concepts/app-home", + ], + }, + "concepts/assistant", + "concepts/custom-steps", + { + type: "category", + label: "App Configuration", + items: [ + "concepts/socket-mode", + "concepts/errors", + "concepts/logging", + "concepts/async", + ], + }, + { + type: "category", + label: "Middleware & Context", + items: [ + "concepts/global-middleware", + "concepts/listener-middleware", + "concepts/context", + ], + }, + "concepts/lazy-listeners", + { + type: "category", + label: "Adaptors", + items: ["concepts/adapters", "concepts/custom-adapters"], + }, + { + type: "category", + label: "Authorization & Security", + items: [ + "concepts/authenticating-oauth", + "concepts/authorization", + "concepts/token-rotation", + ], + }, + { + type: "category", + label: "Legacy", + items: ["concepts/steps-from-apps"], + }, + ], + }, + { type: "html", value: "
" }, + { + type: "category", + label: "Tutorials", + items: ["tutorial/ai-chatbot", "tutorial/getting-started-http"], + }, + { type: "html", value: "
" }, + { + type: "link", + label: "Reference", + href: "https://tools.slack.dev/bolt-python/api-docs/slack_bolt/", + }, + { type: "html", value: "
" }, + { + type: "link", + label: "Release notes", + href: "https://github.com/slackapi/bolt-python/releases", + }, + { + type: "link", + label: "Code on GitHub", + href: "https://github.com/SlackAPI/bolt-python", + }, + { + type: "link", + label: "Contributors Guide", + href: "https://github.com/SlackAPI/bolt-python/blob/main/.github/contributing.md", + }, + ], }; export default sidebars;