Slackのコマンドを作ろう！！

サァアドベントカレンダーの12日目です！！！

機会はやってきた（[前回の続き](http://qiita.com/t-mimura/items/cccf79f541218690ed4e#%E3%81%9D%E3%81%97%E3%81%A6%E6%8A%80%E8%A1%93%E3%83%8D%E3%82%BF%E3%81%B8)）、しかし、Botではなく今回はコマンドを作ってみようと思います。

コマンド(slash command というらしい）もBotKitで作成できます。しかも、簡単に。そうBotKitならね。

# コマンド？

slack で `/` から始まる特定の文字を入れると何かが起こるアレです。
たとえば、よく使うのは `/remind` でしょうか。

```
/remind me Meeting of something at 11:00
```

とすれば、11時に "何か打ち合わせあるよ" と教えてくれます。

デフォルトでSlackにはいくつかコマンドが用意されていますが、カスタムのコマンドを作成することもできます。

# 何を作ろうか？

今回は、「個人用のチャンネル」で分報の利用を加速させるべく、今何をしているのかを積極的に宣言したくなる感じのコマンドを作っていこうと思います。
理想としては以下の機能を妄想します。

- いい感じのフォーマットにしてくれる
- 今日の仕事終わり！と宣言すると、その時までにやっていた仕事の合計時間と割合を表示する
- これから○○する！！と宣言したときに予定の時間をいれることもできる。その場合、時間になったら教えてくれる。

まずは、
`/times slack のtimesコマンド作成`
と打ち込むと、
`⏰ 「slack のtimesコマンド作成」やるぞー！`
と該当のチャンネルに投稿されるコマンドから始めたいと思います。

# 何が必要？

- https な環境

slack の slash command はHTTPSが求められるようです。
今回はHTTPSの環境がすでにあったので、そこからBotKitへリバースプロキシする形で作成したいと思います。
HTTPSの環境がない人は次の項で紹介している方法で作成するか、または、軽く手元で試すだけであれば [rgrok](https://ngrok.com/) のようなサービスを使うのも有りかも知れません。
（´-`）.｡oO（heroku・・・）

# 環境作成
（今回の記事はBotKitのところメインなので、この項目はトピックをあげるだけにします。ここはステマです。）
（2016/12/13：追記） [こちら](http://qiita.com/t-mimura/items/50fa0b6bc05884fd6f0c)に補足しました。

1. VPS 契約します
    - http://vps.sakura.ad.jp/
    - 諸々のセキュリティ対策をお願いします
1. ドメイン登録します
    - http://www.sakura.ne.jp/domain/
    - 私はたまたま手元に持っているドメインがあったのでそれを使います
1. SSL証明書を作ります
    - https://ssl.sakura.ad.jp/
1. VPSでリバプロできるWebServer（nginxなど）を起動します。

# ようやくコマンドを作る

大きな流れとしては次のようになります。

1. アプリケーションを登録する。
2. アプリケーションを実装する。
3. アプリケーションを動かす。
4. チームにアプリケーションを追加する。

# アプリケーションを登録する

[こちらのページ](https://api.slack.com/apps)からアプリケーションを登録します。
`Create an App` を押してください。

![スクリーンショット 2016-12-05 19.32.45.png](https://qiita-image-store.s3.amazonaws.com/0/83996/a9193147-de48-420b-93d7-00df881c49c8.png)

アプリケーションの名前を入れて `Create App` を押してください。

![スクリーンショット_2016-12-05_19_43_36.png](https://qiita-image-store.s3.amazonaws.com/0/83996/272179df-4376-62e0-d4d2-f0350b9c4d7d.png)

いま `Basic Information` にいると思いますが、適当に `Display Information` を記入して下さい。また、スクリーンショットは撮っていませんが `App Credentials` に表示されている `Client ID` と `Client Secret` をBotKit起動時に利用します。（後でまたこのページから参照できます。）

![スクリーンショット 2016-12-05 19.52.05.png](https://qiita-image-store.s3.amazonaws.com/0/83996/534d5120-8031-9849-17a8-d46a60545b96.png)![スクリーンショット 2016-12-05 21.22.58.png](https://qiita-image-store.s3.amazonaws.com/0/83996/d4e11f5b-05df-2620-87b7-1fc5fc603dd0.png)

`OAuth & Permissions` で `Redirect URL(s)` を設定します。これは BotKit を利用すると `/oauth` というパスで受け付けてくれるように動作するので、各自のリバプロの設定を勘案して設定をお願いします。

![スクリーンショット 2016-12-05 19.55.38.png](https://qiita-image-store.s3.amazonaws.com/0/83996/b5be2eb4-e613-5f5e-f900-379da7447323.png)![スクリーンショット 2016-12-05 19.53.27.png](https://qiita-image-store.s3.amazonaws.com/0/83996/809648a4-7cac-a605-c6ce-eac5e3ac85be.png)

最後に `Slash Commands` を追加します。

![スクリーンショット 2016-12-05 19.55.46.png](https://qiita-image-store.s3.amazonaws.com/0/83996/a6637ee9-36e2-80b2-716e-0059864d76c2.png)

`Request Url` は BotKit を使うと `/slack/receive` というパスで受け付けてくれます。

![スクリーンショット 2016-12-06 19.58.11.png](https://qiita-image-store.s3.amazonaws.com/0/83996/6b790c98-a652-8143-f23f-189b3ba33cfb.png)


# アプリケーションを実装します

[Node.js](https://nodejs.org/ja/)の設定と[BotKit](https://github.com/howdyai/botkit)の導入をします。

ここではバージョン管理の仕組みとして `ndenv` を使っていますが、お好みの方法で大丈夫です。またはバージョン管理せず直接Node.jsを入れてもいいかもしれません。今回はこの記事を書いている時点（2016/12/05)のLTSバージョンである `v6.9.1` を使います。（Node.jsのインストール方法はここで省略します）

```bash
$ ndenv local v6.9.1
$ npm init --yes
$ npm install --save botkit
```

ソースコードは次の通りです。

```javascript:index.js
const botkit = require('botkit');
const secrets = require('./.times/.secrets.json');
const env = {
  port: 3000,
  json_file_store_path: './.times/.json_file_store/'
};

const controller = botkit.slackbot({
  debug: false,
  json_file_store: env.json_file_store_path
}).configureSlackApp({
  clientId: secrets.clientId,
  clientSecret: secrets.clientSecret,
  scopes: ['commands']
});

controller.setupWebserver(env.port, (err, webserver) => {
  controller
    .createOauthEndpoints(controller.webserver, (err, req, res) => {
      if (err) {
        res.status(500).send('Error: ' + JSON.stringify(err));
      } else {
        res.send('Success');
      }
    })
    .createWebhookEndpoints(controller.webserver);
});

controller.on('slash_command', (bot, message) => {
  // message.command === '/times'
  bot.replyPublic(message, `⏰ 「${message.text}」やるぞー！`);
});
```

まず、前述した `Client ID` と `Client Secret` ですが、外部ファイルで分離しています。（これはコミット対象外）下記のようにJSONファイルを作って下さい。

```json:./.times/.secret.json
{
  "clientId": "111111.111111",
  "clientSecret": "xxxxxxxxxxxx"
}
```

また、slackbot を生成する際に `json_file_store` を指定していますが、これがないとチームへ追加したときの `access_token` を覚えてくれないので、BotKitのプロセスを再起動した後にリクエストに応えられなくなります。

細かい解説をすると大変なのでしません。(てへぺろ)
BotKitの `configureSlackApp` の資料は[ここ](https://github.com/howdyai/botkit/blob/master/readme-slack.md#controllerconfigureslackapp)です。
そこに渡している `scopes` の資料は[ここ](https://api.slack.com/docs/oauth-scopes)です。
BotKitの slash command に関する記述は[このへん](https://github.com/howdyai/botkit/blob/master/readme-slack.md#outgoing-webhooks-and-slash-commands)にあります。
createOauthEndpoints に関する記述は[このへん](https://github.com/howdyai/botkit/blob/master/readme-slack.md#controllercreateoauthendpoints)ですが、まるっと BotKitがやってくれるので OAuthの仕組みを意識することはなかったです。

最後の `slash_command` のところ以外はほぼ定型です。肝心なのは最後のところです。

```javascript
controller.on('slash_command', (bot, message) => {
  // message.command === '/times'
  bot.replyPublic(message, `⏰ 「${message.text}」やるぞー！`);
});
```

ここでコマンドに対する処理を行います。
今回は、コマンドの種類はひとつなので、処理は入れていませんが、`message` オブジェクトの `command` に実行されたコマンド文字列が入っているので、複数コマンドを登録した場合はここで切り分けができます。
また、返信に `replyPubic` を使っていますが、 `replyPrivate` を使うと本人にしか見えない発言にすることができます。

# アプリケーションを動かす

```bash
$ node index.js
```

# チームにアプリケーションを追加する

[こちら](https://api.slack.com/docs/slack-button)のページの `Add the Slack button` にてリンクが生成可能です。

![スクリーンショット 2016-12-06 21.22.05.png](https://qiita-image-store.s3.amazonaws.com/0/83996/1993d3ee-d2f4-686f-ad2e-5091587c7490.png)

上記のスクリーンショットで説明すると、右上のドロップダウンで対象のアプリケーションを選びます。
また、その下のチェックボックスで `scope` を選びます。（今回はコマンドの作成をしたので `commands` にチェックを入れて下さい。）

その状態で左側にでている `Add to Slack` のリンクから遷移するとアプリケーションをチームに追加するページへ遷移します。
（あとは、言われるままに追加してください！！）

# さあ、やってみよう！！

早速試してみましょう。動きましたでしょうか？？？？
（アイコンをあててみました。弊社デザイナー作です。🙏）

<img width="335" alt="記事を書く.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/83996/d9d54d82-7a44-5153-43cc-f358d20eabb2.png">


# まとめ

当初の予定ではもっと機能がありましたが、記事が長くなってきたので今回は一旦これで終わりたいと思います。
工夫次第でSlackをもっと便利にするツールがつくれそうですので、みなさまご活用くださいませー。

(今回実装したソースコードは[こちら](https://github.com/t-mimura/slack-command-times/tree/1.0.0)にあります)

# おまけ

アドベントカレンダーなのでクリスマスに絡めろという謎の声がありましたので、クリスマスまでの日数をカウントするコマンドを作りました。みなさま、良いクリスマスを！！！ 🎄🎅

<img width="348" alt="あと19日.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/83996/9472489c-1d96-a5db-3b66-b968509ea076.png">


（記事を書いた時点の実行結果です）