Slack 特化 Bot フレームワーク「Shrike」

[Slack Advent Calendar 2016 - Qiita](http://qiita.com/advent-calendar/2016/slack) の10日目です。

「Slack でサクッと Bot を動かしたい・・・」というときに便利な [Shrike](https://github.com/hoto17296/shrike) という Bot フレームワークを紹介します。**まぁ僕が作ったんですが。**

# Shrike とは
超シンプルであることを目指した Slack 用 Bot フレームワークです。
「しゅらいく」と読みます。字面がなんとなく Slack に似ているというだけの雑な命名理由。

## 家庭用/チーム用 Slack の Bot として最適
[Microsoft Bot Framework](https://dev.botframework.com/) のような Bot フレームワークはビジネス用の Bot 開発用途として作られています。
Facebook Messenger や LINE で動かす Bot を開発するのには最適なのですが、家庭内やチーム内の Slack だけで動かす Bot を作るにしては手軽さに欠けています。家庭用/チーム用であればクロスプラットフォームな機能は必要ないどころか、Slack 特有の API などが利用しづらいというデメリットがあります。

**Slack でしか使わないなら Slack 専用の Bot フレームワークがあったほうがいいじゃん** という趣旨でこの Shrike は作られています。

## Hubot はそろそろやめたい
「じゃあ Hubot でいいじゃん」と思うかもしれません。
実際、我が家の Bot もこの Shrike を作る前は Hubot で開発していました。

しかし Hubot には以下のような思うところがあり、Hubot 以外の良いフレームワークを探したものの見つからなかったので自分で作ることにしました。

- Hubot はここ最近開発が止まっている
- CoffeeScript を捨てたい
    - Hubot のコアからエコシステムに至るまで CoffeeScript が利用されている
    - Bot そのものは普通の JavaScript で書くことはできるものの、なんかヤダ
- Slack 特有の API が使いづらい
    - Attachment を添付する場合に `emit` を使わなきゃいけなくてキモい、など

ちなみに Botkit についても諸事情あり「アレはちょっと使いたくない・・・」という感じです。

# Shrike の思想/哲学
## Hubot ライク
Hubot については色々思うところはありましたが、あのメッセージングのインタフェースは手軽に書けて素晴らしいと思っていました。

`bot.respond()` `bot.hear()` `msg.send()` `msg.reply()` など、Shrike のメッセージング API は Hubot が書いたことがあればすぐに慣れることができるようになっています。

## コアはメッセージング機能のみ
Hubot を使うとデフォルトで色々な機能が乗りすぎていました。

Shrike では hubot-brain や hubot-router に相当する機能はコアには含まれていません。データストレージを利用したい場合は [shrike-utils](https://github.com/hoto17296/shrike-utils) というパッケージに含まれる RedisStorage を利用します。また、HTTP エンドポイントが欲しければ自分で Express アプリケーションを作成して Bot に追加するだけです。

切り出せる機能は徹底的に外に切り出すことで、コアが「メッセージを受け取って、メッセージを送る」に注力するシンプルな形になっています。

## ES2015 ネイティブ
最近の JavaScript ライブラリでも Node.js v0.10 までサポートしているものは少なくないですが、**Shrike は Node.js v6 以降しかサポートしていません。**

Bot フレームワークというのは特殊で、既存の Node プロダクトに組み込んで使うことはほぼ無いし、ブラウザ上で動作させることもないため、古いバージョンの JavaScript をサポートする必要はないという判断です。

# とりあえず動かしてみる
Shrike を簡単に試せる [shrike-boilerplate](https://github.com/hoto17296/shrike-boilerplate) というのを作ったのでそれを使っていきます。

先にも説明しましたが **Node.js のバージョンは v6 以上**である必要があります。

## Boilerplate を Clone する
clone してきて依存パッケージをインストールします。

```
$ git clone https://github.com/hoto17296/shrike-boilerplate.git mybot
$ cd mybot
```

```
$ npm install
```

## 環境変数を設定する
プロジェクトルートに `.env` という名前のファイルを作成して環境変数を記述します。

``` :.env
SLACK_TOKEN='xoxb-000000000000-xxxxxxxxxxxxxxxxxxxxxxxx'
SLACK_DEFAULT_CHANNEL='dev-bot'
PORT=3000
```

以下、それぞれの環境変数について簡単に解説します。

### `SLACK_TOKEN` (Required)
最低限この環境変数だけは設定する必要があります。

[Slack の Bots Integration](https://slack.com/apps/A0F7YS25R-bots) で Bot ユーザを作成するとトークン文字列が得られるので、それを設定しましょう。

### `SLACK_DEFAULT_CHANNEL`
Bot からのメッセージを送信時にチャンネル名を指定しなかった場合、このチャンネルにメッセージが送信されます。

この環境変数を設定していなければ `general` がデフォルトチャンネルになります。[^general]

[^general]: 正確には `is_general` フラグが立っているチャンネル

### `PORT`
Express を使って HTTP を Listen する場合は必要です。

Boilerplate の `bot.js` を読んでもらえればわかりますが、この環境変数は Shrike 本体とは無関係です。
別に `PORT` 以外の名前に変えても特に問題ないですが、Heroku の Web Dyno で動かす場合、Heroku 側から `PORT` という環境変数が渡されてきてその PORT で Listen しなければならないという仕様になっているので注意が必要です。

## 起動させる
```
$ npm start
```

これで node-foreman が `.env` と `Procfile` を読み込んで `bot.js` を実行してくれます。

Hubot と違ってコンソールのインタフェースは無いので Slack から動作確認をしてみます。

![](https://qiita-image-store.s3.amazonaws.com/0/16369/b37aaf90-95a4-77ac-642f-65402a4715ba.png)

ちなみに、開発用と本番用でふたつ Bot ユーザを作っておくと便利です。

## 開発する
`scripts/` 以下の JavaScript ファイルを追加することで機能開発ができます。このへんはだいたい Hubot と同じです。
Boilerplate の [scripts/example.js](https://github.com/hoto17296/shrike-boilerplate/blob/master/scripts/example.js) を見るとわかりやすいです。

## デプロイする
Heroku で動かすと簡単です。

Heroku の詳しい使い方は割愛しますが、`.env` に書いていた環境変数を Heroku の `Config Variables` に設定して、あとはそのまま push するだけで動きます。

また、RedisStorage を使う場合は Add-ons で [Heroku Redis](https://elements.heroku.com/addons/heroku-redis) を追加しましょう。追加すると `REDIS_URL` という環境変数が自動で設定されます。

# 機能を開発するのに参考になりそうな例
我が家の Bot はこの Shrike で開発しています。
だいぶ色々な機能があるので参考になるかと思います。

https://github.com/hotogoma/tsukiko2

# 今後やっていきたいこと
Shrike 自体はだいたい作りきったのだけど、周辺のもろもろがまだ何もできておらず・・・(本当はこの Advent Calendar に間に合わせたかった)

- ちゃんとしたドキュメントを書く
- [express-generator](https://www.npmjs.com/package/express-generator) みたいなジェネレータを作る
- テストを書きやすくするヘルパーツールを作る

もし！ Contribute してくれる人がいたら！！超うれしいです！！！