BotにSlackのプライベートチャンネルリストを教えてもらう(Node.jsのBotkitとIBM Cloudを用いた対応)
課題
自分が属している団体のSlackで運営スタッフだけのプライベートチャンネルがいくつかあるが、プライベートチャンネルのため、どのような運営用チャンネルが存在しているかわからなくなるという問題がある。一度誤って抜けてしまうと、誰かに頼まないと戻れなくなるのだが、誰に頼んで良いのかもわからなくなることもある。
この問題を解決するためにBotを開発した。ただし、プライベートチャンネルのため、Botもそのプライベートチャンネルに所属していないとならない。
運用イメージ
- 運営用プライベートチャンネルはBotをメンバーとして登録する
- 運営スタッフはそのBotにメンションかDMかで話しかけることにより、Botが属しているプライベートチャンネルの全リストをその作成者名とともに取得できる
- 自分が入るべきプライベートチャンネルがあったならば、その作成者にコンタクトし、招待してもらう。ここにはBotは介在しない
Botの開発
BotはNode.jsで開発し、IBM Cloudで運用することにした。
Botkit
Node.jsで作られたBotkitを利用した。Slackとの連携も極めて簡単。
使ったものは、
ソースコードは以下。
const Botkit = require('botkit'); const async = require('async'); if (!process.env.token) { console.log('Error: Missing API Token'); process.exit(1); } const controller = Botkit.slackbot({ debug: false, retry: Infinity // 常駐させるため }); controller.spawn({ token: process.env.token }).startRTM((err, bot, payload) => { if (err) { throw new Error(err); } }); // pubchlistと聞かれたら controller.hears('pubchlist',['direct_message','direct_mention','mention'],(bot,message) => { bot.api.channels.list({}, (err, res) => { async.each(res.channels, (channel, callback) => { if(!channel.is_archived){ bot.api.users.info({user:channel.creator}, (err,res) => { bot.reply(message, channel.name + ' created by ' + res['user']['name']); }) } }) }) }); // prchlistと聞かれたら controller.hears('prchlist',['direct_message','direct_mention','mention'], (bot,message) => { bot.api.groups.list({}, (err, res) => { async.each(res.groups, (groups, callback) => { if(!groups.is_archived){ bot.api.users.info({user:groups.creator}, (err,res) => { bot.reply(message, groups.name + ' created by ' + res['user']['name']); }) } }) }) }); // それ以外を聞かれたら controller.hears(['(.*)'], ['direct_message','direct_mention','mention'], (bot,message) => { bot.reply(message, 'Usage: type prchlist to get private channels list OR publist to get public channels'); });
Botに話しかけられるコマンドは2つだけ。
- pubchlist: パブリックチャンネルの一覧をその作成者とともに表示
- prchlist: Botが所属しているプライベートチャンネルの一覧をその作成者とともに表示
【追記】Admin権限を持つ人だけがプライベートチャンネルリストを見れるようにする
プライベートチャンネルリストが見れる人をAdmin権限を持つ人だけに絞るには、prchlist
をhears
している部分を以下のように変更する。
// prchlistと聞かれたら controller.hears('test',['direct_message','direct_mention','mention'], (bot,message) => { var currentUser; bot.api.users.info({user:message.user},function(err,response) { if (err) { throw new Error(err); } currentUser = response['user']; if (!currentUser['is_admin']) { bot.reply(message, 'Only Admin can see the list of private channels'); } bot.api.groups.list({}, (err, res) => { async.each(res.groups, (groups, callback) => { if(!groups.is_archived){ bot.api.users.info({user:groups.creator}, (err,res) => { bot.reply(message, groups.name + ' created by ' + res['user']['name']); }) } }) }) }) });
Slack APIのusers.info
でBotkitから代えるmessage.user
情報を取得し、Admin権限があるかどうかを確認している。
Slack側の準備
プログラムの中でSlackのBot用のAPI Tokenを利用している。これは環境変数で引き渡すことになる。
Sign in | Slack にアクセスし、API Tokenを発行する。
ローカル環境での動作
$ token=<API Token> node app.js
これでSlack側でBotにDMするか、Inviteしたチャンネルでメンションし、話しかけてテストできる。
Botの運用
BotはNode.jsが動かせる環境ならなんでも良かったのだが、IBM Cloudライトアカウントの無料枠の範囲で十分そうだったので、それを使った。
$ cf api https://api.ng.bluemix.net/ $ cf login $ cf push itdartbot --no-route -u none -m 256M $ cf cf set-env itdartbot token <api token> $ cf restage itdartbot
cf push
での--no-route
と-u none
はワーカーとして動作させ、Health Check不要のため。また、-m 256M
はIBM Cloudライトアカウントではメモリが256MBに制限されているため。
参考にしたもの
- ココからスタートしよう、Botkitの基礎!+応用への手引き - Qiita
- はじめてnodejsを使った。はじめてチャットリレーbotを作った話。 - Qiita
- Slackでメンバーが参加しているチャンネルをBotkit(Slack API)で調べる - Qiita
- How to know user's full name who pinged the bot? · Issue #411 · howdyai/botkit · GitHub
- channels.list method | Slack
- groups.list method | Slack
- users.info method | Slack