Skip to content

Commit

Permalink
Merge branch '@slack/bolt@next' into shortcutV2
Browse files Browse the repository at this point in the history
  • Loading branch information
stevengill authored Mar 17, 2020
2 parents 50d2008 + 9c8d01d commit 63bf681
Show file tree
Hide file tree
Showing 41 changed files with 479 additions and 487 deletions.
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,17 @@ called with arguments that make it easy to build a rich app.
* `say` - A function to respond to an incoming event. This argument is only available when the listener is triggered
for event that contains a `channel_id` (including `message` events). Call this function to send a message back to the
same channel as the incoming event. It accepts both simple strings (for plain messages) and objects (for complex
messages, including blocks or attachments).
messages, including blocks or attachments). `say` returns a promise that will resolve with a
[response](https://api.slack.com/methods/chat.postMessage) from `chat.postMessage`.

* `ack` - A function to acknowledge that an incoming event was received by the app. Incoming events from actions,
commands, and options requests **must** be acknowledged by calling this function. See [acknowledging
events](#acknowledging-events) for details.
events](#acknowledging-events) for details. `ack` returns a promise that resolves when complete.

* `respond` - A function to respond to an incoming event. This argument is only available when the listener is
triggered for an event that contains a `response_url` (actions and commands). Call this function to send a message
back to the same channel as the incoming event, but using the semantics of the `response_url`.
back to the same channel as the incoming event, but using the semantics of the `response_url`. `respond`
returns a promise that resolves with the results of responding using the `response_url`.

* `context` - The event context. This object contains data about the message and the app, such as the `botId`.
See [advanced usage](#advanced-usage) for more details.
Expand All @@ -99,9 +101,9 @@ Here is an example where the app sends a simple response, so there's no need for

```js
// Reverse all messages the app can hear
app.message(({ message, say }) => {
app.message(async ({ message, say }) => {
const reversedText = message.text.split('').reverse().join('');
say(reversedText);
await say(reversedText);
});
```

Expand Down Expand Up @@ -162,15 +164,15 @@ The following is an example of acknowledging a dialog submission:
app.action({ callbackId: 'my_dialog_callback' }, async ({ action, ack }) => {
// Expect the ticketId value to begin with "CODE"
if (action.submission.ticketId.indexOf('CODE') !== 0) {
ack({
await ack({
errors: [{
name: 'ticketId',
error: 'This value must begin with CODE',
}],
});
return;
}
ack();
await ack();

// Do some work
});
Expand All @@ -193,9 +195,7 @@ app.error((error) => {
If you do not attach an error handler, the app will log these errors to the console by default.

The `app.error()` method should be used as a last resort to catch errors. It is always better to deal with errors in the
listeners where they occur because you can use all the context available in that listener. If the app expects that using
`say()` or `respond()` can fail, it's always possible to use `app.client.chat.postMessage()` instead, which returns a
`Promise` that can be caught to deal with the error.
listeners where they occur because you can use all the context available in that listener.

## Advanced usage

Expand Down Expand Up @@ -257,13 +257,13 @@ function authWithAcme({ payload, context, say, next }) {
// Pass control to the next middleware (if there are any) and the listener functions
next();
})
.catch((error) => {
.catch(async (error) => {
// Uh oh, this user hasn't registered with Acme. Send them a registration link, and don't let the
// middleware/listeners continue
if (error.message === 'Not Found') {
// In the real world, you would need to check if the say function was defined, falling back to the respond
// function if not, and then falling back to only logging the error as a last resort.
say(`I'm sorry <@${slackUserId}>, you aren't registered with Acme. Please use <https://acme.com/register> to use this app.`);
await say(`I'm sorry <@${slackUserId}>, you aren't registered with Acme. Please use <https://acme.com/register> to use this app.`);
return;
}

Expand Down
2 changes: 1 addition & 1 deletion docs/_advanced/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ async function addTimezoneContext({ payload, context, next }) {

app.command('request', addTimezoneContext, async ({ command, ack, context }) => {
// Acknowledge command request
ack();
await ack();
// Get local hour of request
const local_hour = (Date.UTC() + context.tz_offset).getHours();

Expand Down
4 changes: 2 additions & 2 deletions docs/_advanced/ja_context.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async function addTimezoneContext({ payload, context, next }) {

app.command('request', addTimezoneContext, async ({ command, ack, context }) => {
// コマンドリクエストの確認
ack();
await ack();
// リクエスト時のローカル時間を取得
const local_hour = (Date.UTC() + context.tz_offset).getHours();

Expand Down Expand Up @@ -65,4 +65,4 @@ app.command('request', addTimezoneContext, async ({ command, ack, context }) =>
}
}
});
```
```
6 changes: 3 additions & 3 deletions docs/_basic/acknowledging_requests.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ We recommend calling `ack()` right away before sending a new message or fetching
// Regex to determine if this is a valid email
let isEmail = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/
// This uses a constraint object to listen for dialog submissions with a callback_id of ticket_submit
app.action({ callback_id: 'ticket_submit' }, ({ action, ack }) => {
app.action({ callback_id: 'ticket_submit' }, async ({ action, ack }) => {
// it’s a valid email, accept the submission
if (isEmail.test(action.submission.email)) {
ack();
await ack();
} else {
// if it isn’t a valid email, acknowledge with an error
ack({
await ack({
errors: [{
"name": "email_address",
"error": "Sorry, this isn’t a valid email"
Expand Down
6 changes: 3 additions & 3 deletions docs/_basic/ja_acknowledging_requests.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ order: 7
// Regex でメールアドレスが有効かチェック
let isEmail = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/
// 制約付きのオブジェクト を使用して ticket_submit という callback_id を持つダイアログ送信をリスニング
app.action({ callback_id: 'ticket_submit' }, ({ action, ack }) => {
app.action({ callback_id: 'ticket_submit' }, async ({ action, ack }) => {
// メールアドレスが有効。ダイアログを受信
if (isEmail.test(action.submission.email)) {
ack();
await ack();
} else {
// メールアドレスが無効。エラーを確認
ack({
await ack({
errors: [{
"name": "email_address",
"error": "Sorry, this isn’t a valid email"
Expand Down
4 changes: 2 additions & 2 deletions docs/_basic/ja_listening_actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ order: 5
```javascript
// action_id が "approve_button" のインタラクティブコンポーネントがトリガーされる毎にミドルウェアが呼び出される
app.action('approve_button', async ({ ack, say }) => {
ack();
await ack();
// アクションを反映してメッセージをアップデート
});
```
Expand All @@ -35,7 +35,7 @@ app.action('approve_button', async ({ ack, say }) => {
// action_id が 'select_user' と一致し、block_id が 'assign_ticket' と一致する場合のみミドルウェアが呼び出される
app.action({ action_id: 'select_user', block_id: 'assign_ticket' },
async ({ action, ack, context }) => {
ack();
await ack();
try {
const result = await app.client.reactions.add({
token: context.botToken,
Expand Down
4 changes: 2 additions & 2 deletions docs/_basic/ja_listening_messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ order: 1
```javascript
// 特定の文字列、この場合 👋絵文字を含むメッセージと一致
app.message(':wave:', async ({ message, say }) => {
say(`Hello, <@${message.user}>`);
await say(`Hello, <@${message.user}>`);
});
```

Expand All @@ -34,7 +34,7 @@ app.message(/^(hi|hello|hey).*/, async ({ context, say }) => {
// context.matches の内容が特定の正規表現と一致
const greeting = context.matches[0];

say(`${greeting}, how are you?`);
await say(`${greeting}, how are you?`);
});
```

Expand Down
4 changes: 2 additions & 2 deletions docs/_basic/ja_listening_modals.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ order: 11
// モーダルビューでのデータ送信イベントを処理します
app.view('view_b', async ({ ack, body, view, context }) => {
// モーダルビューでのデータ送信イベントを確認
ack();
await ack();

// 入力値を使ってやりたいことをここで実装 - ここでは DB に保存して送信内容の確認を送っている

Expand All @@ -41,7 +41,7 @@ app.view('view_b', async ({ ack, body, view, context }) => {

// ユーザーにメッセージを送信
try {
app.client.chat.postMessage({
await app.client.chat.postMessage({
token: context.botToken,
channel: user,
text: msg
Expand Down
4 changes: 2 additions & 2 deletions docs/_basic/ja_listening_responding_commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ order: 8
// この echo コマンドは 単純にコマンドをエコー(こだま)
app.command('/echo', async ({ command, ack, say }) => {
// コマンドリクエストを確認
ack();
await ack();

say(`${command.text}`);
await say(`${command.text}`);
});
```
6 changes: 3 additions & 3 deletions docs/_basic/ja_listening_responding_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ app.options('external_action', async ({ options, ack }) => {
});
}

ack({
await ack({
"options": options
});
} else {
ack();
await ack();
}
});
```
```
6 changes: 3 additions & 3 deletions docs/_basic/ja_opening_modals.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ order: 9

```javascript
// コマンド起動をリッスン
app.command('/ticket', ({ ack, body, context }) => {
app.command('/ticket', async ({ ack, body, context }) => {
// コマンドのリクエストを確認
ack();
await ack();

try {
const result = app.client.views.open({
const result = await app.client.views.open({
token: context.botToken,
// 適切な trigger_id を受け取ってから 3 秒以内に渡す
trigger_id: body.trigger_id,
Expand Down
14 changes: 7 additions & 7 deletions docs/_basic/ja_responding_actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ order: 6

```javascript
// action_id が "approve_button" のインタラクティブコンポーネントがトリガーされる毎にミドルウェアが呼び出される
app.action('approve_button', ({ ack, say }) => {
app.action('approve_button', async ({ ack, say }) => {
// アクションリクエストの確認
ack();
say('Request approved 👍');
await ack();
await say('Request approved 👍');
});
```

Expand All @@ -31,10 +31,10 @@ app.action('approve_button', ({ ack, say }) => {

```javascript
// "user_select" の action_id がトリガーされたアクションをリスニング
app.action('user_choice', ({ action, ack, respond }) => {
ack();
respond(`You selected <@${action.selected_user}>`);
app.action('user_choice', async ({ action, ack, respond }) => {
await ack();
await respond(`You selected <@${action.selected_user}>`);
});
```

</details>
</details>
8 changes: 4 additions & 4 deletions docs/_basic/ja_sending_messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ order: 2

```javascript
// "knock knock" を含むメッセージをリスニングし、 "who's there?" というメッセージをイタリック体で送信
app.message('knock knock', ({ message, say }) => {
say(`_Who's there?_`);
app.message('knock knock', async ({ message, say }) => {
await say(`_Who's there?_`);
});
```

Expand All @@ -31,9 +31,9 @@ app.message('knock knock', ({ message, say }) => {

```javascript
// 誰かが 📅 絵文字でリアクションした時に、日付ピッカー block を送信
app.event('reaction_added', ({ event, say }) => {
app.event('reaction_added', async ({ event, say }) => {
if (event.reaction === 'calendar') {
say({
await say({
blocks: [{
"type": "section",
"text": {
Expand Down
6 changes: 3 additions & 3 deletions docs/_basic/ja_updating_pushing_modals.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ order: 10
```javascript
// action_id: button_abc のボタンを押すイベントをリッスン
// (そのボタンはモーダルビューの中にあるという想定)
app.action('button_abc', ({ ack, body, context }) => {
app.action('button_abc', async ({ ack, body, context }) => {
// ボタンを押したイベントを確認
ack();
await ack();

try {
const result = app.client.views.update({
const result = await app.client.views.update({
token: context.botToken,
// リクエストに含まれる view_id を渡す
view_id: body.view.id,
Expand Down
4 changes: 2 additions & 2 deletions docs/_basic/listening_actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ You’ll notice in all `action()` examples, `ack()` is used. It is required to c
```javascript
// Your middleware will be called every time an interactive component with the action_id "approve_button" is triggered
app.action('approve_button', async ({ ack, say }) => {
ack();
await ack();
// Update the message to reflect the action
});
```
Expand All @@ -35,7 +35,7 @@ You can use a constraints object to listen to `callback_id`s, `block_id`s, and `
// Your middleware will only be called when the action_id matches 'select_user' AND the block_id matches 'assign_ticket'
app.action({ action_id: 'select_user', block_id: 'assign_ticket' },
async ({ action, ack, context }) => {
ack();
await ack();
try {
const result = await app.client.reactions.add({
token: context.botToken,
Expand Down
4 changes: 2 additions & 2 deletions docs/_basic/listening_messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ To listen to messages that [your app has access to receive](https://api.slack.co
```javascript
// This will match any message that contains 👋
app.message(':wave:', async ({ message, say }) => {
say(`Hello, <@${message.user}>`);
await say(`Hello, <@${message.user}>`);
});
```

Expand All @@ -34,7 +34,7 @@ app.message(/^(hi|hello|hey).*/, async ({ context, say }) => {
// RegExp matches are inside of context.matches
const greeting = context.matches[0];

say(`${greeting}, how are you?`);
await say(`${greeting}, how are you?`);
});
```

Expand Down
4 changes: 2 additions & 2 deletions docs/_basic/listening_modals.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Read more about view submissions in our <a href="https://api.slack.com/surfaces/
// Handle a view_submission event
app.view('view_b', async ({ ack, body, view, context }) => {
// Acknowledge the view_submission event
ack();
await ack();

// Do whatever you want with the input data - here we're saving it to a DB then sending the user a verifcation of their submission

Expand All @@ -41,7 +41,7 @@ app.view('view_b', async ({ ack, body, view, context }) => {

// Message the user
try {
app.client.chat.postMessage({
await app.client.chat.postMessage({
token: context.botToken,
channel: user,
text: msg
Expand Down
4 changes: 2 additions & 2 deletions docs/_basic/listening_responding_commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ There are two ways to respond to slash commands. The first way is to use `say()`
// The echo command simply echoes on command
app.command('/echo', async ({ command, ack, say }) => {
// Acknowledge command request
ack();
await ack();

say(`${command.text}`);
await say(`${command.text}`);
});
```
6 changes: 3 additions & 3 deletions docs/_basic/listening_responding_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ app.options('external_action', async ({ options, ack }) => {
});
}

ack({
await ack({
"options": options
});
} else {
ack();
await ack();
}
});
```
```
6 changes: 3 additions & 3 deletions docs/_basic/opening_modals.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ Read more about modal composition in the <a href="https://api.slack.com/surfaces

```javascript
// Listen for a slash command invocation
app.command('/ticket', ({ ack, body, context }) => {
app.command('/ticket', async ({ ack, body, context }) => {
// Acknowledge the command request
ack();
await ack();

try {
const result = app.client.views.open({
const result = await app.client.views.open({
token: context.botToken,
// Pass a valid trigger_id within 3 seconds of receiving it
trigger_id: body.trigger_id,
Expand Down
Loading

0 comments on commit 63bf681

Please sign in to comment.