Cargo Lambda で Slack にカスタムダイアログを出す
内容
Slack でダイアログに入力をさせたい場合、基本的にはワークフロービルダーを使ってノーコードで作成することができる。
しかし任意のスクリプトを実行したり、複雑な内容を表示したいときには外部のエンドポイントを作成して、叩く必要がある。
ここでは Cargo Lambda (Rust の Lambda) を使ってダイアログを出すサンプルを紹介する。
大まかなフローとしては下図のように Slash Command
で Lambda にリクエストを行い、ダイアログを表示するよう Slack に Request を行う。そして最初の Slash Command にレスポンスを返す。
Slash Command の Slack のリクエストには 3秒以内 に応えなければタイムアウトになってしまう。
しかしレスポンスを返すと Lambda が終了してしまうため、その前にダイアログ表示のリクエストを送信する構成になっている。
ダイアログを返すだけであればそこまで時間はかからないので問題はない。
もしすぐにレスポンスを返せないロジックであればリクエストを受けたら非同期に別の Lambda を Invoke してレスポンスは返すという対策はある。
Slack 側の設定はエンドポイントの URL が必要なので Lambda のデプロイ後に設定する。
Lambda は slash command を押したときの POST リクエストが来ているものとする。
実装
Request
Slack から slash command での POST リクエストが飛んでくる。
飛んできた値が正規のリクエストなのか検証するべきであるがそれは別の解説記事で述べる。
ダイアログを出すためには trigger_id
が欲しい。リクエストボディに入っているはずである。
リクエストボディのフォーマットは
token=XXXXXXXXXXXXXXXXXXXXXXXX&team_id=T0000000000&team_domain=XXXXXXXXXXXXXX&channel_id=C0000000000&channel_name=XXXXXXXXXXXXXX&user_id=U0000000000&user_name=XXXXXXXXXXXXXX&command=%2FXXXXXXXXXXXXXX&text=&api_app_id=A0000000000&is_enterprise_install=false&response_url=https%3A%2F%2Fhooks.slack.com%2Fcommands%2FT0000000000%2F0000000000000%2FXXXXXXXXXXXXXXXXXXXXXXXX&trigger_id=XXXXXXXXXXXXX.XXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
見やすくすると
token=XXXXXXXXXXXXXXXXXXXXXXXX
&team_id=T0000000000
&team_domain=XXXXXXXXXXXXXX
&channel_id=C0000000000
&channel_name=XXXXXXXXXXXXXX
&user_id=U0000000000
&user_name=XXXXXXXXXXXXXX
&command=%2FXXXXXXXXXXXXXX
&text=
&api_app_id=A0000000000
&is_enterprise_install=false
&response_url=https%3A%2F%2Fhooks.slack.com%2Fcommands%2FT0000000000%2F0000000000000%2FXXXXXXXXXXXXXXXXXXXXXXXX
&trigger_id=XXXXXXXXXXXXX.XXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
というようにURLエンコードされて入っている。
JSON で来てくれたほうがパースは楽であるがこうなっている。
パースして trigger_id
を取り出す。
Dialog
あとは JSON でダイアログを出すように Slack の https://slack.com/api/views.open
に POST するだけである。
サンプルではシンプルな構成にしてあるが blocks には Block API で定義されたものが使える。
ちなみに Rust で Slack を扱うクレート slack-morphism
を使ってもよいが、地味にダイアログで使うような input な型が serde_json::Value のままで定義されていないことが多いのでここでは使っていない。
{
"trigger_id": <TRIGGER_ID>,
"view": {
"type": "modal",
"title": {
"type": "plain_text",
"text": "Dialog"
},
"blocks": [
{
"type": "section",
"text": {
"type": "plain_text",
"text": "Hello Slack"
}
}
]
}
}
CDK
CDK では Lambda に Function URL を発行してアクセスできるようにしている。
サンプルを動かす場合は Lambda の環境変数に
- SLACK_TOKEN
- SIGNING_SECRET
が必要となる。実運用であればこれは環境変数でなく ParameterStore などから参照できるようにしておくとよい。
Slack App
Slack の App では
Features
> Slash Commands
からエンドポイントを設定しておく。
また Lambda の環境変数として必要な値を
-
SLACK_TOKEN
Features
>OAuth & Permissions
> Bot User OAuth Token -
SIGNING_SECRET
Settings
>Basic Information
>App Credentials
>Signing Secret
から取得して設定する。
動作確認
まとめ
Slack に任意のダイアログを出すサンプルを提示した。
シンプルなメッセージやテキストの転送であれば ワークフロービルダー などを利用すればそれなりのものを作ることはできる。
しかし、より複雑な要件には上記のような外部連携を用いたリッチなダイアログが有効である。
ファイル(最大 10 MB)の外部転送など様々な使い方もできる。
また GAS などを使うことも可能なので正確性が求められないものならば Lambda 以外の選択肢もある。
ぜひ試していただきたい。
Discussion