TL;DR
- App Manifestで設定する方法の節を読んで、添付するYAMLコードをコピーする
- Slack APPを新規作成し、「From a manifest」を選ぶ
- 上記YAMLを記入し、APPを作成する
- APPをワークスペースにインストールし、該当APPを所定のチャンネルに追加する
- Bolt frameworkを使った実装の節を読んでのコードを実装する
はじめに
Slackは手軽で無料で使える IM (Instant Messaging) ツールの一つとして、広く使われています。
しかも同じIMツールですが、Discord、Line、ChatworkなどはAPIでメッセージを受信したい場合、自前のサーバーを構築しWebhookを登録せざるを得ないか、APIポーリングでの実装となります。
それらに比べると、Slackの方はWebSocketを活用したSocket Modeの存在していていることはとても重宝されています。
しかし、Slack APIのSocket Modeはこの4、5年で、 RTM API => Slack Socket Mode => Bolt(Socket Mode)と推奨実装が変わっていました。そのせいで、ネット上の資料だけ読むと、かなり困惑になります。
今回私たちは現在推奨している Bolt SDK をメインに解説します。
方法
[最重要] Slack アプリの設定
昔SlackのAPI叩くには、API Key一本で足りましたが、今はSlack appを構築し、いくつかの権限を設定せねばならないです。
これら権限の設定が誤ると、エラーすらでない場合があります。
画面上の操作で設定する方法
叩き台(Scratch)の作成
まずはCreate an appにアクセスし、「From scratch」 をクリックします。
App Nameを入力して、アクセス予定のWorkspaceを選び、「Create App」をクリックします。
これでAppの雛形が作成完了し、設定画面が表示されます。次はアクセス権限等を設定します。
Socket Modeの権限設定
Slackのポリシーにより、Socket Modeが設定されたAppはマーケットプレイスでは公開不可ですが、個人での利用は問題ありません。
左側のメニューにある「Socket Mode」をクリックし、「Enable Socket Mode」のスイッチをONにします。
するとAPP用トークンの設定画面が表示され、「Token Name」を入れて、「Generate」をクリックします。
これで xapp-
から始まる、いわゆるApp Tokenが作成されます。
Slack AppのTokenは xapp-...
、 xoxb-...
、 xoxp-...
3種類があります。
本文でも後ほど一応軽く説明しますが、詳しい解説はこちらをご覧ください。
Events APIの設定
Socket Mode設定画面そのまま下へスクロールすると、「Event Subscriptions」のところが「No」となっています。そのリンクをクリックするか、またはメニューの「Event Subscriptions」をクリックし、設定画面に入ります。
「Enable Events」のスイッチをオンにして、「Subscribe to bot events」のアコーデオンを展開し、「Add Bot User Event」をクリックします。
メッセージを受信するには、下記の4つを追加します。
message.channels
, message.im
, message.groups
, message.mpim
追加したら、ページの一番下の「Save Changes」をクリックします。
それぞれのEventについてはこちらをご覧ください。
送信権限の設定
「Features」=>「OAuth & Permissions」を開き、「Scopes」=>「Bot Token Scopes」に chat:write
を入れて保存します。
App Manifestで設定する方法
前述の設定は、メニューの「Features」=>「App Manifest」欄にJSONまたはYAML形式で出力できます。
同じ設定で別のAppを作る際は、Create New Appの時、「From a manifest」を選び、下記の設定ファイルを貼り付ければOKです。
display_information:
name: Slack-Bot-Demo
features:
bot_user:
display_name: Slack-Bot-Demo
always_online: false
oauth_config:
scopes:
bot:
- channels:history
- groups:history
- im:history
- mpim:history
- chat:write
settings:
event_subscriptions:
bot_events:
- message.channels
- message.groups
- message.im
- message.mpim
interactivity:
is_enabled: true
org_deploy_enabled: false
socket_mode_enabled: true
token_rotation_enabled: false
Appのインストール
Appをワークスペースにインストールしてから、アクセス可能となります。
インストール出来たら、xoxb-
から始まる、いわゆるBot Tokenも使えるようになります。
Slackのチャット画面を開くと、先ほど作成したAppが表示されます。だが、そのままはまだ使えないので、右クリック =>「アプリの詳細を表示する」=>「チャンネルにこのアプリを追加する」で、所定のチャンネルに該当Appを登録します。
Bolt frameworkを使った実装
環境変数の用意
.env
ファイルを作成し、下記の内容を記入します。
SLACK_APP_TOKEN=xapp-XXXXXXXXXXX
SLACK_BOT_TOKEN=xoxb-XXXXXXXXXXX
トークンの確認方法は:
-
xapp-
から始まるSLACK_APP_TOKEN
: 「Settings」=>「Basic Information」を開き、下にスクロールして、「App-Level Tokens」のところで確認
-
xoxb-
から始まるSLACK_BOT_TOKEN
: 「Settings」=>「Install App」または「Features」=>「OAuth & Permissions」で確認
ライブラリのインストール
npm i @slack/bolt dotenv
サンプルコードの実装
import bolt from '@slack/bolt';
import { config } from 'dotenv';
config({ quiet: false });
const { App } = bolt;
const app = new App({
token: process.env.SLACK_BOT_TOKEN, // xoxb-XXXXX
appToken: process.env.SLACK_APP_TOKEN, // xapp-XXXXX
socketMode: true,
});
(async () => {
await app.start();
console.log('⚡️ Bolt app started');
// すべてのメッセージを受信
app.message(/.*/, async ({ message, say }) => {
console.log(`Received message:`, message.text);
await say(`Hi <@${message.user}>!`);
// 下記と同じ
// await app.client.chat
// .postMessage({ channel: message.channel, text: `Hi <@${message.user}>!` });
});
})();
実行結果
$ node ./index.mjs
[dotenv@17.2.0] injecting env (2) from .env (tip: 🔐 prevent building .env in docker: https://dotenvx.com/prebuild)
⚡️ Bolt app started
Received message: こんにちは
Curl / WebSocket Clientでのアクセス
WebSocket URLの取得
xapp-
から始まるアクセスキーで、下記のようにWebSocket URLを取得します。
$ curl -X POST "https://slack.com/api/apps.connections.open" \
-H "Content-type: application/x-www-form-urlencoded" \
-H "Authorization: Bearer xapp-XXXXX"
{"ok":true,"url":"wss:\/\/wss-primary.slack.com\/link\/?ticket=xxxxx-xxxx-xxx-xxx-xxx&app_id=XXXXXX"}
WebSocketでメッセージを受信
上記 wss://wss-primary.slack.com/link/
から始まるURLを自前のWebSocket Clientでアクセスします。
コンソルの vi/websocat も、下記のようなChrome拡張機能もアクセスできます。
アクセス成功したら、まずは下記のような hello
Eventが受信されます。
{
"type" : "hello",
"num_connections" : 2,
"debug_info" : {
"host" : "applink-12",
"build_number" : 118,
"approximate_connection_time" : 18060
},
"connection_info" : {
"app_id" : "XXXXX"
}
}
Slackでメッセージを送信したら、WebSocket Client側は下記のようなJSONが受信されます。
手動でSlackのSocket Modeから受信する際は、直ちに確認のメッセージを送信しないと、リトライが発生します。
手動でメッセージを送信
従来のRTM APIと違い、SlackのSocket Mode APIは受信専用なので、送信する際は下記のように、REST APIを使います(その際、使うアクセスキーは xoxb-
から始まるもの)。
POST https://slack.com/api/chat.postMessage
Content-Type: application/json
Authorization: Bearer xoxb-XXXXXX
{
"channel": "YOUR-CHANNEL-ID",
"text": "Hello, world!"
}
公式ライブラリの@slack/socket-modeも、Boltも、chat.postMessage()
を使って送信をしています。
余談: Botとのダイレクトメッセージをしたい時
デフォルトの設定では、ボットのDM画面では「このアプリへのメッセージ送信はオフにされています。」が表示され、送信できません。
APP設定画面の「Features」=>「App Home」を開き、下までスクロールして、「Allow users to send Slash commands and messages from the messages tab」のチェックをすれば、送信できるようになります。(再インストールは不要、チェックだけでOK)