Function ComputeでサーバレスなSlack Botを作る
作るもの
Alibaba CloudのFunction ComputeでサーバレスなSlack Botを作ります。
/my_echo [TEXT]
と入力すると作ったBotが[TEXT]
を返すechoのコマンドを作ります。
LambdaとSlack Botの連携をする公式ドキュメントを参考にしています。Slack側の設定はこちらを参照してください。
Handling events from the Events API using AWS Lambda | Slack
botの追加
App Deirectoryで「bots」と検索してbotを追加します。 Add Apps to Slack | Apps and Integrations | Slack App Directory
BotsのページでAdd Configuration
を押します
適当なUsername
を入力します。私は安直にtest_botにしました。
API Token
をコピーします。
ここの中程にあるcurlを実行して正常にbotが喋ったら成功です。
$ curl -X POST -H 'Authorization: Bearer xoxb-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \ -H 'Content-type: application/json' \ --data '{"channel":"random","text":"I hope the tour went well, Mr. Wonka.","attachments": [{"text":"Who wins the lifetime supply of chocolate?","fallback":"You could be telling the computer exactly what it can do with a lifetime supply of chocolate.","color":"#3AA3E3","attachment_type":"default","callback_id":"select_simple_1234","actions":[{"name":"winners_list","text":"Who should win?","type":"select","data_source":"users"}]}]}' \ https://slack.com/api/chat.postMessage
シャァベッタァァァァァァァ!!
Function Computeで関数の追加
一つ適当に作っておきます。以下を参照のこと。
Slash Commandsの追加
my_echo
ってコマンドにします。
実装
nodejsでソースコードを書きます。
こんな感じの構成にします。
$ tree . ├── node_modules ....(略) ├── package.json ├── slack.js └── yarn.lock
npmのライブラリであるrequest
を使うので、/node_modules
も一緒にアップロードします。
※zipでアップロードしようとしましたがなんか壊れてるっぽい(2018/7/12)のでコンソール画面から「フォルダのアップロード」でアップロードしました。
const https = require('https') const req = require('request') const getRawBody = require('raw-body') const VERIFICATION_TOKEN = "xxxxxxxxxxxxxxxxxxxxx" const ACCESS_TOKEN = "xoxb-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" function post(query, request, response) { getRawBody(request, function(err, data){ const params = { form: { token: ACCESS_TOKEN, channel: query.channel, text: query.text } } req.post('https://slack.com/api/chat.postMessage', params) .on('response', (res) => { const body = data const status = 200 respBody = new Buffer(body) response.setStatusCode(status) response.setHeader('content-type', 'application/json') response.send(respBody) }) }) } function process(request, response) { const data = request.queries const message = { channel: data.channel, text: data.text } post(message, request, response) } function verify(request, response) { let status, body if (request.queries.token === VERIFICATION_TOKEN) { status = 200 body = `challenge:${VERIFICATION_TOKEN}` } else { status = 500 body = 'error' } getRawBody(request, function(err, data){ respBody = new Buffer(body) response.setStatusCode(status) response.setHeader('content-type', 'application/json') response.send(respBody) }) } exports.handler = (request, response, context) => { switch (request.queries.type) { case "url_verification": verify(request, response, '', ''); break case "event_callback": process(request, response); break default: process(request, response) } }
verify()
はSlack APIのサービス追加時のEvent Subscriptions
で使います。
url_verification event | Slack
handler
の第一引数であるrequest
には以下のオブジェクトが入っています。
{ "domain": null, "_events": {}, "_eventsCount": 0, "method": "GET", "clientIP": "54.234.37.47", "url": "/2016-08-15/proxy/test/slack/?token=xxxxxxxxxxxxxxxxx&team_id=TBPAQJLHK&team_domain=asmsuechan&channel_id=CBNF2BSQG&channel_name=random&user_id=UBNF2BPB2&user_name=suenagaryoutaabc&command=%2Fmy_echo&text=asaaaaa&response_url=https%3A%2F%2Fhooks.slack.com%2Fcommands", "path": "/", "queries": { "channel_id": "CBNF2BSQG", "channel_name": "random", "command": "/my_echo", "response_url": "https://hooks.slack.com/commands/TBPAQJLHK/397188022723/xxxxxxxxxxxxxxxxxxxxxxx", "team_domain": "asmsuechan", "team_id": "TBPAQJLHK", "text": "asaaaaa", "token": "xxxxxxxxxxxxxxxxxxxxxxx", "user_id": "UBNF2BPB2", "user_name": "suenagaryoutaabc" }, "headers": { "accept": "application/json,*/*", "user-agent": "Slackbot 1.0 (+https://api.slack.com/robots)" } }
※デバッグむずい。SlackへのPOSTリクエスト送信部とFunctionComputeのhandler部分を分けて実装したら作りやすいです。
特にBotsのIntegration Settingsのchallenge。
検証
よっしゃできた。
まとめ
Slackさん、諸々のキーがどこにあるか分かりにくい。