Node-REDでSlackの特定の投稿に反応して返答する
Node-REDの「Slack Listen」ノードを利用して、Slackでメンション付きの特定の投稿に対して、返答する方法について説明します。
Slackの準備とnode-red-contrib-slackのインストール
Slackの準備とnode-red-contrib-slackのインストールは、以下の記事を参考にしてください。
今回は、ワークスペース「Node-RED開発」のチャンネル「node-red_alert」で、メンション「@Node-RED_notify」を付けて投稿したときに、返答するようにします。
Slackの追加設定
Socket Modeの設定
Slack APIページにアクセスして、アプリのSocket Modeを設定します。
- Slackのワークスペース「Node-RED開発」のメニューをクリックして、「設定と管理」を選択し、「アプリを管理する」をクリックします。
- slack app directoryのページが表示されるので、「ビルド」をクリックします。
-
slack apiのページが表示されるので、登録されているアプリの一覧から「Node-RED_notify」をクリックします。
-
メニューの「Socket Mode」を選択します。「Enable Socket Mode」のスイッチをONにして、Socket Modeを有効にします。
- Socket Modeのトークンを発行するために、Token Nameを入力して(ここでは、「socket_mode」)、「Generate」ボタンをクリックします。
- Socket Modeの
xapp-
で始まるトークンが生成されます。「Copy」ボタンをクリックしてトークンをコピーし、「Done」ボタンをクリックします。
- メニューの「Event Subscriptions」を選択します。「Enable Events」のスイッチをONにして、Slackのイベントが取得できるようにします。
- 下にスクロールし、Subscribe to bot eventsの「Add Bot User Event」ボタンをクリックして、「app_mention」イベントを追加します。「Save Changes」ボタンをクリックします。
「app_mention」は、ボットやアプリのメンションを付けた投稿があったときに発生するイベントです。
スコープの確認
メンションを付けた投稿を読み取る権限が付与されていることを確認します。
- メニューの「OAuth & Permissions」を選択します。
- ScopesのBot Token Scopesに「app_mention:read」が追加されています。
- 上にスクロールして、設定を反映させるために「Reinstall to Workspace」ボタンをクリックします。
- 「許可する」ボタンをクリックして、権限のリクエストを許可します。
▼ボタンをクリックすると、付与したスコープを見ることができます。
「アプリが参加している会話で@noderednotifyを直接メンションしているメッセージを表示」の権限が追加されています。
- 設定を変更しても、Slackアプリの
xoxb-
で始まるトークンは変わりません。
Node-REDによるフローの作成
Node-REDで、Slackに「@Node-RED_notify」を付けて投稿したとき、次のように返答するフローを作成します。
- 「Hello」の文字を含む投稿 ⇒ 「こんにちは」のメッセージを返答
- 「画像」の文字を含む投稿 ⇒ 「ロゴです」のメッセージとSlackのロゴを返答
- それ以外の投稿 ⇒ メンションを除いたメッセージをオウム返しに返答
Slack Listenのインストール
- Node-REDをWebブラウザで開きます。
- 右上にある「三」のボタンをクリックしてメニューを開き、「パレットの管理」をクリックします。
- 「ノードの追加」タブを選択して、検索のテキストボックスに「
slack-socket
」と入力します。
検索されたノードから「node-red-contrib-slack-socket」の「ノードを追加」ボタンをクリックします。
- パレットの「chat」グループに「Slack Listen」ノードが追加されます。
ノードの設定
- Node-REDのワークスペースに以下のノードを追加し、図のように配置します。
- Slack Listenノード
- functionノード
- slack-web-outノード
- debugノード
- Slack Listenノードをダブルクリックして、「新規にslack-controllerを追加」をクリックします。
- 以下の設定をして、「追加」ボタンをクリックします。
- Name: slack_message(任意)
- Token: コピーしたSocket Modeのトークンを貼り付け
- Event: app_mention(Subscribe to bot eventsに追加したイベント)
-
「完了」ボタンをクリックします。
-
functionノードをダブルクリックして、以下のコードを入力します。
// メンションを除いたメッセージを取得
var text = msg.payload.text.replace(/<@.*?> /, "");
var message = text;
if (text.indexOf("Hello") !== -1) {
message = "こんにちは";
msg.topic = "chat.postMessage";
msg.payload = {
"channel": "node-red_alert",
"text": message
};
} else if (text.indexOf("画像") !== -1) {
const fs = global.get('fs');
const filepath = "D:\\logo\\node-red-icon-2.png";
message = "ロゴです";
msg.topic = "files.upload";
msg.payload = {
"channels": "node-red_alert",
"initial_comment": message,
"filename": filepath,
"file": fs.createReadStream(filepath),
"filetype": "auto"
};
} else {
msg.topic = "chat.postMessage";
msg.payload = {
"channel": "node-red_alert",
"text": message
};
}
return msg;
- 「完了」ボタンをクリックします。
- slack-web-outノードをダブルクリックして、「slack-config」を選択します。
Slackアプリのトークンが追加されていない場合は、「新規にslack-coinfigを追加」を選択して、TokenにBot User OAuth Tokenのxoxb-
で始まるトークンをコピーして、貼り付けます。
- 「完了」ボタンをクリックします。
- 「デプロイ」ボタンをクリックします。
- 完成したフローです。
作成したフローのJSONを以下に貼っておきます。
Node-REDのメニューから「読み出し」->「クリップボード」で配置することができます。
Slack Listenノード、slack-web-outノードのTokenは再設定してください。
[{"id":"be894fe2ee8da493","type":"slack-listen","z":"74d16458.3e634c","slack":"dd37b22c18b48339","name":"","x":110,"y":160,"wires":[["d63f2da6d1b94492"]]},{"id":"66a5d8b47432f0e0","type":"debug","z":"74d16458.3e634c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":690,"y":160,"wires":[]},{"id":"3b3a64c981acc01e","type":"slack-web-out","z":"74d16458.3e634c","client":"095a24e4c419e66b","name":"","x":480,"y":160,"wires":[["66a5d8b47432f0e0"]]},{"id":"d63f2da6d1b94492","type":"function","z":"74d16458.3e634c","name":"","func":"// メンションを除いたメッセージを取得\nvar text = msg.payload.text.replace(/<@.*?> /, \"\");\nvar message = text;\n\nif (text.indexOf(\"Hello\") !== -1) {\n message = \"こんにちは\";\n msg.topic = \"chat.postMessage\";\n msg.payload = {\n \"channel\": \"node-red_alert\",\n \"text\": message\n };\n} else if (text.indexOf(\"画像\") !== -1) {\n const fs = global.get('fs');\n const filepath = \"D:\\\\logo\\\\node-red-icon-2.png\";\n \n message = \"ロゴです\";\n msg.topic = \"files.upload\";\n msg.payload = {\n \"channels\": \"node-red_alert\",\n \"initial_comment\": message,\n \"filename\": filepath,\n \"file\": fs.createReadStream(filepath),\n \"filetype\": \"auto\"\n };\n} else {\n msg.topic = \"chat.postMessage\";\n msg.payload = {\n \"channel\": \"node-red_alert\",\n \"text\": message\n };\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":300,"y":160,"wires":[["3b3a64c981acc01e"]]},{"id":"dd37b22c18b48339","type":"slack-controller","name":"slack_message","appToken":"","tokenType":"str","listenEvents":"app_mention"},{"id":"095a24e4c419e66b","type":"slack-config","name":"","credentials":{"token":""}}]
動作確認
Slackのチャンネル「node-red_alert」へ投稿すると次のように「Node-RED_notify」アプリから返答があります。
- A. メンションがないメッセージに対して返答がありません。
- B. メンションを指定して「Hello」と投稿すると、「こんにちは」と返答します。
- C. メンションを指定して「画像をください」と投稿すると、「ロゴです」というメッセージとSlackのロゴを返答します。
- D. メンションを指定して、投稿したメッセージに「Hello」、「画像」の文字がない場合は、そのままのメッセージを返答します。
Discussion