Bolt 入門ガイド

    このガイドでは、Bolt for Python を使った Slack アプリの設定と起動する方法について説明します。ここで説明する手順は、新しい Slack アプリを作成し、ローカルの開発環境をセットアップし、Slack ワークスペースからのメッセージをリッスンして応答するアプリを開発するという流れになります。

    この手順を全て終わらせたら、あなたはきっと ⚡️Slack アプリのはじめ方のサンプルアプリを動作させたり、それに変更を加えたり、自分のアプリを作ったりすることができるようになるでしょう。


    アプリを作成する

    最初にやるべきこと : Bolt での開発を始める前に、Slack アプリを作成します。

    💡 いつもの仕事のさまたげにならないように、別の開発用のワークスペースを使用することをおすすめします。新しいワークスペースは無料で作成できます

    アプリ名を入力し(後で変更可能)、インストール先のワークスペースを選択したら、「Create App」ボタンをクリックすると、アプリの Basic Information ページが表示されます。

    このページでは、アプリの概要を確認できます。また、「App Credentials」ヘッダーの下では「Signing Secret」などの重要な認証情報も確認できます。これらの認証情報は後で必要になります。

    Basic Information ページ

    ひと通り確認し、アプリのアイコンと説明を追加したら、アプリの構成 🔩 を始めましょう。


    トークンとアプリのインストール

    Slack アプリでは、Slack API へのアクセスの管理に OAuth を使用します。アプリがインストールされると、トークンが発行されます。アプリはそのトークンを使って API メソッドを呼び出すことができます。

    Slack アプリで使用できるトークンには、ユーザートークン(xoxp)とボットトークン(xoxb)の 2 種類があります。ユーザートークンを使用すると、ユーザーがアプリをインストールまたは認証した後、アプリがそのユーザーを代理して API メソッドを呼び出すことができます。1 つのワークスペースに複数のユーザートークンが存在する可能性があります。ボットトークンはボットユーザーに関連づけられ、1 つのワークスペースでは最初に誰かがそのアプリをインストールした際に一度だけ発行されます。どのユーザーがインストールを実行しても、アプリが使用するボットトークンは同じになります。_ほとんど_のアプリで使用されるのは、ボットトークンです。

    説明を簡潔にするために、このガイドではボットトークンを使用します。

    左サイドバーの「OAuth & Permissions」をクリックし、「Bot Token Scopes」セクションまで下にスクロールします。「Add an OAuth Scope」をクリックします。

    ここでは chat:write というスコープのみを追加します。このスコープは、アプリが参加しているチャンネルにメッセージを投稿することを許可します。

    OAuth & Permissions ページの一番上までスクロールし、「Install App to Workspace」をクリックします。Slack の OAuth 確認画面 が表示されます。この画面で開発用ワークスペースへのアプリのインストールを承認します。

    インストールを承認すると OAuth & Permissions ページが表示され、Bot User OAuth Access Token を確認できるでしょう。

    OAuth トークン

    💡 トークンはパスワードと同様に取り扱い、安全な方法で保管してください。アプリはこのトークンを使って Slack ワークスペースで投稿をしたり、情報の取得をしたりします。


    ローカルでプロジェクトをセットアップする

    初期設定が終わったら、新しい Bolt プロジェクトのセットアップを行いましょう。このプロジェクトが、あなたのアプリのロジックを処理するコードを配置する場所となります。

    プロジェクトをまだ作成していない場合は、新しく作成しましょう。空のディレクトリを作成します。

    1
    2
    
    mkdir first-bolt-app
    cd first-bolt-app
    

    次に、プロジェクトの依存関係を管理する方法として、Python 仮想環境を使ったおすすめの方法を紹介します。これはシステム Python に存在するパッケージとのコンフリクトを防ぐために推奨されている優れた方法です。Python 3.6 以降の仮想環境を作成し、アクティブにしてみましょう。

    1
    2
    
    python3 -m venv .venv
    source .venv/bin/activate
    

    python3 へのパスがプロジェクトの中を指していることを確かめることで、仮想環境がアクティブになっていることを確認できます(Windows でもこれに似たコマンドが利用できます)。

    1
    2
    
    which python3
    # 出力結果 : /path/to/first-bolt-app/.venv/bin/python3
    

    Bolt for Python のパッケージを新しいプロジェクトにインストールする前に、アプリの設定時に作成されたボットトークンと署名シークレットを保存しましょう。これらは環境変数に保存する必要があります。バージョンコントロールには保存しないようにしてください。

    1. Basic Information ページの署名シークレット(Signing Secret)をコピーして、新しい環境変数に保存します。以下のコマンド例は Linux と macOS で利用できます。Windows でもこれに似たコマンドが利用できます
      1
      
      export SLACK_SIGNING_SECRET=<署名シークレット>
      
    2. OAuth & Permissions ページのボットトークン(xoxb)をコピーして、別の環境変数に保存します。
      1
      
      export SLACK_BOT_TOKEN=xoxb-<ボットトークン>
      

    完了したら、アプリを作ってみましょう。以下のコマンドを使って、仮想環境に Python の slack_bolt パッケージをインストールします。

    1
    
    pip install slack_bolt
    

    このディレクトリに「app.py」という名前の新しいファイルを作成し、以下のコードを追加します。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    import os
    from slack_bolt import App
    
    # ボットトークンと署名シークレットを使ってアプリを初期化します
    app = App(
        token=os.environ.get("SLACK_BOT_TOKEN"),
        signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
    )
    
    # アプリを起動します
    if __name__ == "__main__":
        app.start(port=int(os.environ.get("PORT", 3000)))
    

    このようにトークンと署名シークレットだけあれば、最初の Bolt アプリが作成できます。「app.py」ファイルを保存して、コマンドラインで以下を実行します。

    python3 app.py
    

    アプリが起動し、実行中であることが表示されます。


    イベントを設定する

    アプリはワークスペース内の他のメンバーと同じように振る舞い、メッセージを投稿したり絵文字リアクションを追加したりできます。Slack ワークスペースで発生するイベント(メッセージが投稿されたときや、メッセージに対するリアクションがつけられたときなど)をリッスンするには、Events API を使って特定の種類のイベントをサブスクライブします

    アプリをイベントに対応させるため、まずこのアプリの設定ページに戻って設定を行います。アプリ管理ページでアプリをクリックします。次に、左サイドバーの「Event Subscriptions」をクリックします。「Enable Events」というラベルのスイッチをオンに切り替えます。

    Request URL」というラベルのテキスト入力フィールドが表示されます。Request URL は、指定したイベントに対応する Slack からの HTTP POST リクエストの送信先となるパブリック URL です。

    ⚙️ API サイトに、Slack の開発チームがアプリのホストによく使用する一般的なホスティングプロバイダをいくつか記載しておきました。

    イベントが発生すると、そのイベントをトリガーしたユーザーやイベントが発生したチャンネルなど、イベントに関する情報が Slack からアプリに送信されます。アプリではこれらの情報を処理して、適切な応答を返します。

    開発用にローカルの Request URL を使用する

    アプリの開発を始めたばかりの場合、パブリックにアクセスできる URL をまだ持っていないかもしれませんね。最終的には適切なものをセットアップするものとして、ここでは ngrok のような開発用プロキシを利用することにします。開発用プロキシを利用すると、リクエストを開発環境にトンネルするパブリック URL を作成できます。Slack のローカル開発で ngrok を使用する方法については、別のチュートリアルを用意していますので参考にしてください。開発用プロキシをインストールして実行を開始すると、リクエストが特定のポートに転送されるようになります(この例ではポート 3000 を使用していますが、アプリを初期化する際に使用ポートをカスタマイズしている場合は、そのポートを使用してください)。shell ngrok http 3000 ngrok の実行 利用可能な URL が生成され、出力結果に表示されます(「https://」で始まる URL をおすすめします)。この URL がリクエスト URL のベースになります。この例では「https://8e8ec2d7.ngrok.io」です。—

    これで、ローカルマシンにトンネルしてアプリで利用できるパブリック URL が用意できました。アプリの設定で指定する Request URL は、パブリック URL に、アプリがリッスンするパスを組み合わせたものになります。デフォルトでは、Bolt アプリは「/slack/events」をリッスンします。この場合、Request URL 全体は「https://8e8ec2d7.ngrok.io/slack/events」となります。

    ⚙️ Bolt では、/slack/events というエンドポイントで、すべての受信リクエストをリッスンします。これらのリクエストにはショートカット、イベント、インタラクションペイロードが含まれます。アプリの設定でエンドポイントを指定するときは、すべての Request URL の末尾に「/slack/events」を追加してください。

    Request URL」ボックスの「Enable Events」スイッチの下に URL を貼りつけます。Bolt アプリが起動した状態のままなら、URL の検証が成功するはずです。

    Request URL の検証が完了したら、「Subscribe to Bot Events」まで下にスクロールします。メッセージに関連するイベントには、次の 4 つがあります。

    • message.channels アプリが参加しているパブリックチャンネルのメッセージをリッスン
    • message.groups アプリが参加しているプライベートチャンネルのメッセージをリッスン
    • message.im あなたのアプリとユーザーのダイレクトメッセージをリッスン
    • message.mpim あなたのアプリが追加されているグループ DM をリッスン

    ボットが参加するすべての場所のメッセージをリッスンさせるには、これら 4 つのメッセージイベントをすべて選択します。ボットにリッスンさせるメッセージイベントの種類を選択したら、「Save Changes」ボタンをクリックします。


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

    アプリにロジックを組み込む準備が整いました。まずは message() メソッドを使用して、メッセージのリスナーをアタッチしましょう。

    次の例では、アプリが参加するチャンネルとダイレクトメッセージに投稿されるすべてのメッセージをリッスンし、「hello」というメッセージに応答を返します。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    import os
    from slack_bolt import App
    
    # ボットトークンと署名シークレットを使ってアプリを初期化します
    app = App(
        token=os.environ.get("SLACK_BOT_TOKEN"),
        signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
    )
    
    # 'hello' を含むメッセージをリッスンします
    @app.message("hello")
    def message_hello(message, say):
        # イベントがトリガーされたチャンネルへ say() でメッセージを送信します
        say(f"Hey there <@{message['user']}>!")
    
    # アプリを起動します
    if __name__ == "__main__":
        app.start(port=int(os.environ.get("PORT", 3000)))
    

    アプリを再起動し、ボットユーザーが参加しているチャンネルまたはダイレクトメッセージに「hello」というメッセージを投稿すれば、アプリが応答するでしょう。

    これはごく基本的なコード例ですが、最終的にやりたいことを実現するためにアプリをカスタマイズするための起点として利用できます。プレーンテキストを送信する代わりにボタンを表示するという、もう少しインタラクティブな動作を試してみましょう。


    アクションを送信して応答する

    インタラクティブ機能を有効にすると、ボタン、選択メニュー、日付ピッカー、モーダル、ショートカットなどの機能が利用できるようになります。イベントと同様に、Slack からのアクション(ユーザーがボタンをクリックしたなど)の送信先となる URL を設定する必要があります。

    アプリ設定ページに戻り、左サイドメニューの「Interactivity & Shortcuts」をクリックします。別の Request URL ボックスを見つけます。

    デフォルトでは、Bolt はイベントに使用しているのと同じエンドポイントをインタラクティブコンポーネントにも使用するように設定されているため、上記と同じリクエスト URL(この例では「https://8e8ec2d7.ngrok.io/slack/events」)を使用します。このままの状態で、右下隅にある「Save Changes」ボタンを押してください。これでインタラクティブ機能がアプリで利用できるようになりました。

    Request URL の設定

    それでは、アプリのコードに戻り、インタラクティブ機能を追加しましょう。インタラクティブ機能は 2 つのステップで構成されます。まず、ボタンを含んだメッセージをアプリから送信します。次に、ユーザーから返されるボタンクリックのアクションをリッスンし、それに応答します。

    以下のコードの後の部分を編集し、文字列だけのメッセージの代わりに、ボタンを含んだメッセージを送信するようにしてみます。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    
    import os
    from slack_bolt import App
    
    # ボットトークンと署名シークレットを使ってアプリを初期化します
    app = App(
        token=os.environ.get("SLACK_BOT_TOKEN"),
        signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
    )
    
    # 'hello' を含むメッセージをリッスンします
    @app.message("hello")
    def message_hello(message, say):
        # イベントがトリガーされたチャンネルへ say() でメッセージを送信します
        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']}>!"
        )
    
    # アプリを起動します
    if __name__ == "__main__":
        app.start(port=int(os.environ.get("PORT", 3000)))
    

    say() の中の値を blocks という配列のオブジェクトに変えました。ブロックは Slack メッセージを構成するコンポーネントであり、テキストや画像、日付ピッカーなど、さまざまなタイプのブロックがあります。この例では accessorybutton を持たせた「section」のブロックを、アプリからの応答に含めています。blocks を使用する場合、text は通知やアクセシビリティのためのフォールバックとなります。

    ボタンを含む accessory オブジェクトでは、action_id を指定していることがわかります。これは、ボタンを一意に示す識別子として機能します。これを使って、アプリをどのアクションに応答させるかを指定できます。

    💡 Block Kit Builder を使用すると、インタラクティブなメッセージのプロトタイプを簡単に作成できます。自分自身やチームメンバーがメッセージのモックアップを作成し、生成される JSON をアプリに直接貼りつけることができます。

    アプリを再起動し、アプリが参加しているチャンネルで「hello」と入力すると、ボタン付きのメッセージが表示されるようになりました。ただし、ボタンをクリックしても、まだ何も起こりません。

    ハンドラーを追加して、ボタンがクリックされたときにフォローアップメッセージを送信するようにしてみましょう。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    
    import os
    from slack_bolt import App
    
    # ボットトークンと署名シークレットを使ってアプリを初期化します
    app = App(
        token=os.environ.get("SLACK_BOT_TOKEN"),
        signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
    )
    
    # 'hello' を含むメッセージをリッスンします
    @app.message("hello")
    def message_hello(message, say):
        # イベントがトリガーされたチャンネルへ say() でメッセージを送信します
        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):
        # アクションを確認したことを即時で応答します
        ack()
        # チャンネルにメッセージを投稿します
        say(f"<@{body['user']['id']}> clicked the button")
    
    # アプリを起動します
    if __name__ == "__main__":
        app.start(port=int(os.environ.get("PORT", 3000)))
    

    app.action() を使って、先ほど命名した button_click という action_id をリッスンしています。アプリを再起動し、ボタンをクリックすると、アプリからの「clicked the button」というメッセージが新たに表示されるでしょう。


    次のステップ

    はじめての Bolt for Python アプリを構築することができました。🎉

    ここまでで基本的なアプリをセットアップして実行することはできたので、次は自分だけの Bolt アプリを作る方法を調べてみましょう。参考になりそうな記事をいくつかご紹介します。

    • 基本的な概念について読む。Bolt アプリがアクセスできるさまざまメソッドや機能について知ることができます。
    • events() メソッドでボットがリッスンできるイベントをほかにも試してみる。すべてのイベントの一覧は API サイトで確認できます。
    • Bolt では、アプリにアタッチされたクライアントから Web API メソッドを呼び出すことができます。API サイトに 220 以上のメソッドを一覧しています。
    • API サイトでほかのタイプのトークンを確認する。アプリで実行したいアクションによって、異なるトークンが必要になる場合があります。