techium

このブログは何かに追われないと頑張れない人たちが週一更新をノルマに技術情報を発信するブログです。もし何か調査して欲しい内容がありましたら、@kobashinG or @muchiki0226 までいただけますと気が向いたら調査するかもしれません。

Botkitを使ってSlackBotを作ってみる

Slackやその他のチャットでBotを作る場合はよくHubotを使われますが、Hubotを使わなくても(ベースはNode.jsですが…)Node.jsで実現可能です。
そこで非常に簡単にSlackの操作がすることができるライブラリとしてBotkitがあります。

今回はそのBotkitを使ってSlackに入力される文字列から判断して会話するBotを作ってみましょう。

Slackからトークンを取得する

まずはSlackのBot用のTokenを取得しましょう。
ここで得られるTokenはBotkitでのアクセスに利用されます。

Tokenの取得はこちらのページに飛ぶと下図のような画面に遷移します。

f:id:muchiki0226:20160417164814p:plain:w400

ここでBotのユーザ名を設定します。
このユーザ名はダイレクトメッセージを送るときに使われる名前になります。
ユーザ名を入力し、Add bot integrationをクリックすると次のような画面に遷移します。

f:id:muchiki0226:20160417164818p:plain:w400

上図のオレンジで伏せられている場所に書かれているものがTokenとなります。 これをTokenをBotkitで利用します。

この画面に遷移したタイミングでBotを作成を実施したチームに指定したBotのユーザ名が未ログイン状態で表示されていると思います。
これで準備完了です。

BotkitでSlackと接続してみる

Botkitのインストールは次のようにします。

$ npm init
$ npm install botkit --save

npm initでpackage.jsonを作るための情報を入力することになりますが、それは作りたいアプリの名前と作成者、ライセンスの種類を指定してください。
これでNPMでBotkitのインストールができました。
それでは簡単にBotに対してダイレクトメッセージが送られてきた時に返答を返すようにしてみましょう。
それは次のように実装を行います。

Botkitを使ってSlackの応答を返す

index.jsの3行目でBotkitoでSlackをコントロールできるコントローラを作成する。
この時にdebugフラグをfalseにしているがtrueにするとBotkitoがバックグラウンドでどのような動作しているかのログが表示されるようになる。
例えばBotの生存確認のために定期的にPing/Pongで生存確認を行ったり、Slack上での状態の変化があった時の通知を届いているかなどが確認できる。
そして最初に登録したtokenを8行目に設定する。
今回は環境変数のtoken設定しましょう。わからない場合はサンプルコードのREADMEを見てください。
9行目のstartRTMを実行するとSlackと接続が行われ、双方向に通信が始まる。
startRTM以降にSlack上でメッセージの書き込みや呼び出しなどが行われるとBotkitにメッセージが送付される。
次に12行目のhearsでメッセージの送付されてきた時の動作を記述する。
第1引数はどのようなメッセージがSlack上に書き込まれたかを判断する文字列になります。
そして第2引数はどのイベントのメッセージを拾うかを設定します。
イベントの種類は下記の通りになります。

イベント 概要
direct_message Botに対して直接メッセージを送付した場合
direct_mention Botが参加しているチャンネルで「@ボット名:」を先頭にして呼び出した場合
mention Botが参加しているチャンネルで文章中に「@ボット名」が含まれている場合

第3引数にSlack上のメッセージに第1引数の文字列と合致したときに呼び出されるコールバック関数を設定します。
ここで注意が必要なことはSlack上で入力された文字列が第1引数と完全一致したら呼び出されるわけではないことに注意しましょう。
例えば第1引数にhiという文字列の場合にSlack上で「high」や「tahichi」などでも引っかかります。
Slack側で入力された文字列を取得するには第3引数のコールバッ関数の第2引数にJSONオブジェクトが渡され、その内容に入力された文字列の詳細を取得することができます。

例えば、上記のソースコードを実行した時にSlack上で下記の文字列を入力します。

@bot名: techium 

そうするとindex.jsの12行目のhearsが呼び出されます。
そのコールバック関数の第2引数は下記のような構成になっています。

{ type: 'message',
  channel: 'XXXXX',
  user: 'XXXXX',
  text: 'techium',
  ts: 'XXXXX',
  team: 'XXXXX',
  event: 'direct_mention',
  match: [ 'techium', index: 0, input: 'techium' ] }

textという部分に実際に入力された文字列が入ります。
そしてmatchで一致した位置を取得することができます。
これらで求めている文字列かどうかの判断をすることができます。

Botと会話をしてみる

最後にBotと会話する方法についてです。 Botと会話をするにはConversationのaskという機能を使います。 例を用意しました。 今回の例は「weather」という文字列が入力された時に明日の天気が雨なことと車で出かけられるかどうかBotが尋ねるようなコードになっています。

Botkitを使ってSlackユーザーに要件を尋ねる

11行目のhearで特定の文字列「weather」という入力を待ち、入力された時に36行目で会話をスタートさせています。
また、15行目のaskの第1引数をSlackのユーザに問いかけます。
そして何かしらレスポンスを貰えると第2引数のコールバック関数に応答が返ってきます。
このコールバック関数の第1引数のtextという変数に実際の応答された文字列が入ってきます。
18行目のところでtextを確認して動作を切り替えています。
また、17行目ではsayを使うことでSlackへメッセージを送っていますが、 もし引き続きユーザへ問いかけたい場合は19行目のように26行目のaskをもう一度呼び出すことで会話の続きを実施することができます。
最後に22行目や33行目でnextというのを実施していますがこれは必ず必要となります。
これをしないとConversationに処理が返らず、ハングするそうです。
またnext以外にもrepeatもあり、これはもう一度同じaskを実行することになります。

これを実行した時の動きは下図のようになります。

f:id:muchiki0226:20160417230904p:plain

サンプルコード

github.com