Node.jsでslackのbotを作ってEC2上でデーモン化するまで

Web開発用にチームでSlackを使うことになった。
今後はChatOps的な使い方をしてデプロイや監視との連携なんかをしていきたいんだけども
まず始めは bot を使い倒してチーム内のコミュニケーションをうまくできないかなぁと思って始めてみた。

# botの準備
## Slack Botsを設定する
SlackのApps&integrationsメニューから、Manageを選択
<img width="1439" alt="スクリーンショット 2017-06-03 17.26.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/163591/2019db25-7ab5-0bdc-a39f-2715c5ce6878.png">

Custom Integrationsの項目を開くとBotsがあるので選択

<img width="1440" alt="スクリーンショット 2017-06-03 17.29.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/163591/97ab8953-5daf-efeb-367b-c946821fbdb1.png">

Add Configurationを選択し、Botの名前（@username）を入力して Add bot integration

<img width="1440" alt="スクリーンショット 2017-06-03 17.29.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/163591/f4ebb989-f7c3-ebc9-aa2b-46d5de3492f9.png">

<img width="1440" alt="スクリーンショット 2017-06-03 17.30.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/163591/f1f2e6fb-a2df-d52a-38e6-167f6f06ce1b.png">

ここでは @username=satomiとしました。
次のページで出てくるAPIトークンは後で使用するので覚えておきましょう。
Botsのアイコンは画像をアップロードしてもいいし、絵文字を使用することもできるようです。
とりあえずここまでできればBotsの準備はOK

## 

# EC2とNode.jsの準備
最初は自前のmacにnode.jsを入れて動かしてたんだけど
macがスリープモードになったり、シャットダウンしたら当然botは動かなくなるので
しかたなくサーバを立てようかなと思っていたってのと、

AWSの無料枠があると聞いていたので使ってみようかなと思って
EC2インスタンス上にnode.jsを入れてbotが常駐できる環境を作ることにした。

## EC2インスタンスにSSHで接続
EC2インスタンスをどうやって立てるの？ってのは省略します。
ローカルPCからこんな感じで接続することになります。
```
ssh -i "XXXXXX.pem" ec2-user@XXXXXXXX.compute-1.amazonaws.com
```

## 最新のNode.jsの準備
nvm (Node Version Manager)を入れて、最新のNode.jsを使えるようにしましょう。

### 1. nvmのインストール

```
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash
```

### 2. Node.jsの最新バージョンをインストール

```
$ nvm install v5.1
```

### 3. インストールしたNode.jsの設定
インストールしたNode.jsはデフォルトver.として5.1を使うことにしておきましょう

```
$ nvm use 5.1
$ nvm alias default 5.1
```

## foreverの準備
Node.jsをバックグラウンドで動かしておくためのパッケージforeverをインストールする。

nodejsはコマンドアプリケーションのため、コンソール閉じるとアプリが終了してしまうらしい。そのため、永続的に起動するには、コンソールからnodejsを切り離す。

foreverはハンドルされていない例外が発生してプログラムが停止した場合自動で再起動やってくれる。なのでプログラムがエラーで勝手に止まっちゃう心配は無い。

これがないとSSH接続が切れた際にNode.jsも一緒に切断されてしまってbotが落ちてしまった。少しハマった。

```
$ sudo npm install -g forever
```

これでOK。

ちなみにforeverの使い方を簡単に書いておくとこんな感じ

```
// 書式
forever [options] [action] SCRIPT [script-options]

// プログラムを実行
forever start SCRIPT

// 実行中のプロセスを確認. ここで表示されるログファイルなどチェック
forever list

// プログラムを停止. プロセス番号はforever listで確認
forever stop プロセス番号

// プログラムを再起動. プロセス番号はforever listで確認
forever restart プロセス番号
```

# Node.jsでbot用のスクリプトを書いていく
ここまで準備ができたらいよいよbotを作ります。

## botの作成
botを作成しましょう。まずはnpmで初期化します。

```
$ npm init
```
usernameとか聞かれますのでいい感じに答えていってください。

botkitを使ってbotを作っていきます。
公式サイト：　https://www.botkit.ai/

```
$ npm install --save botkit
```

これによってnode_modulesというディレクトリができ、そのなかにbotkitディレクトリができます。
--saveオプションをつけてインストールすることで、package.jsonのdependenciesにもbotkitを追加してくれるようです。

botの中身を書いていきます。

```
$ vi index.js
```

```index.js
var Botkit = require('botkit');
var controller = Botkit.slackbot();
var bot = controller.spawn({
  token: '初めに作ったbotのAPIトークン'
}).startRTM(function(err,bot,payload) {
  // 初期処理
  if (err) {
    throw new Error('Could not connect to Slack');
  }
});
controller.hears(["hello"],["direct_message","direct_mention","mention"],function(bot,message) {
  // キーワードに反応した処理
  bot.reply(message, 'hello! I am bot!!');
});<img width="238" alt="スクリーンショット 2017-06-03 18.18.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/163591/49a475d1-d60b-9b84-2a14-83e76837483c.png">

```

## botの起動

```
$ forever start -l app.log -a index.js
```

このようにしておくとapp.logにログを吐いてくれるので便利ですね。
念のためforever listで確認しておきましょう。

```
$ forever list
info:    Forever processes running
data:        uid  command                                           script   forever pid   id logfile                         uptime       
data:    [0] Kpda /home/ec2-user/.nvm/versions/node/v5.1.1/bin/node index.js 27318   27323    /home/ec2-user/.forever/app.log 0:1:3:57.891 
```

正常にrunnningしているようです。
やっと完成。あとはbotに話しかけてみましょう。

<img width="238" alt="スクリーンショット 2017-06-03 18.18.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/163591/2d34dc16-e44c-289b-aa39-bab586208980.png">

上手くできてますね。