Slack bot で bot 自身の発言は無視したい
Slack botへのメンションをトリガーとした何かしらを作るにあたって、とりあえずの練習として「botへのメンションがあったらその内容をオウム返しする」ものを作りました。
そのとき、無限ループに陥ってしまったので、それを回避する方法です。
Slack bot自体の作成の方法については述べません。
Slack bot自体の扱いはいくつかの他のブログを参考にさせていただきました。 teppay.hatenablog.com
これまで通り、SlackとGASの組み合わせです。
これまで ↓
ohshige.hatenablog.com
ささっと、オウム返しを行うGASを書いて公開しました。
function doPost(e) { var params = JSON.parse(e.postData.getDataAsString()); // URL検証用 if (params.type === 'url_verification') { var response = {'challenge': params.challenge}; return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON); } // Webhookを使ってparamsをそのままオウム返しする処理 }
この状態で、 @bot名 こんにちは
などとメンションを送ると、Slack Eventの様々な情報を含んだままポストされました。
{ "token":"XXXXXXXXXX", "team_id":"XXXXXXXXXX", "api_app_id":"XXXXXXXXXX", "event":{ "client_msg_id":"xxxxxxxxxxxxxxxxxxxxxxx", "type":"app_mention", "text":"@bot名 こんにちは", "user":"UXXXXXXXXXX", "ts":"0000000000000000", "team":"TXXXXXXXXXX", "channel":"CXXXXXXXXXX", "event_ts":"0000000000000000" }, "type":"event_callback", "event_id":"EvXXXXXXXXXX", "event_time":0000000000000000, "authed_users":["UXXXXXXXXXX"] }
これで成功したかに思えたのですが、直後またポストがあり、その直後にもポストがあり、...と無限ループに陥ってしまいました。
急遽連携を解除したことで止まりましたが、かなり焦りました。
2つ目のポストはこんな内容でした。
{ "token":"XXXXXXXXXX", "team_id":"TXXXXXXXXXX", "api_app_id":"XXXXXXXXXX", "event":{ "type":"app_mention", "subtype":"bot_message", "text":"{\"token\":\"XXXXXXXXXX\",\"team_id\":\"TXXXXXXXXXX\",\"api_app_id\":\"XXXXXXXXXX\",\"event\":{\"client_msg_id\":\"xxxxxxxxxxxxxxxxxxxxxxx\",\"type\":\"app_mention\",\"text\":\"@bot名 こんにちは\",\"user\":\"UXXXXXXXXXX\",\"ts\":\"0000000000000000\",\"team\":\"TXXXXXXXXXX\",\"channel\":\"CXXXXXXXXXX\",\"event_ts\":\"0000000000000000\"},\"type\":\"event_callback\",\"event_id\":\"EvXXXXXXXXXX\",\"event_time\":0000000000000000,\"authed_users\":[\"UXXXXXXXXXX\"]}", "ts":"0000000000000000", "bot_id":"BXXXXXXXXXX", "channel":"CXXXXXXXXXX", "event_ts":"0000000000000000" }, "type":"event_callback", "event_id":"EvXXXXXXXXXX", "event_time":0000000000000000, "authed_users":["UXXXXXXXXXX"] }
これでわかるように、botによってポストされた内容にも @bot名 こんにちは
が含まれています。
オウム返しなのだから当然だろうという話ですが、実行するまで気づけなかったです。
というわけでbotによるポストは無視して、ユーザによるポストだけに反応させれば良さそうなので、そのポストがbotかどうかの判定を入れます。
その方法としては、eventのsubtypeがbot_messageかどうかを判定すれば良さそうです。
function doPost(e) { var params = JSON.parse(e.postData.getDataAsString()); // URL検証用 if (params.type === 'url_verification') { var response = {'challenge': params.challenge}; return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON); } // botによるポストの場合は何もしない if (params.event.subtype === 'bot_message') { return; } // Webhookを使ってparamsをそのままオウム返しする処理 }
bot_idもわかるので、自分自身だけは無視して他のbotとの会話は可能にしたい場合などはbot_idで判定すれば良さそうです。
無限ループって怖いですね。