Heroku(Free Dyno)のWorkerでSlackのBotkitを動かしてみよう!

 おのでらです。
 Heroku で worker を試していたので、そのメモを改めて記事にしました。
 というか、「なんだ、ベトナムの記事の続きじゃないのかよ!?」と突っ込まれそうですね。ごめんなさい。先に謝っておきます。今年は先に謝っておくシーンが多い暗示なのかもしれませんね…。

 さぁ、レッツ本題。
 みなさん、Slack使っていますか? このブログの過去記事に何件かあるように、弊社でも社内ツールとしてSlackを去年から使い始めました。
 そのSlackですが、昨年末に今後の戦略としてプラットフォーム化宣言をしました。その中で、Botフレームワークとして「Botkit」も発表しており、公式のものがやっとできたという感じですね。
 さっそく使ってみましょう。
ゴール

 Heroku 内に、Slackの特定チャネルのメッセージの内容を判断して目的の応答を返すBotを作ってみます。
 使うモジュールはBotkitです。
 BotkitはNode.jsのライブラリですので、サーバ側処理もNode.jsを使います。
 
 
はじめに

 今回はお試しな導入でもあるので、Heroku の Free Dyno Type を使います。Free Dynoは稼働時間に制約があるのでドキュメントを確認しておいてください。アカウントは適宜取って、"Getting Started" などのHerokuの基本的なチュートリアルは済ませておいてください(※)。
 また、Node.jsで開発を進めるので、ローカルの開発環境にNode.jsをインストールしておきます。オススメとしてはNodebrewですね。作るアプリケーション毎にNode.jsのバージョンを任意で切り替えられるのと、かつ自分のアカウント下のみで完結する環境が構築できる、という理由から重宝します。インストールしてみてください。

※一度チュートリアルを済ますと、Webアプリが1つ出来上がってしまい、このままでは今回作るアプリがプランの制約上動きません。Heroku の Dashboard で、次のようにチュートリアルで作成したWebアプリを停止してから進めてください。

20150113-scene6


Slackのintegrationを設定

 PCのブラウザで、Slackのサービス管理画面からBotsを検索して、追加します。画面をキャプチャしたので参考にしてください。すでにBotsがインストールしているのであれば、右上のConfigureから進めみましょう。
 ところでこの管理画面のリニューアルも戦略化の一環らしいですね。他のアプリが探しやすくなったようなので、時間があるときに眺めてみてください。使えるものがすでにあるならば、それを使うのが車輪を再発明しない近道ですしね。

20160113-scene1


 指示に従って、Botに名前をつけましょう。もちろん、アイコンや First Name, Family Name なんかも決めてあげましょう。
20160113-scene2


 ところで、名前はなんでもいいですが、Botkitのインストラクションにも書いてあるとおり、やはり親しみやすい名前がいいですね。曰く、
Make it something fun and friendly, but avoid a single task specific name. Bots can do lots! Let's not pigeonhole them.
楽しげで親しみやすい名前にしようぜ。おっと、1つの仕事に限定させるような名前はダメさ。なんでかって?Botsはたくさんのことをこなすからな!後回しにしちゃダメだぜ!
 なので、しっかり名付けてあげましょう。

 名前に関しては1つ留意して欲しい点があります。後述しますが、ここで設定するBotを自分のサーバで動かす事になります。このBot用にディレクトリを作り、また、アプリケーション名として定義もします。そういう理由から、名前は、Slackとサーバの間で共通して認識できる名前(で、かつ英数字)にしておきましょう。今回私は「nano」と命名しておきます。

 そしてこのシーンでもう1つ大事なタスクがあります。設定画面中にAPI Tokenが表示されます。これはBotの起動時に必要になるものなので、どこかに記録(メモ帳などにCopy&Pasteとか)しておきましょう

 保存したならば、Slack側の設定は終わりです。


ローカル開発環境の準備

 さて、サーバ側の設定をします。自分のホームディレクトリ下などに、Bot用のディレクトリを作ります。先に書いたように、Slackで設定した名前と同じものを使うのが吉です。Slackで「nano」と命名したので、ここでもディレクトリ名を「nano」とします。

 なお、以降のコマンド実行は全てこのnanoディレクトリ下で行います。

Node.js環境の設定

 nanoディレクトリの下に、Node.jsの環境を作ります。

$ cd     # 今回は自分のホームディレクトリ直下に作成するとする
$ mkdir nano
$ cd nano
$ npm init    # 質問に適宜答える(無回答可)

これで package.json ファイルが作られます。さらにこのpackage.jsonを編集して、手元のNode.jsのバージョンを記入しておいてください。Herokuはこのバージョン情報を元に、Heroku内で該当バージョンのNode.jsを動かします(※)。私の場合は4.2.4でしたので、これを指し示します。

※要素の末尾に足す場合は、前の要素の後ろに","を足すのを忘れずに! ついつい忘れがちかつ見つかりにくいミスですね、これ。

$ node --version
v4.2.4
$ vi package.json

{
  ...(snipped)...
  "author": "Hakase Shinonome",
  "license": "ISC",
  "engines": {
    "node": "4.2.4"
  }
}

Botkitのインストール

 先ほど作ったディレクトリに、Botkitをインストールしましょう。Botkitのインストラクションを読みながら進めます。といっても、コマンド1つですけどね。はぁ、便利な世の中になった。

$ npm install --save botkit    # --save オプションをつけると、モジュールのバージョンがpackage.jsonに付記される。

 node_modulesディレクトリの下にBotkitがインストールされます。Botkitのディレクトリの中にサンプルのデモ用Botプログラムがあるので、今回は手始めにこのプログラムを動かしてみましょう。

Procfileの作成とローカルでのテスト

 Herokuはアプリケーションのルートディレクトリ(ここではnanoディレクトリ直下にあたる)のProfileを参照して、アプリケーションを起動させます。
 一方Botkitですが、インストラクションにあるように、

 token=REPLACE_THIS_WITH_YOUR_TOKEN node bot.js     

と実行することでデモ用のアプリが立ちあがります。実際にはデモはnode_modules/botkit/examples下にあるので、これをルートディレクトリにコピーし、この起動コマンドをProcfileに記述します。今回は"web"ではなく、バックグラウンド稼働型のBotなので"worker"になりますので、プロセスの種類も"worker"とします。

$ cp node_modules/botkit/examples/demo_bot.js ./bot.js
$ echo 'worker: token=YOUR_TOKEN node bot.js' > Procfile

YOUR_TOKENは、SlackのBot設定画面でところでメモしたAPI Tokeに置き換えます。
なお、このデモプログラムなのですが、コピーしたためディレクトリの親子関係が変わり、requireのパスが適切ではなくなりました。なので修正します。

$ vi bot.js

// var Botkit = require('../lib/Botkit.js');
var Botkit = require('botkit');

 ここまで作れば、(適切な通信環境があれば)ローカル環境でテストで動かすことができます。試してみましょう。

$ node bot.js

 エラーが出ずに起動していますか? nano に挨拶をすることで返事をしてくれますので、試してみましょう。
20160113-scene3

Herokuへデプロイ

 ローカルの準備はほぼできました。このデモプログラムをHerokuサービス環境で動かしてみましょう。
 もうちょっとでゴールです!

gitの環境設定

 Herokuのサービス環境へのプログラム転送には、gitのPUSH命令を使います。gitでPUSHする前に、ローカルのgitの環境とHeroku側のgit環境との関連付けなどを行わなくてはなりません。まずは、.gitignoreファイルを作ります(※)。

※Herokuではnode_modulesディレクトリをリモートリポジトリ下(Herokuサービス下)に置くことは推奨していません。Heroku環境の必要なモジュールは、Herokuが用意します。

$ cat <<'EOF' > .gitignore
> /node_modules
> npm-debug.log
> .DS_Store
> /*.env
> EOF

 次に、このnanoディレクトリをgitリポジトリ化して、ファイルをcommitしておきます。

$ git init
$ git add .
$ git commit -m "First Commiting"
[master (root-commit) 36249e9] First Commiting
3 files changed, 22 insertions(+)
...(snipped)...

Heroku環境の設定

 続けて、Heroku環境設定を行います。ログインしていない場合はログインしてから進めましょう。

$ heroku login    # ログインしていない場合
Enter your Heroku credentials.
(...snipped...)

$ heroku create
Creating xxxxx-yyyyy-nnnn... done, stack is cedar-14
https://xxxxx-yyyyy-nnnn.herokuapp.com/ | https://git.heroku.com/xxxxx-yyyyy-nnnn.git
Git remote heroku added

 これで、ローカルの環境と(リモートの)Heroku側が関連付けられ、両者の環境が整いました。

Heroku環境へデプロイ

 デプロイしてみましょう。

$ git push heroku master
Counting objects: 5, done.
Compressing objects: 100% (4/4), done.
...(snipped)...
remote: Verifying deploy.... done.
To https://git.heroku.com/xxxxx-yyyyy-nnnn.git
* [new branch] master -> master

Verifying deploy が完了と出てますね。とりあえずデプロイ成功のようです。

Workerを動かす

 webのプロセスタイプの場合、デプロイすると自動的にプロセスが立ちあがるのですが、workerの場合、そうではないようです(2016/1/13時点)。
 HerokuのDashbordで、次のように当該workerを明示的に起動(ON)してあげてください。
 
20160113-scene7


動作確認

さあ、これで全てが整いました。動いているかどうか確認してみましょう。

サーバ側

開発環境サーバ上で heroku ps コマンドを実行すると、リモートのHeroku側のプロセスを確認できます。ターミナルで確認しましょう。

$ heroku ps
=== worker (Free): token=YOUR_TOKEN node bot.js
worker.1: up 2016/01/12 22:56:19 (~ 1m ago)

プロセスが up 状態であれば、無事あなたのBotプログラムは動いています!

Slack側

Botプログラムが起動しているのであれば、Slackで応答してくれるはずです。
Slack上で、Direct MessageでこのBot、つまりnano宛に挨拶しましょう! 「Hello」か「Hi」とメッセージを送ってみてください。

20160113-scene3

そうすると、Direct Messageで、nanoから返事が返ってきます!

20160113-scene4


"Hello"
無事ゴールです、デモプログラムを使ったBotが作成できました!


おわりに

 さくっとBotkitの導入を紹介するつもりでしたが、思ってたよりHerokuの設定に説明量を割いてしまいました。とはいえその分、Herokuの導入を手軽に感じられる内容にはなったかな、とも思います。

 今回はBotkitのデモプログラムを動かしただけですので、もう少し実用的なBotに改造したいですね。また、Heroku の Free Dyno は時間制限もありつつ、workerをDashboadを使っていちいち立ち上げるのもなんだかなぁ、です。次回はそこらへんのブラッシュアップにフォーカスを当てていきましょう。

(おわり)