[Slack API] Bolt for JavaScript を使用した Getting Started を試してみた

2023.05.05

こんにちは、CX事業本部 Delivery部の若槻です。

前回の記事までは Slack API を利用したアプリ(Slack App)について調べていましたが、この Slack App でユーザーの操作に対するアクションを実施するなどのインタラクティブな動作を実装するためには Bolt を使うと便利なようです。

Bolt は Slack が公式提供しているライブラリで、現在は以下の3言語に対応した SDK が提供されています。

  • Bolt for JavaScript
  • Bolt for Python
  • Bolt for Java

今回は、Bolt for JavaScript を使った Slack App の実装方法を確認してみました。

やってみた

Slack 公式が公開している下記の Getting Started が良さそうだったので、今回はこちらを参考に、若干のアレンジをしつつ試してみます。

Slack App の作成

前述の Getting Started では、Slack App(アプリ)の作成をすべて GUI から行っていますが、同じ方法をトレースするだけだと芸が無いので、今回はマニフェストを使用してアプリを作成してみます。

マニフェストは AWS だと CloudFormation Template に相当するもので、YAML または JSON で記述することで、事前定義された構成で Slack App の設定を簡単に行うことができます。(現在はBETA提供となります)

今回使用するマニフェストは下記になります。

app_manifest.yml

display_information:
  name: BoltTestApp
features:
  bot_user:
    display_name: BoltTestApp
    always_online: false
oauth_config:
  scopes:
    bot:
      - chat:write
      - channels:history
      - groups:history
      - im:history
settings:
  event_subscriptions:
    bot_events:
      - message.channels
      - message.groups
      - message.im
  interactivity:
    is_enabled: true
  org_deploy_enabled: false
  socket_mode_enabled: true
  token_rotation_enabled: false

oauth_config の Bot Token Scopes で指定している権限は4つありますが、chat:write を指定した場合は他の3つも必須となります。

上記マニフェストからアプリを作成してみます。https://api.slack.com/apps にアクセスし、Create New App をクリックします。

From an app manifest を選択します。

アプリを実装するワークスペースを選択して、Next をクリックします。

先ほど作成したマニフェストを貼り付けて、Next をクリックします。

Create をクリックします。

マニフェストからアプリを作成できました。

アプリのインストール

次に、アプリを Slack ワークスペースにインストールします。

Basic Information > Building Apps for Slack > Install your appInstall to Workspace をクリックします。

ワークスペースへのアクセス権限を求められるので許可します。

インストールできました。

プロジェクトの作成

任意の開発環境で下記コマンドを実行し、npm プロジェクトを初期化します。

mkdir first-bolt-app
cd first-bolt-app
npm init

npm init コマンドを実行すると一連の質問が表示されますが、今回はすべてデフォルトのままで問題ありません。これにより package.json が作成されます。

Bolt for JavaScript のインストール

そして次のコマンドを実行して Bolt for JavaScript をインストールします。

npm install @slack/bolt

トークンの環境変数の設定

Bolt for JavaScript からアプリへの接続に使用するトークンを取得して環境変数に設定します。

Basic Information > App Credentials から Signing Secret をコピーして、環境変数に設定します。

export SLACK_SIGNING_SECRET=<your-signing-secret>

OAuth & Permissions > OAuth Tokens for Your Workspace から Bot User OAuth Token をコピーし、環境変数に設定します。

export SLACK_BOT_TOKEN=xoxb-<your-bot-token>

動作確認

プロジェクトのトップに app.js ファイルを作成して、下記コードを記述します。

app.js

const { App } = require('@slack/bolt');

// Initializes your app with your bot token and signing secret
const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  signingSecret: process.env.SLACK_SIGNING_SECRET
});

(async () => {
  // Start your app
  await app.start(process.env.PORT || 3000);

  console.log(' Bolt app is running!');
})();

ファイルを保存して次のコマンドを実行します。

node app.js

app.js が動作することが確認できます。

イベントのリッスン設定

Slack ワークスペース上でのイベント(ユーザーによるメッセージの投稿など)をアプリがサブスクライブ(リッスン)できるように、ソケットモードを使用します。

サブスクライブするイベントは先程のマニフェストの event_subscriptions.bot_events 、ソケットモードの有効化は socket_mode_enabledtrue に設定することにより定義済みです。

app_manifest.yml

settings:
  event_subscriptions:
    bot_events:
      - message.channels
      - message.groups
      - message.im
  interactivity:
    is_enabled: true
  org_deploy_enabled: false
  socket_mode_enabled: true
  token_rotation_enabled: false

ここでは Bolt からイベントをリッスンするためのトークンを生成し、環境変数に設定します。

Basic Information > App-Level TokensGenerate Token and Scopes をクリックします。

スコープとして connections:write を追加し、Generate をクリックします。

トークンが生成されるのでコピーし、環境変数に設定します。

export SLACK_APP_TOKEN=xapp-<your-app-token>

メッセージイベントをリッスンして応答する

Slack デスクトップアプリで任意のチャンネルにアプリをメンバーとして追加します。

チャンネルにアプリが追加されました。

app.js を次の通り更新して、node app.js コマンドを実行して app.js を再起動します。

app.js

const { App } = require('@slack/bolt');

const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  signingSecret: process.env.SLACK_SIGNING_SECRET,
  socketMode: true,
  appToken: process.env.SLACK_APP_TOKEN,
  // Socket Mode doesn't listen on a port, but in case you want your app to respond to OAuth,
  // you still need to listen on some port!
  port: process.env.PORT || 3000
});

// Listens to incoming messages that contain "hello"
app.message('hello', async ({ message, say }) => {
  // say() sends a message to the channel where the event was triggered
  await say(`Hey there <@${message.user}>!`);
});

(async () => {
  // Start your app
  await app.start();

  console.log(' Bolt app is running!');
})();

上記は、app.messagehello というメッセージをリッスンし、say() でメッセージを送信するという処理を実装しています。

デスクトップアプリで hello を含むメッセージを投稿すると、アプリからの応答が返ってきました。

対話型コンポーネントを送信する

イベントへの応答として対話型コンポーネントを送信することもできます。

以前の下記ブログで紹介した通り、blocks フィールドに Block Kit の JSON オブジェクトを指定することで、ボタンや選択メニュー、モーダルなどの、ユーザーに対してインタラクティブな操作を可能とする対話型コンポーネントを送信できます。

app.js を次の通り更新して、node app.js コマンドを実行して app.js を再起動します。

app.js

const { App } = require('@slack/bolt');

const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  signingSecret: process.env.SLACK_SIGNING_SECRET,
  socketMode: true,
  appToken: process.env.SLACK_APP_TOKEN,
  // Socket Mode doesn't listen on a port, but in case you want your app to respond to OAuth,
  // you still need to listen on some port!
  port: process.env.PORT || 3000
});

// Listens to incoming messages that contain "hello"
app.message('hello', async ({ message, say }) => {
  // say() sends a message to the channel where the event was triggered
  await say({
    blocks: [
      {
        "type": "section",
        "text": {
          "type": "mrkdwn",
          "text": `Hey there <@${message.user}>!`
        },
        "accessory": {
          "type": "button",
          "text": {
            "type": "plain_text",
            "text": "Click Me"
          },
          "action_id": "button_click"
        }
      }
    ],
    text: `Hey there <@${message.user}>!`
  });
});

app.action('button_click', async ({ body, ack, say }) => {
  // Acknowledge the action
  await ack();
  await say(`<@${body.user.id}> clicked the button`);
});

(async () => {
  // Start your app
  await app.start();

  console.log(' Bolt app is running!');
})();

上記は app.message('hello',...)hello というメッセージをリッスンし、say() で Block Kit を利用したメッセージを送信しています。またそのメッセージに含まれるボタンをクリックしたときに app.action('button_click',...)button_click という ID をリッスンし、say() でメッセージを送信しています。

デスクトップアプリで hello を含むメッセージを投稿すると、アプリからボタン付きのメッセージが返ってきました。またボタンをクリックすると、アプリから2つ目のメッセージが返ってきました。

おわりに

Slack App の Bolt for JavaScript を使用した Getting Started を試してみました。

Slack API を利用したインタラクティブなアプリを開発する上での基本を抑えることができる良いチュートリアルだと思うので、Slack API 開発を始める際にはぜひ試したい Getting Started でした。

以上