Raspberry PiでSlack Botことはじめ


# 概要
ビジネス向けグループツールとして最近Slackが有名ですが，家庭レベルでも色々使える話があり，Raspberry PiでSlackのBotを動かして使い心地どんなもんか，というのを試してみました．

## こういうことします
- Rasberry Pi に Node.js + Hubot でSlackのbot作成
- 発言に対して自動応答，定期的に自動発言，ができるようにする

## 環境
- Raspberry Pi 3
- OS: Raspbian 8.0
- ユーザのルートディレクトリ(`~/`)に`mybot`ディレクトリを作ってBot作成

# 手順
## 1. Node.jsの導入
Rasbianにデフォルトで入っているNode.jsはバージョンのかなり古いもの(0.x??) らしいので，下記URLを参考に新しいNode.jsを導入します．
全く同じ作業なので割愛
最終的に以下のバージョンを導入

```
pi@raspberrypi:~ $ node -v
v7.10.0
```
参考 : http://qiita.com/setouchi/items/437e4b62e4210871496f

## 2. Hubotの導入と初期設定
参考 : http://seiya-orz.hatenablog.com/entry/2016/06/25/214014
### インストール

```
$ sudo npm install -g npm
$ sudo npm install -g n
$ sudo npm install -g yo generator-hubot coffee-script
```
色々Warningが出てきましたが，ヘコタレない．

### 初期設定
Botを作っていきます．適当なディレクトリ(ユーザのルートなど)で

```
$ mkdir mybot #適当なディレクトリ名
$ cd mybot
$ yo hubot
```
ロボットっぽい絵柄が出ればOK．
Botの詳細を入力していきますが，Owner name など厳密で無くて問題なし．**Bot adaptor**のみ**slack**と入力すること．
Botの確認のため下のコマンドを実行しますが，エラーが出ました．

```
pi@raspberrypi:~/mybot $ bin/hubot
pibot> [xx xx xx 2017 15:35:53 GMT+0900 (JST)] WARNING Loading scripts from hubot-scripts.json is deprecated and will be removed in 3.0 (https://github.com/github/hubot-scripts/issues/1113) in favor of packages for each script.

Your hubot-scripts.json is empty, so you just need to remove it.
[xx xx xx 2017 15:35:54 GMT+0900 (JST)] ERROR hubot-heroku-alive included, but missing HUBOT_HEROKU_KEEPALIVE_URL. `heroku config:set HUBOT_HEROKU_KEEPALIVE_URL=$(heroku apps:info -s  | grep web-url | cut -d= -f2)`
[xx xx xx 2017 15:35:55 GMT+0900 (JST)] INFO hubot-redis-brain: Using default redis on localhost:6379
```
hubot-heroku-aliveのモジュールでエラーが出ました．Herokuというのはプラットフォームの提供サービス(PaaS)で，調べるとHeroku上で停止せず動かすためのモジュールのようです．
モジュール類の読み込みは`mybot`下の`external-scripts.json`というファイルで管理されており，その中の`hubot-heroku-alive`の記述を削除すれば上記エラーは解消できます．

最終的に`bin/hubot`起動後，`ping`を送ってPONGと返ってこれば完了ですが，`yo hubot`で詳細入力したときの**名前**(ここでの例はpibot)も入力しないと返って来ないので注意

```
$ bin/hubot
pibot> pibot ping ← 入力
pibot> PONG ← 返ってくる
```

## 3. Slack上の設定
ここではSlackの登録については省きます．
ブラウザでSlackのTeamのホーム画面を開き，下の方にある"Add applications"をクリックすると，インストールできるアプリ一覧が出てきます．
検索で "Hubot" を調べてインストール，インストール後の設定画面で`HUBOT_SLACK_TOKEN=xxxx…`という部分が表示されます．これがHubotとSlackを連携するためのアクセスコードになりますので，コピーします．(名前はpibotとします)
ラズパイに戻り，`bin/hubot`にこのコードを入力していきます．

```
$ nano bin/hubot
export HUBOT_SLACK_TOKEN=xxx… ← 追記．xxxの部分はSlack画面で出ていた通りに
```
以下のコマンドで起動し，Slackの"pibot"というアカウントがオンラインになっていれば成功です．

```
$ bin/hubot -a slack
```
ダイレクトメッセージで"ping"と入力して"PONG"と返ってこればOKです．

## 4. バックグラウンド起動化
上の方法で起動するとターミナルを占有してしまい，SSH接続でやっていたら接続を切ったときに停止してしまいます．
foreverを使ってバックグラウンド起動 & 自動再起動化します
参考 : http://qiita.com/KeitaMoromizato/items/d9130b3f6c04292c129d

```
$ sudo npm install -g forever
```
インストール後，`bin/hubot`を編集し，`exec~`の行をコメントアウト，`forever`の行を追記します．

```
forever start -c coffee node_modules/.bin/hubot -a slack
# exec node_modules/.bin/hubot "$@"
```
`bin/hubot`を実行することで，バックグラウンド起動するはずです．
※ サーバ起動時の自動起動は上記URLに書いていますが導入していないので割愛．基本はinit.dディレクトリに導入で問題ないかと

### 確認と停止
`forever list`で確認．

```
$ forever list
info:    Forever processes running
data:        uid  command script                           forever pid   id logfile                    uptime         
data:    [0] xxxx coffee  node_modules/.bin/hubot -a slack 31547   23217    /home/pi/.forever/xxxx.log 0:21:39:14.421
※ xxxxの部分は起動毎に変化
```
このときに表示されるログファイルでエラー情報など分かります．スクリプト作成・変更でうまく動かないときは，`tail -f /home/pi/.forever/xxxx.log`などでエラーを見ながらSlackでメッセージを送ったりするといいのでは．

停止は以下のコマンド（mybot/ディレクトリ下じゃないとダメ？）

```
$ forever stop node_modules/.bin/hubot
```

## 5. スクリプト作成
`scripts`フォルダに入っている JavaScript, CoffeeScriptが読み込まれ，Botの動作に使われます．
書き方は以下のURLを参考に

- CoffeeScriptの文法→ http://qiita.com/moriyaman/items/0da99254f110155954d3
- Hubotスクリプトの書き方→ http://blog.fumiz.me/2012/08/05/hubot-irc-bot-script/

### 基本的な書き方

``` ex.coffee
# ここにモジュール読み込みや変数定義を
hogehoge = require('hoge')

# module.exportsに代入する関数に各処理をインデント付きで書いていく．
module.exports = (robot) ->
  # respond: "mybot ほげ" と発言すると反応. DMなら"ほげ"でも反応することに注意
  robot.respond /ほげ/i, (msg) ->
    msg.send "ふが"
  # hear: "ふが" だけで反応．
  robot.hear /ふが (.*)/i, (msg) ->
    msg.send "ほげ#{msg.match[1]}"
  # //内は正規表現． ""内に#{変数名}で文字列に含められる
```

### 定期的に発言させる(node-cron)
Node.jsのモジュール"node-cron"を使います

```
$ sudo npm install cron
```

``` cron-ex.coffee
cron = require('cron').cronJob

module.exports = (robot) ->
  # 時間書式はlinuxのcronと同じ．
  new cron '0 0 20 * * *', () ->
    # ここに処理を記述
  , null, true, "Asia/Tokyo"
```

## 問題点

- cron使用時，編集してHubot再読込されたときにcronが何故か一度実行されてしまいます… なぜ？