Slack RTM APIとは?
RTMはReal Time Messagingの略です。
その名の通り、Slackのサーバーとクライアントがリアルタイムに(かつ双方向に)やり取りするためのAPIです。web socketという仕組みが使われています。
現在はWeb APIとEvents APIを使うように推奨されていますが、まだ一応は使えます1。
また、RTM APIにしか出来ないこともいくつかあります。
「Web API + Events API」と「RTM API」のどちらを使えばよいかの判断基準はEvents API FAQにまとめられていますが、個人的には
You're building an on-premise integration or have no ability to receive external HTTP requests
つまり
Slackのアプリ(例:ボット)を動かすサーバーを外部に公開したくない/できない
ような場合、RTM APIは非常に便利です2。
簡単にRTM APIを使う方法
Slack公式でPythonからRTM APIを使うためのライブラリが公開されています。
単純にボットを作るだけなら、ライブラリを使うのが手っ取り早いです。
あえてAPIを直にたたく
冒頭でも述べたようにRTM APIはweb socketという仕組みで実現されています。
勉強のために、このweb socketを直接触ってみようと思います!
下準備
まずはwebsocatというコマンドを導入します。
インストール方法の詳細はリポジトリのREADMEを見てほしいのですが、自分の環境(Ubuntu18.04)では次のようにインストールしました
# debファイルをいい感じにインストールしてくれるコマンドを導入しておく
# debファイルがインストールできさえすれば良いので他のコマンドでも可
$ sudo apt install gdebi
# websocatのdebファイルのダウンロード
$ wget https://github.com/vi/websocat/releases/download/v1.5.0/websocat_1.5.0_ssl1.1_amd64.deb
# debファイルのインストール
$ sudo gdebi install websocat_1.5.0_ssl1.1_amd64.deb
また、SlackのAPIはJSONファイルを扱うことが多いので、JSON整形用のコマンドを導入しました。
$ sudo apt install jq
最後にRTM APIを使うためのトークンを取得します。
一番手っ取り早いのはBotsインテグレーションの利用です。
https://[your_team_name].slack.com/apps/A0F7YS25R-bots
からSlackに追加
をクリックし、ボットのユーザー名を入力するとトークン(xoxb-
から始まる文字列)が表示されます。
実践
準備が整ったので早速APIを触ってみましょう。
まずはwebsocketでRTMを開始するためのURLを発行します。
詳細はrtm.connectを参照してください
# xoxb-***には取得したトークンを記述する
$ curl -X GET -H "Authorization: Bearer xoxb-*************" https://slack.com/api/rtm.connect | jq
APIの結果はJSON形式で返ってくるのでjq
で整形しています。
実行例は以下の通りです。
{
"ok": true,
"url": "wss://cerberus-xxxx.lb.slack-msgs.com/websocket/*****",
"team": {
"id": "****",
"name": "your_team_name",
"domain": "your_team_name"
},
"self": {
"id": "*****",
"name": "your_bot_name"
}
}
このurl
の値をもとに次のコマンドをすぐに実行します(30秒以内の制限あり)。
$ websocat wss://cerberus-xxxx.lb.slack-msgs.com/websocket/*****
ただ、30秒以内にURLをコピーしてwebsocatコマンドを実行するのは大変なので次のようにコマンドをまとめた方がよいかもしれません。
$ export SLACK_TOKEN="xoxb-******"
$ websocat $(curl -sS -X GET -H "Authorization: Bearer ${SLACK_TOKEN}" https://slack.com/api/rtm.connect | jq -r '.url')
成功すると
{"type": "hello"}
と表示されるはずです。
イベントを眺める
Slackクライアントからボットにダイレクトメッセージを送ってみましょう。ここではhoge
というメッセージを送ってみました。
このときターミナル側では次のような出力が得られるはずです(一部マスクしています)。
{"type":"user_typing","channel":"*****","user":"******"}
{"client_msg_id":"******","suppress_notification":false,"type":"message","text":"hoge","user":"******","team":"******","blocks":[{"type":"rich_text","block_id":"tKU","elements":[{"type":"rich_text_section","elements":[{"type":"text","text":"hoge"}]}]}],"source_team":"******","user_team":"*****","channel":"*****","event_ts":"1583495285.002500","ts":"1583495285.002500"}
{"type":"desktop_notification","title":"*****","subtitle":"******","msg":"1583495285.002500","ts":"1583495285.002500","content":"hoge","channel":"******","launchUri":"slack:\/\/channel?id=******&message=1583495285002500&team=TCH2Q1N1H","avatarImage":"https:\/\/avatars.slack-edge.com\/****.png","ssbFilename":"knock_brush.mp3","imageUri":null,"is_shared":false,"is_channel_invite":false,"event_ts":"1583495286.000100"}
これらはSlackのイベントを表しています。
どうやらhoge
というダイレクトメッセージを送った結果、3つのイベントが発生したようです。
どのようなイベントが発生したかは、type
の値を見ればわかります。
- 1行目:
type
はuser_typing
となっています。このイベントは文字入力をしメッセージをているときに生じるイベントです (○○さんが入力しています みたいなメッセージが表示されることがありますよね)。 - 2行目:
type
はmessage
になっています。文字通りメッセージが送られたことを表すイベントです。text
の値も確かにhoge
になっています。 - 3行目:
type
はdesktop_notification
です。
他にも様々なイベントが存在しここにまとめられています。
RTM APIでメッセージを送る
websocatの標準入力に文字を入力することでRTM APIを用いてメッセージを送ることができます。
ただしメッセージの送信はJSON形式で行います。
以下は入力例です。
{"type": "message", "channel": "******", "text": "foo"}
channel
にはuser_typing
やmessage
イベントで受け取ったchannel
の値をそのまま入力します。
うまくいくとSlackクライアント側でfoo
というメッセージがボットに送られたことを確認できるはずです。
まとめ
websocetで直接RTM APIを叩いてみました。実際にボットを作るのであれば各言語で用意されているライブラリを使うべきでしょう。
現在推奨されているEvents APIではサブスクライブしたイベントだけがアプリサーバーに送られます。一方でRTM APIにはそういったスコープのようなものは無いです。
実際にRTMでイベントを受信するのを眺めてみると、スコープもなく様々なイベントが送られてくることが実感できますね!