オウム返し slack bot をぱっとつくる

slackで `@channel` メンションに消耗してる人のために 'at channel police' という Bot を作った．
[![https://gyazo.com/e2e0e7241579a38ce051660b969ba77b](https://i.gyazo.com/e2e0e7241579a38ce051660b969ba77b.gif)](https://gyazo.com/e2e0e7241579a38ce051660b969ba77b)

メッセージの送信をトリガーにした slack bot を作るのが意外と面倒だったのでまとめた．タイトルにはぱっと作るって書いたけど，書いてみたら全然ぱっと作れなさそう．

サンプルコードはrailsだけど，slack上の設定の方が圧倒的にウェイトが重いので，そこを中心にまとめた．
ちなみにサンプルでは [slack-ruby-client](https://github.com/slack-ruby/slack-ruby-client) という公式のgemを使った．

## Prepare
### slack app を作る
https://api.slack.com/apps
App name と team を入力して作成，

### https接続
callback URL が https でないといけないので， [ngrok](https://ngrok.com/)をつかうと便利．
ref: [ngrokを使用してローカル環境を外部に公開する](http://qiita.com/kitaro729/items/44214f9f81d3ebda58bd)

### 表記について
slack の設定ページURLは
https://api.slack.com/apps/{APP_ID}/general
となっていてリンクをベタ書きしづらいので，サイドバーの名称をとって xx page と表記することにする．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/84506/4d654353-df89-d2a4-749f-39bc7aab7eea.png)
↑これだったら Basic Information page と表記

## Bot の作成

Bot Users page から Default username を設定して追加する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/84506/51a33fe9-27b3-84d6-16e9-e5808f99769c.png) 

## callback urlの設定， verify
このリンク先から auth 用 と Event API 用をそれぞれ設定する．

[![Screenshot from Gyazo](https://gyazo.com/feac5a1c6ee5f15b1a30e342d5652e29/raw)](https://gyazo.com/feac5a1c6ee5f15b1a30e342d5652e29)

(at channel police では InteractiveMessage も使ったので Event Subscriptions の上の Interactive Messages からも callback の設定をしないといけなかった．)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/84506/d5c6965c-1b7b-d0d7-00bb-528281cf3427.png)
↑InteractiveMessageってこういうやつ

Events API 用の callback を設定する時は verify が必要で，

```json
{
    "token": "Jhj5dZrVaK7ZwHHjRyZWjbDl",
    "challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P",
    "type": "url_verification"
}
```
ってリクエストが飛んでくるので， challenge をまんまオウム返しする必要がある．

rails で書くとこんな感じ．

```ruby
class ReportController < ApplicationController
  def callback
    @body = JSON.parse(request.body.read)
    case @body['type']
    when 'url_verification'
      render json: @body
    when 'event_callback'
      # ..
    end
  end
end
```
ref: [url_verification event](https://api.slack.com/events/url_verification)

## Events API
websocket を使った [Real Time Messaging API](https://api.slack.com/rtm) というのがあったけど，今回は [Events API](https://api.slack.com/events-api) で十分ぽかったのでコレを使った．

Subscribe する Event を [Event Types](https://api.slack.com/events/api) を参考に Event Subscriptions page で設定する． 今回はユーザからの Message に反応したいだけなので， `message.channels` のみでいいっぽい．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/84506/0364a250-6ef8-1575-e832-779f88cc4f82.png)

あわせて OAuth & Permissions page から Required Scope の設定もする．追加するのは `channels:history` と，メッセージを送る [chat.postMessage](https://api.slack.com/methods/chat.postMessage) というAPIを使用するために `chat:write:bot` を追加する． (`bot` は Bot を有効にした時に自動で追加されてる．  `channels:write` はユーザをチャンネルから kick する時に必要だったやつ)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/84506/7ec15a66-0ed8-5b5c-ef53-ba6a89f7d8ec.png)

ref: [OAuth Scopes](https://api.slack.com/docs/oauth-scopes)

## 必要な token
使用する API によって必要な token が違う． Message の post をする [chat.postMessage](https://api.slack.com/methods/chat.postMessage) を使うためには `bot`, `workspace`, `user` のどれかの token を使う． 

[![Screenshot from Gyazo](https://gyazo.com/c868e0b5c20fc2974f18ff2185187d93/raw)](https://gyazo.com/c868e0b5c20fc2974f18ff2185187d93)

bot token を使えば bot が post するし， user token を使えば authenticate したユーザが post する．tokenは OAuth & Permissions pageで両方見られる．

(ちなみにメンバーをチャンネルから kick する時は User token が必要だったので at channel police は post message と合わせて1つのアプリケーション内で2種類の token を使いわける実装になった．)

## オウム返しする
これでオウム返しができるようになる．

```ruby
def callback
  @body = JSON.parse(request.body.read)
  case @body['type']
  when 'event_callback'
    Slack.configure do |config|
      config.token = ENV['SLACK_BOT_USER_TOKEN']
    end
    client.chat_postMessage(
      as_user: 'true',
      channel: @body['event']['channel'],
      text: @body['event']['text']
    )
    end
    head :ok
  end
end
```

## あとがき
ただオウム返しさせるだけでやること多くて疲れたし，設定ページで見たいリソースがどこにあるのかがわかりづらくていちいちたどるのに時間がかかった．
[slack-ruby-client](https://github.com/slack-ruby/slack-ruby-client) という公式のgemを使ったけど， [`chat_postMessage`](http://www.rubydoc.info/gems/slack-ruby-client/0.9.0/Slack/Web/Api/Endpoints/Chat#chat_postMessage-instance_method) とかいう名前のメソッドを見てつらい気持ちになった．

at channel police を完成させる元気はなくなってしまったけどこのまま成果ゼロは嫌だったので知見だけまとめた．

## REF
[Slack-Ruby-Onboarding-Tutorial](https://github.com/slackapi/Slack-Ruby-Onboarding-Tutorial)