Hubotを使ってSlackへBotを投げる


# 使うもの

- Heroku
- Hubot
- Slack

## 各々の役割

### Heroku
サーバー

### Hubot
https://hubot.github.com/
Node.js製のbotを作成＆動かすフレームワーク。
GitHub社が開発したもので、様々なチャットツールに使えるのが特徴。


### Slack

チャットツール

# 作り方

1. Hubotを使う準備
2. Hubotを起動してみる
3. Slackと連携する
4. ディレクトリをGit管理する
5. Herokuへデプロイ
6. Hubotが寝てしまわないようにする
7. 時報を流すようにする

## 1. Hubotを使う準備
ドキュメントに従って進めていく。
https://hubot.github.com/docs/

### Node.jsが入っているかを確認する

```
node -v
```

入ってなければ https://nodejs.org/ja/ からインストールかな？

### Hubotジェネレーターをインストール

フロントエンドでよく使う環境構築をコマンド1つでサクッと作ってくれるツールYeoman。
http://yeoman.io/learning/

これを使って、Hubotジェネレーターをインストールする。

```
npm install -g yo generator-hubot
```

### ディレクトリ＆Hubotの作成

```
mkdir myhubot
cd myhubot
yo hubot
```

匿名でのレポート報告に答えて、

![Screen Shot 2018-01-05 at 15.58.01.png](https://qiita-image-store.s3.amazonaws.com/0/109241/1f732727-de1e-7a32-41ff-99adb2580e42.png "Screen Shot 2018-01-05 at 15.58.01.png")

Hubotに関する情報を入力。

![Screen Shot 2018-01-05 at 16.40.56.png](https://qiita-image-store.s3.amazonaws.com/0/109241/a63eb834-08cf-e89d-8b99-c9b70d978bf2.png "Screen Shot 2018-01-05 at 16.40.56.png")

OwnerはEnterでOK、nameとdescriptionは適当に。
Adapterでチャットツールを指定するのでslackとする。
https://hubot.github.com/docs/adapters/


![Screen Shot 2018-01-05 at 16.45.02.png](https://qiita-image-store.s3.amazonaws.com/0/109241/0f4c2f2d-e74c-93a6-20d9-f28d625214bc.png "Screen Shot 2018-01-05 at 16.45.02.png")

できた。

## 2. Hubotを起動してみる

```
bin/hubot
```

と打つと、

![Screen Shot 2018-01-05 at 18.08.39.png](https://qiita-image-store.s3.amazonaws.com/0/109241/282ab329-1317-82d4-60a2-ecdf46ca1b5a.png "Screen Shot 2018-01-05 at 18.08.39.png")

こんなエラーがでる。
jsonファイルを削除しろ、coffee-scriptがインストールされていない、などと言われる。
ここのエラーに惑わされてファイルを削除したりしたらうまくいかなくなったので、無視してEnterを押していく。

```
myhubot>
```

と出てくるので、ここでpingと呼びかけたり、helpを見てみたり、試してみる。

![Screen Shot 2018-01-06 at 17.05.44.png](https://qiita-image-store.s3.amazonaws.com/0/109241/0efcff2a-ada9-d11b-9a33-597af26cf2fb.png "Screen Shot 2018-01-06 at 17.05.44.png")

でるときはexit。

### Hubotの名前は *case-insensitive*

Hubotの名前は大文字・小文字を区別しないので以下でもOK。

```
MYHUBOT help
myhubot help
@myhubot help
myhubot: help
```

## 3. Slackと連携する

とりあえずローカルでSlackと連携できるようにする。

### SlackにHubotのAppを追加

https://slack.com/apps で検索して、名前をつけて追加するとトークンが見れる。

### adapterをslackに設定＆トークンを投げてHubotを起動

https://slackapi.github.io/hubot-slack/#running-hubot

```
HUBOT_SLACK_TOKEN=xoxb-YOUR-TOKEN-HERE ./bin/hubot --adapter slack
```

SlackのAppsにHubotが現れ、

![Screen Shot 2018-01-06 at 17.39.02.png](https://qiita-image-store.s3.amazonaws.com/0/109241/ad65e6b5-0e98-49c2-68d0-c64476a6a92b.png "Screen Shot 2018-01-06 at 17.39.02.png")

ここでHubotを起動できるようになった。

![Screen Shot 2018-01-06 at 17.40.00.png](https://qiita-image-store.s3.amazonaws.com/0/109241/0b3b02d5-7e4b-b164-1329-5f9b5e9d4c23.png "Screen Shot 2018-01-06 at 17.40.00.png")

### 特定のチャンネルで起動したい場合

話したいチャンネル内で

```
/invite @shosho_hubot
```

と招待する。
この場合、はなしかけるときは `@` でメンションを飛ばすこと。

![Screen Shot 2018-01-06 at 17.49.26.png](https://qiita-image-store.s3.amazonaws.com/0/109241/9932e57f-381b-e5bb-303c-9a0545f40b35.png "Screen Shot 2018-01-06 at 17.49.26.png")


## 4. ディレクトリをGit管理する

Git管理の方法については割愛。

### .ideaディレクトリについて

`.idea/workspace.xml` はエディタの並び順などの情報を持っているらしい。
http://gihyo.jp/dev/serial/01/android_studio/0035
バージョン管理すると毎回コミットしなければならないのでignoreする。

```.gitignore
node_modules
.DS_Store*
.hubot_history
/.idea/workspace.xml
```

## 5. Herokuへデプロイ

https://slackapi.github.io/hubot-slack/

主にやることとしては

- Herokuのアカウント登録
- ターミナルからログイン
- Hubot用のアプリケーション作成
- アプリケーションのconfigの値を設定 ★
- heroku push ★

アカウント登録〜アプリケーションまではドキュメントを見れば大体わかるので割愛。

### configの設定

SlackのトークンをHerokuのConfig Variablesに設定。

```Herokuのconfigに設定
HUBOT_SLACK_TOKEN=xoxb-YOUR-TOKEN-HERE
```

### heroku push

`package.json` のnode&npmのバージョンで引っかかっていたっぽいので

```package.json
  "engines": {
    "node": "0.10.x",
  }
```

```エラーメッセージ
remote: -----> Installing binaries
remote:        engines.node (package.json):  0.10.x
remote:        engines.npm (package.json):   unspecified (use default)
remote:        
remote:        Resolving node version 0.10.x...
remote:        Downloading and installing node 0.10.48...
remote:        Detected package-lock.json: defaulting npm to version 5.x.x
remote:        Bootstrapping npm 5.x.x (replacing 2.15.1)...
remote: 
remote: /tmp/build_3e00b1468764ab785def2846f66385a9/.heroku/node/lib/node_modules/npm/lib/utils/unsupported.js:28
remote:         console.error(`a bug known to break npm. Please update to at least ${r
remote:                       ^
remote: SyntaxError: Unexpected token ILLEGAL
remote:     at Module._compile (module.js:439:25)
```

ひとまず手元のバージョンに合わせて `package.json` を修正。
https://qiita.com/tmkt/items/4e6aaac0711da937384a

```package.json（修正後）
  "engines": {
    "node": "9.2.1",
    "npm": "5.5.1"
  }
```

pushが完了し、Herokuにデプロイされた。

![Screen Shot 2018-01-06 at 19.17.10.png](https://qiita-image-store.s3.amazonaws.com/0/109241/6e8c0812-0fc0-c9cc-133d-87b21fedfd96.png "Screen Shot 2018-01-06 at 19.17.10.png")

## 6. Hubotが寝てしまわないようにする

Herokuへデプロイした次の日、Hubotに話しかけても返事が返ってこなくなっていた。
https://blog.heroku.com/new-dyno-types-public-beta#hobby-and-free-dynos
Herokuはフリープランだと、最大18時間しか起動させておくことができないそうで、寝てしまったらしい。

なので、使うことがなさそうな深夜等に6時間以上眠らせ、朝になったら起こすように設定する。

### hubot-heroku-keepaliveの設定

起床時間・就寝時間の設定を行う。
https://github.com/hubot-scripts/hubot-heroku-keepalive
以下の4つをHerokuのConfig Variablesに設定。

```Herokuのconfigに設定
HUBOT_HEROKU_WAKEUP_TIME=9:00
HUBOT_HEROKU_SLEEP_TIME=24:00
TZ='Asia/Tokyo'
HUBOT_HEROKU_KEEPALIVE_URL='https://hogehoge.herokuapp.com/'
```

Herokuの管理画面から設定するときに `'Asia/Tokyo'` としていたせいで日本標準時になっていなかったので `Asia/Tokyo` となるように注意する。

### Heroku Schedularの設定

起床時間の設定はできたが、起こしてあげる目覚まし的なものが必要らしい。
Heroku Schedularというアドオンを使う。

https://github.com/hubot-scripts/hubot-heroku-keepalive#waking-hubot-up
クレジットカードの登録をしたら、アドオンを追加。
Curlコマンド、次回実行時間の設定（JSTをUTCに変換）などしたらOK。

## 7. 時報を流すようにする

正時に時報を流すようにする。

### モジュールのインストール
https://www.npmjs.com/package/cron
https://www.npmjs.com/package/time

```
$ npm install cron --save
$ npm install time --save
```

### スクリプトを書く

`scripts`ディレクトリ下にファイルを作成。

```js:timesignal.coffee
cronJob = require('cron').CronJob

module.exports = (robot) ->

    cronjob = new cronJob(
      cronTime: "0 0 * * * *"    # 実行する時間
      start:    true                # すぐにcronのjobを実行するかどうか
      timeZone: "Asia/Tokyo"        # タイムゾーン
      onTick: ->                    # 実行処理
        robot.send {room: "#myhubot"}, "正時です"
    )
```

#### 「〜時になりました〜！」と言わせる

```
cronJob = require('cron').CronJob
time = require('time')

module.exports = (robot) ->

    cronjob = new cronJob(
      cronTime: "0 0 * * * *"    # 実行する時間
      start:    true                # すぐにcronのjobを実行するかどうか
      timeZone: "Asia/Tokyo"        # タイムゾーン
      onTick: ->                    # 実行処理
        now = new time.Date()
        robot.send {room: "#myhubot"}, now.getHours()+"時"+now.getMinutes()+"分になりました〜！"
    )
```


# 参考
https://qiita.com/kon_yu/items/57fb169cb871a009393b
https://qiita.com/mochidamochiko/items/29c2d77715d8a1ff062a
https://qiita.com/susuwatarin/items/019e0e701754161f7c4c
https://qiita.com/susuwatarin/items/aade8301b93e175d3ff8