From 0a7100c3fc65672cf017af21cdfd013d60f8cf6d Mon Sep 17 00:00:00 2001 From: Shane DeWael Date: Wed, 15 May 2019 16:57:38 -0700 Subject: [PATCH 1/2] Small edits throughout the existing docs --- docs/_advanced/authorization.md | 8 ++-- docs/_advanced/conversation_store.md | 8 ++-- docs/_advanced/error_handling.md | 2 +- docs/_advanced/logging.md | 2 +- docs/_advanced/middleware_global.md | 2 +- docs/_advanced/middleware_listener.md | 2 +- docs/_advanced/receiver.md | 4 +- docs/_basic/listening_actions.md | 6 +-- docs/_basic/listening_events.md | 2 +- docs/_basic/listening_messages.md | 4 +- docs/_basic/listening_responding_commands.md | 2 +- docs/_basic/responding_actions.md | 4 +- docs/_basic/sending_messages.md | 2 +- docs/_tutorials/getting_started.md | 48 ++++++++++---------- 14 files changed, 48 insertions(+), 48 deletions(-) diff --git a/docs/_advanced/authorization.md b/docs/_advanced/authorization.md index e00ae5088..2d46467a6 100644 --- a/docs/_advanced/authorization.md +++ b/docs/_advanced/authorization.md @@ -7,13 +7,13 @@ order: 2
Authorization is the process of deciding which Slack credentials (such as a bot token) should be available while processing a specific incoming event. -Custom apps installed on a single workspace can simply use the `token` option at the time of `App` initialization. However, when your app needs to handle multiple tokens, such as cases where it will be installed on multiple workspaces or needs access to more than one user token, the `authorize` option should be used instead. +Custom apps installed on a single workspace can simply use the `token` option at the time of `App` initialization. However, when your app needs to handle several tokens, such as cases where it will be installed on multiple workspaces or needs access to more than one user token, the `authorize` option should be used instead. -The `authorize` option should be set to a function that takes an event source as its input, and should return a Promise for an object containing the authorized credentials. The source contains information about who and where the event is coming from using properties like `teamId` (always available), `userId`, `conversationId`, and `enterpriseId`. +The `authorize` option can be set to a function that takes an event source as its input, and should return a Promise for an object containing the authorized credentials. The source contains information about who and where the event is coming from by using properties like `teamId` (always available), `userId`, `conversationId`, and `enterpriseId`. -The authorized credentials should also have a few specific properties: `botToken`, `userToken`, `botId` (required for app to ignore messages from itself), and `botUserId`. You can also include any other properties you'd like to make available on the [`context`](#context). +The authorized credentials should also have a few specific properties: `botToken`, `userToken`, `botId` (required for an app to ignore messages from itself), and `botUserId`. You can also include any other properties you'd like to make available on the [`context`](#context) object. -You should always provide either one or both of the `botToken` and `userToken` properties. One of them is necessary to make helpers like `say()` work. If they are both given, then `botToken` will take precedence. +You should always provide either one or both of the `botToken` and `userToken` properties. At least one of them is necessary to make helpers like `say()` work. If they are both given, then `botToken` will take precedence.
```javascript diff --git a/docs/_advanced/conversation_store.md b/docs/_advanced/conversation_store.md index e2d31617c..bef1c2839 100644 --- a/docs/_advanced/conversation_store.md +++ b/docs/_advanced/conversation_store.md @@ -6,12 +6,12 @@ order: 3
Bolt includes support for a store, which sets and retrieves state related to a conversation. Conversation stores have two methods: -* `set()` modifies conversation state. `set()` requires a `conversationId` of type string, `value` that can be any type, and an optional `expiresAt` of type number. `set()` returns a `Promise`. -* `get()` fetches conversation state from the store. Get requires a `conversationId` of type string and returns a Promise with the conversation’s state. +* `set()` modifies conversation state. `set()` requires a `conversationId` of type string, `value` of any type, and an optional `expiresAt` of type number. `set()` returns a `Promise`. +* `get()` fetches conversation state from the store. `get()` requires a `conversationId` of type string and returns a Promise with the conversation’s state. -`conversationContext()` is a built-in [global middleware](#global-middleware) that allows conversations to be updated by middleware. When receiving an event, middleware functions can use `context.updateConversation()` to set state and reading from `context.conversation` to retrieve it. +`conversationContext()` is a built-in [global middleware](#global-middleware) that allows conversations to be updated by other middleware. When receiving an event, middleware functions can use `context.updateConversation()` to set state and `context.conversation` to retrieve it. -The default (built-in) conversation store simply stores conversation state in memory. While this is sufficient for some situations, if there is more than one instance of your app running the state will not be shared among your processes so you’ll want to implement a conversation store that fetches conversation state from a database. +The built-in conversation store simply stores conversation state in memory. While this is sufficient for some situations, if there is more than one instance of your app running, the state will not be shared among the processes so you’ll want to implement a conversation store that fetches conversation state from a database.
```javascript diff --git a/docs/_advanced/error_handling.md b/docs/_advanced/error_handling.md index 631fcfa92..1fca0097d 100644 --- a/docs/_advanced/error_handling.md +++ b/docs/_advanced/error_handling.md @@ -5,7 +5,7 @@ order: 1 ---
-If an error occurs in a listener, it’s recommended you handle it directly. However, there are cases where errors may occur after your listener middleware has returned (such as `say()`, `respond()`, or not calling `ack()`). By default, these errors will be logged to the console. To handle them yourself, you can attach a global error handler to your app using the `error(fn)` method. +If an error occurs in a listener, it’s recommended you handle it directly. However, there are cases where errors may be triggered after your listener middleware has already returned (such as in `say()`, `respond()`, or if you don't call `ack()` when it's required). By default, these errors will be logged to the console. To handle them yourself, you can attach a global error handler to your app with the `error(fn)` method. If you want more control over errors, it’s advised to use the [`chat.postMessage`](https://api.slack.com/methods/chat.postMessage) method attached to your app under the `client` key (instead of `say()` or `respond()`). This returns a `Promise` that can be caught to handle the error.
diff --git a/docs/_advanced/logging.md b/docs/_advanced/logging.md index dd0c0190b..a48e151c1 100644 --- a/docs/_advanced/logging.md +++ b/docs/_advanced/logging.md @@ -26,7 +26,7 @@ const app = new App({
-If you want to send logs to somewhere besides the console or want more control over the logger, you can implement a logger. A custom logger must implement specific methods (known as the `Logger` interface): +If you want to send logs to somewhere besides the console or want more control over the logger, you can implement a custom logger. A custom logger must implement specific methods (known as the `Logger` interface): | Method | Parameters | Return type | |--------------|-------------------|-------------| diff --git a/docs/_advanced/middleware_global.md b/docs/_advanced/middleware_global.md index 27a2ed71e..5681a17cc 100644 --- a/docs/_advanced/middleware_global.md +++ b/docs/_advanced/middleware_global.md @@ -7,7 +7,7 @@ order: 4
Global middleware is run for all incoming events before any listener middleware. You can add any number of global middleware to your app by utilizing `app.use(fn(payload,...,next))`. -Both global and listener middleware must call `next()` to pass control of the execution chain to the next middleware, or call `next(error)` to pass an error back up the already-executed middleware chain. +Both global and listener middleware must call `next()` to pass control of the execution chain to the next middleware, or call `next(error)` to pass an error back up the previously-executed middleware chain. As an example, let's say your app should only respond to users identified with a corresponding internal authentication service (an SSO provider or LDAP, for example). You may define a global middleware that looks up a user record in the authentication service and errors if the user is not found.
diff --git a/docs/_advanced/middleware_listener.md b/docs/_advanced/middleware_listener.md index 4a51d929c..8503839e8 100644 --- a/docs/_advanced/middleware_listener.md +++ b/docs/_advanced/middleware_listener.md @@ -9,7 +9,7 @@ Listener middleware is used for logic across many listener functions (but usuall There’s a collection of built-in listener middleware that you can use like `subtype()` for filtering on a message subtype and `directionMention()` which filters out any message that doesn’t directly @-mention your bot. -But of course, you can write your own middleware for more custom functionality. While writing your own middleware, your function must call `next()` to pass control to the next middleware, or calling `next(error)` to pass an error back up the already-executed middleware chain. +But of course, you can write your own middleware for more custom functionality. While writing your own middleware, your function must call `next()` to pass control to the next middleware, or call `next(error)` to pass an error back up the previously-executed middleware chain. As an example, let’s say your listener should only deal with messages from humans. You can write a listener middleware that excludes any bot messages. diff --git a/docs/_advanced/receiver.md b/docs/_advanced/receiver.md index 58a16228b..4041b7e48 100644 --- a/docs/_advanced/receiver.md +++ b/docs/_advanced/receiver.md @@ -5,7 +5,7 @@ order: 8 ---
-A receiver is responsible for handling and parsing any incoming requests from Slack, then emitting the request so the Bolt app can add context and pass the request to your app’s listeners. Receivers must conform to the Receiver interface: +A receiver is responsible for handling and parsing any incoming events from Slack, then emitting the event so the Bolt app can add context and pass it to your app’s listeners. Receivers must conform to the Receiver interface: | Method | Parameters | Return type | |--------------|----------------------------------|-------------| @@ -17,7 +17,7 @@ A receiver is responsible for handling and parsing any incoming requests from Sl * `Receiver.on('message', listener)` should route all incoming requests that have been parsed to `onIncomingEvent()`. It’s called in the Bolt app as `this.receiver.on('message', message => this.onIncomingEvent(message))`. * `Receiver.on('error', listener)` should route errors to the global error handler. It’s called in the Bolt app as `this.receiver.on('error', error => this.onGlobalError(error))`. -To use a custom receiver, you’ll need to pass it into the constructor when initializing your Bolt app. Here is what a basic custom receiver might look like. +To use a custom receiver, you can pass it into the constructor when initializing your Bolt app. Here is what a basic custom receiver might look like. For a more in-depth look at a receiver, [read the source code for the built-in Express receiver](https://github.com/slackapi/bolt/blob/master/src/ExpressReceiver.ts)
diff --git a/docs/_basic/listening_actions.md b/docs/_basic/listening_actions.md index feeeff7e8..5a833ddbd 100644 --- a/docs/_basic/listening_actions.md +++ b/docs/_basic/listening_actions.md @@ -7,9 +7,9 @@ order: 5
Your app can listen to user actions like button clicks, menu selects, and message actions using the `action` method. -Actions can be filtered on an `action_id` of type string or RegExp. `action_id`s act as unique identifiers for interactive components on the Slack platform. +Actions can be filtered on an `action_id` of type string or RegExp object. `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 the event was received from Slack. This is discussed in the [acknowledging requests section](#acknowledge). +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 event was received from Slack. This is discussed in the [acknowledging events section](#acknowledge).
@@ -27,7 +27,7 @@ app.action('approve_button', async ({ ack, say }) => {
-You can use a constraints object to listen to `callback_id`s, `block_id`s, and `action_id`s (or any combination of them). Constraints in the object can be of type string or RegExp. +You can use a constraints object to listen to `callback_id`s, `block_id`s, and `action_id`s (or any combination of them). Constraints in the object can be of type string or RegExp object.
```javascript diff --git a/docs/_basic/listening_events.md b/docs/_basic/listening_events.md index b2c5b3da9..e739c0a9d 100644 --- a/docs/_basic/listening_events.md +++ b/docs/_basic/listening_events.md @@ -5,7 +5,7 @@ order: 3 ---
-You can listen to [any Events API event](https://api.slack.com/events) using the `event()` method by subscribing to it in your app configuration. on your This allows your app to take action when something happens in Slack, like a user reacting to a message or joining a channel. +You can listen to [any Events API event](https://api.slack.com/events) using the `event()` method after subscribing to it in your app configuration. This allows your app to take action when something happens in Slack, like a user reacting to a message or joining a channel. The `event()` method requires an `eventType` of type string.
diff --git a/docs/_basic/listening_messages.md b/docs/_basic/listening_messages.md index fe9dcd23d..dddb13af8 100644 --- a/docs/_basic/listening_messages.md +++ b/docs/_basic/listening_messages.md @@ -5,9 +5,9 @@ order: 1 ---
-To listen to messages that [your app has access to receive](https://api.slack.com/messaging/retrieving#permissions), you can use the `message()` method. This method filters out any events that aren’t of type `message`. +To listen to messages that [your app has access to receive](https://api.slack.com/messaging/retrieving#permissions), you can use the `message()` method which filters out events that aren’t of type `message`. -It accepts an optional `pattern` parameter of type `string` or `RegExp` object that will filter out any messages that don’t match. +`message()` accepts an optional `pattern` parameter of type `string` or `RegExp` object which filters out any messages that don’t match the pattern.
```javascript diff --git a/docs/_basic/listening_responding_commands.md b/docs/_basic/listening_responding_commands.md index eee124e80..994c15835 100644 --- a/docs/_basic/listening_responding_commands.md +++ b/docs/_basic/listening_responding_commands.md @@ -5,7 +5,7 @@ order: 8 ---
-Your app can use the `command()` method to listen to incoming slash command payloads. The method requires a `commandName` of type string. +Your app can use the `command()` method to listen to incoming slash command events. The method requires a `commandName` of type string. Commands must be acknowledged with `ack()` to inform Slack your app has received the event. diff --git a/docs/_basic/responding_actions.md b/docs/_basic/responding_actions.md index 851744d21..356182212 100644 --- a/docs/_basic/responding_actions.md +++ b/docs/_basic/responding_actions.md @@ -5,7 +5,7 @@ order: 6 ---
-There are two main ways to respond to actions. The first way (and the most common way) is using the `say` function. The `say` function sends a message back to the conversation where the incoming event took place. +There are two main ways to respond to actions. The first (and most common) way is to use the `say` function. The `say` function sends a message back to the conversation where the incoming event took place. The second way to respond to actions is using `respond()`, which is a simple utility to use the `response_url` associated with an action.
@@ -25,7 +25,7 @@ app.action('approve_button', ({ ack, say }) => {
-Since `respond()` is a utility for calling the `response_url`, it behaves in the same way. You can pass a JSON object with a new message payload that will be published back to the source of the original interaction with optional properties like `response_type` (`in_channel` or `ephemeral`), `replace_original`, and `delete_original`. +Since `respond()` is a utility for calling the `response_url`, it behaves in the same way. You can pass a JSON object with a new message payload that will be published back to the source of the original interaction with optional properties like `response_type` (which has a value of `in_channel` or `ephemeral`), `replace_original`, and `delete_original`.
```javascript diff --git a/docs/_basic/sending_messages.md b/docs/_basic/sending_messages.md index b4bc78255..9ac2c9f7e 100644 --- a/docs/_basic/sending_messages.md +++ b/docs/_basic/sending_messages.md @@ -5,7 +5,7 @@ order: 2 ---
-Within your listener function, `say()` is available whenever there is an associated conversation (for example, the conversation where the event or action which triggered the listener occurred). `say()` accepts a string to post simple text-based messages and JSON payloads to send more complex messages. The message payload you pass in will be sent to the associated conversation. +Within your listener function, `say()` is available whenever there is an associated conversation (for example, a conversation where the event or action which triggered the listener occurred). `say()` accepts a string to post simple messages and JSON payloads to send more complex messages. The message payload you pass in will be sent to the associated conversation. In the case that you'd like to send a message outside of a listener or you want to do something more advanced (like handle specific errors), you can call `chat.postMessage` [using the client attached to your Bolt instance](#web-api).
diff --git a/docs/_tutorials/getting_started.md b/docs/_tutorials/getting_started.md index 4478ededf..a8fd707cb 100644 --- a/docs/_tutorials/getting_started.md +++ b/docs/_tutorials/getting_started.md @@ -41,9 +41,9 @@ Look around, add an app icon and description, and then let's start configuring y --- ### 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 your app can use to call various API methods. +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 two token types available to a Slack app: user (`xoxp`) tokens and bot (`xoxb`) tokens. User tokens allow you to call API methods on behalf of users who are a part of your workspace. Your app receives an `xoxp` token associated with each user who installs the app. Bot tokens require adding a bot user to your app, which are granted once in each workspace that a user installs the app into, and will be the identical no matter which user performed the installation. +There are two token types available to a Slack app: user (`xoxp`) and bot (`xoxb`) tokens. User tokens 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 are granted once in every workspace where someone installs the app, though they require adding a bot user to your app. The bot token your app uses will be the same no matter which user performed the installation. For brevity, we're going to use bot tokens for this guide. @@ -51,7 +51,7 @@ To add a bot user, click **Bot Users** on the left sidebar and then **Add A Bot Now that you have a bot user with permission to send messages to Slack, let's install the app to your workspace. -Click **Install App** on the left sidebar and click the big **Install App to Workspace** button at the top of the page. You'll see a screen that details what permissions the app is requesting, which correlate to the scopes applied to your app's OAuth token(s). +Click **Install App** on the left sidebar and click the **Install App to Workspace** button at the top of the page. You'll see a screen that details what permissions the app is requesting, which correlate to the scopes applied to your app's OAuth token(s). Once you authorize the installation, you'll land on the **OAuth & Permissions** page. @@ -113,7 +113,7 @@ const app = new App({ })(); ``` -Your token and signing secret are enough to create your first Bolt app. Save your `app.js` file then, back at the command line, run the following: +Your token and signing secret are enough to create your first Bolt app. Save your `app.js` file then on the command line run the following: ```script node app.js @@ -124,11 +124,11 @@ Your app should let you know that it's up and running. --- ### Setting up events -Your app behaves similarly to people on your team — it can respond to that happen, post messages, and more. To listen for events happening in a Slack workspace (like when a message is posted or when a emoji 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 more. 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). To enable events for your app, start by going 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**. -You'll see a text input labeled **Request URL**. The Request URL is a public URL where Slack will send HTTP POST requests about the events you specify. +You'll see a text input labeled **Request URL**. The Request URL is a public URL where Slack will send HTTP POST requests corresponding to events you specify. > ⚙️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) @@ -139,9 +139,9 @@ When an event occurs, Slack will send your app some information about the event,

Using a local Request URL for development

-If you’re just getting started with your app's development, you probably don’t have a publicly accessible URL yet. Eventually, you’ll want to set that up, but for now a development proxy like [ngrok](https://ngrok.com/) will create a public URL and tunnel requests to your own development environment. We've written a separate tutorial about [using ngrok with Slack for local development](https://api.slack.com/tutorials/tunneling-with-ngrok) that should help you get everything set up. +If you’re just getting started with your app's development, you probably don’t have a publicly accessible URL yet. Eventually, you’ll want to set one up, but for now a development proxy like [ngrok](https://ngrok.com/) will create a public URL and tunnel requests to your own development environment. We've written a separate tutorial about [using ngrok with Slack for local development](https://api.slack.com/tutorials/tunneling-with-ngrok) that should help you get everything set up. -Once you’ve installed a development proxy, run it to begin forwarding requests to a specific port (we’re using port 3000 for this example, but if you customized the port used to initialize your app use that port instead): +Once you’ve installed a development proxy, run it to begin forwarding requests to a specific port (we’re using port `3000` for this example, but if you customized the port used to initialize your app use that port instead): ```shell ngrok http 3000 @@ -199,7 +199,7 @@ To use features like buttons, select menus, datepickers, dialogs, and message ac Back on your app configuration page, click on **Interactive Components** on the left side. You'll see that there's another **Request URL** box. -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 (in the example, it was `https://8e8ec2d7.ngrok.io/slack/events`). Press the **Save Changes** button in the lower right hand corner, and that's it. Your app is all set up for interactivity! +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 (in the example, it was `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 for interactivity! ![Configuring a Request URL](../assets/request-url-config.png "Configuring a Request URL") @@ -223,19 +223,19 @@ app.message('hello', ({ message, say }) => { say({ blocks: [ { - "type": "section", + "type": "section", + "text": { + "type": "mrkdwn", + "text": `Hey there <@${message.user}>!` + }, + "accessory": { + "type": "button", "text": { - "type": "mrkdwn", - "text": `Hey there <@${message.user}>!` + "type": "plain_text", + "text": "Click Me" }, - "accessory": { - "type": "button", - "text": { - "type": "plain_text", - "text": "Click Me" - }, - "action_id": "button_click" - } + "action_id": "button_click" + } } ] }); @@ -251,7 +251,7 @@ app.message('hello', ({ message, say }) => { 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. -You'll notice in the same `accessory` object as the button, there is an `action_id`. This will act as a unique identifier for the button so your app can specify what action it is responding to. +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. > 💡 The [Block Kit Builder](https://api.slack.com/tools/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. @@ -272,7 +272,7 @@ app.message('hello', ({ message, say }) => { // say() sends a message to the channel where the event was triggered say({ blocks: [ - { + { "type": "section", "text": { "type": "mrkdwn", @@ -285,8 +285,8 @@ app.message('hello', ({ message, say }) => { "text": "Click Me" }, "action_id": "button_click" - } - } + } + } ] }); }); From c0fd7d6bc274e6c1d76fd1dd4615755771ea93c7 Mon Sep 17 00:00:00 2001 From: Shane DeWael Date: Thu, 16 May 2019 09:32:42 -0700 Subject: [PATCH 2/2] listener consistency --- docs/_advanced/error_handling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_advanced/error_handling.md b/docs/_advanced/error_handling.md index 1fca0097d..1f525c2fd 100644 --- a/docs/_advanced/error_handling.md +++ b/docs/_advanced/error_handling.md @@ -5,7 +5,7 @@ order: 1 ---
-If an error occurs in a listener, it’s recommended you handle it directly. However, there are cases where errors may be triggered after your listener middleware has already returned (such as in `say()`, `respond()`, or if you don't call `ack()` when it's required). By default, these errors will be logged to the console. To handle them yourself, you can attach a global error handler to your app with the `error(fn)` method. +If an error occurs in a listener, it’s recommended you handle it directly. However, there are cases where errors may be triggered after your listener has already returned (such as in `say()`, `respond()`, or if you don't call `ack()` when it's required). By default, these errors will be logged to the console. To handle them yourself, you can attach a global error handler to your app with the `error(fn)` method. If you want more control over errors, it’s advised to use the [`chat.postMessage`](https://api.slack.com/methods/chat.postMessage) method attached to your app under the `client` key (instead of `say()` or `respond()`). This returns a `Promise` that can be caught to handle the error.