スラッシュコマンドでモーダルを開く Slack App を Glitch で実装するチュートリアルをやってみた

2023.05.12

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

Slack App では、モーダル を利用することにより、ユーザーにデータ入力や情報閲覧を集中して行わせるためのインターフェースを提供することができます。

このモーダルを利用した Slack App 開発の良い学習素材が無いか探したところ、次のチュートリアルが良さげでした。Slack クライアントからスラッシュコマンド /thankyou を実行し、開いたモーダルからユーザーが送信したデータをサーバー側で取得できる実装です。

そして上記チュートリアルでは Glitch という外部サービスを利用する手順になっていたので、Glitch についても簡単に紹介しつつ、やってみた内容をまとめてみます。

Glitch とは

Glitch とは、コードの共同編集からアプリのホスティングまでを簡単に行えるオンライン IDE サービスです。

Glitch はアプリケーションサーバーのホスティング環境を簡単に無料で構築できるため、Slack App 開発の公式チュートリアルでもよく登場しています。

ちなみに Glitch は、エッジクラウドサービスを提供する Fastly に2022年に買収されたとのことです。

やってみた

Glitch アカウントの作成

本手順では Glitch アカウントが必要なので、まだの場合は作成しておきましょう。

Glitch プロジェクトの作成

こちらからチュートリアルように予め用意された Glith プロジェクト(valley-maize-skiff)を開きます。

Remix をクリックします。

すると新しい名前でアプリが Remix(複製)されます。

※無料利用の場合は Remix されたプロジェクトはすべて一般公開となるため、後述の .env 以外には機密情報を含めないように注意してください。

プロジェクト内で予め作成されていた server.py では、Slack Bolt を使ったサーバーサイドの処理が実装されています。

server.py

import os, logging

logging.basicConfig(level=logging.DEBUG)

from slack_bolt import App

app = App(
    token=os.environ.get("SLACK_BOT_TOKEN"),
    signing_secret=os.environ.get("SLACK_SIGNING_SECRET"),
)


@app.middleware  # or app.use(log_request)
def log_request(logger, body, next):
    logger.debug(body)
    next()


# Step 5: Payload is sent to this endpoint, we extract the `trigger_id` and call views.open
@app.command("/thankyou")
def handle_command(body, ack, client, logger):
    logger.info(body)
    ack()

    res = client.views_open(
        trigger_id=body["trigger_id"],
        view={
            "type": "modal",
            "callback_id": "gratitude-modal",
            "title": {"type": "plain_text", "text": "Gratitude Box"},
            "submit": {"type": "plain_text", "text": "Submit"},
            "close": {"type": "plain_text", "text": "Cancel"},
            "blocks": [
                {
                    "type": "input",
                    "block_id": "my_block",
                    "element": {"type": "plain_text_input", "action_id": "my_action"},
                    "label": {"type": "plain_text", "text": "Say something nice!"},
                }
            ],
        },
    )
    logger.info(res)


# Step 4: The path that allows for your server to receive information from the modal sent in Slack
@app.view("gratitude-modal")
def view_submission(ack, body, client, logger):
    ack()
    logger.info(body["view"]["state"]["values"])
    # Extra Credit: Uncomment out this section
    # thank_you_channel = "your_channel_id"
    # user_text = body["view"]["state"]["values"]["my_block"]["my_action"]["value"]
    # client.chat_postMessage(channel=thank_you_channel, text=user_text)


if __name__ == "__main__":
    app.start(3000)

handle_command 関数ではスラッシュコマンド /thankyou を受け付けてモーダルビューを返しています。この時に Slack App 側はリクエストボディの trigger_id をレスポンスでも返してもらうことにより、ユーザーインタラクションを実現しています。また view_submission ではモーダルで入力された内容を受け取ってログ出力しています。

Glitch プロジェクトの Live site の取得

スラッシュコマンド実行時やモーダルでのデータ送信時に Slack App からの送信先となる Live site を取得します。

Remix されたプロジェクトで Share をクリックします。(このボタンが表示されるためには Glitch にサインインする必要があります)

ダイアログ中の Live site のURLをコピーして取得します。

App Manifest

今回のチュートリアルに従って作成した Slack App の App Manifest は以下となります。

App Manifest

display_information:
  name: ModalTestApp
features:
  bot_user:
    display_name: ModalTestApp
    always_online: false
  slash_commands:
    - command: /thankyou
      url: https://XXX-XXX-XXXXX.glitch.me/slack/events
      description: A place to give thanks to someone !
      should_escape: false
oauth_config:
  scopes:
    bot:
      - commands
settings:
  interactivity:
    is_enabled: true
    request_url: https://XXX-XXX-XXXXX.glitch.me/slack/events
  org_deploy_enabled: false
  socket_mode_enabled: false
  token_rotation_enabled: false

featuresslash_commands ではスラッシュコマンドのキーワードと、 Request URL として先程取得した Live site の URL を登録しています。また settingsinteractivity ではユーザーによるモーダルからのデータ送信の Request URL として同じ URL を指定しています。

手っ取り早くアプリの動作を試したい方はこちらをお使いください。また本記事では Slack App の構築部分はこちらに代えさせて頂きます。GUI からの Slack App の作成手順はチュートリアルにありますので、確認したい方はそちらをご覧ください。

Glitch プロジェクトへの Slack App アクセス権限の設定

Slack App からスラッシュコマンドによるリクエストを受け付けた Glitch プロジェクトが、Slack App にモーダルのビューを返すための権限を設定します。

Slack App の Features > OAuth & Permissions で、Slack App をワークスペースにインストールしたら、Bot User OAuth Tokenを控えます。

Settings > Basic InformationSigning Secret を控えます。

そして Glitch プロジェクトで .env ファイルを開き、SLACK_BOT_TOKEN および SLACK_SIGNING_SECRET に先程控えた値をそれぞれ入力し、Slack Bolt の App 初期化時に参照するようにします。

Glitch では、この .env ファイルは公開されている Glitch プロジェクトであっても、外部からは参照できないようになっています。

動作確認

Slack クライアントでスラッシュコマンド /thankyou を実行します。Slack App が登録されていれば途中まで入力すると候補として出てきます。

すると dispatch_failed となりました。

Interactivity & Shortcuts および Slash Commands メニューに設定した Request URL でベースパス /slack/events を追加し忘れていました。

上記を修正して再度スラッシュコマンドを実行すると、次は operation_timeout となりました。

今度は Glitch プロジェクトの .env に Slack App へのアクセス権限が正しく設定できていませんでした。(SLACK_BOT_TOKENSLACK_SIGNING_SECRET の指定が逆になっていた)

上記を修正して改めてスラッシュコマンドを実行すると、今度はモーダルが表示されました。

モーダルからデータを入力して送信します。すると Glitch プロジェクト側のログで、送信されたデータを受信することができました。

おわりに

スラッシュコマンドでモーダルを開く Slack App を Glitch で実装するチュートリアルをやってみました。

Slack App でのモーダルを利用する場合の処理の流れを把握できたのと合わせて、Glitch という便利なサービスについても知ることができました。Slack App の検証利用程度であればリソースを明示的に作成や管理する必要がない Glitch で十分に事足りそうです。

以上