Railsでスタンプを勝手に押してくれるSlackのbotを作ってみた

こんにちは。
出張で福岡に来ているのですが、こちらの朝は少し寒いですね。

作業の効率化を行いたくて、Ruby on Railsで勝手にスタンプを押してくれるSlackのbotを作ってみました。

その一部始終を語ってみようかなと思います。

## slack-ruby-client

慣れ親しんでいるRailsでパパっとやってしまいたい。
そんな思いから、探してきたgemがこちら。

[slack-ruby-client](https://github.com/slack-ruby/slack-ruby-client)

メソッドは、SlackのAPIをそのままスネークケースに変換したようなメソッドなので、[SlackAPI](https://api.slack.com/)のレファレンスも見ながらあれこれ試して実装を進めてました。

### 1. botの登録

まずは、botを[ここ](https://my.slack.com/services/new/bot)で登録します。

<img width="1280" alt="スクリーンショット 2017-12-08 0.52.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/217122/a995fad3-1f86-5753-fe99-d1e8237b7d13.png">

「Add Configlation」より、Slackで表示させたいbotの名前を入力して「Add bot integration」をクリックすると、詳細な設定が行える画面に飛びます。

<img width="1280" alt="スクリーンショット 2017-12-08 2.54.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/217122/ea612e03-03f5-b3c9-4d84-31a67136b1a5.png">

アイコンの設定や、botを使えるIPの制限なんかもここで設定できるようになっていました。

<img width="1280" alt="スクリーンショット 2017-12-08 9.00.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/217122/bea76f57-9f23-c13c-fc4d-4a1700cda95a.png">

ここの上部に表示されている**「API Token」**、これが、後で実装する上で必要になるので、ここでメモ。

### 2. channelへbotの招待

Slackを起動し、botを稼働させたいchannelから先ほど作ったbotを招待します。

<img width="1213" alt="スクリーンショット 2017-12-08 9.40.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/217122/f8edf047-4956-78b1-7717-4f8134b1a374.png">

<img width="1206" alt="スクリーンショット 2017-12-08 9.42.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/217122/ff981dca-8812-51ec-9f86-790c4975634b.png">

こうしてやることで、botに閲覧権限と発言権が与えられるようです。

### 3. 実装

まず、Gemfileにgemを追加ですね。

```gem 'slack-ruby-client'```

次に、botのための設定のためのファイルを```config/initializers/```に保存。
_slack_api.rb_と名付けて以下のコードを記載しました。

```ruby:slack_api.rb
require 'slack'

Slack.configure do |config|
  config.token = ENV['BOT_TOKEN']
end

Slack::Web::Client.config do |config|
  config.user_agent = 'Slack Ruby Client/1.0'
end

Slack::RealTime::Client.config do |config|
  config.start_method = :rtm_start
end
```

```config.token = ENV['BOT_TOKEN']```の箇所ですが、環境変数にbot登録時に取得した**API Token**をBOT_TOKENという変数名でサーバーに登録し、それを読み込ませるようにした記述です。

Settingsに書いた方がよかったかなと思ったり………


そして、実際に動かすファイルをどこに置くかは、用途や人によって違うと思いますが、僕は```app/batch```というディレクトリにファイルを作って、クライアントを呼び出すメソッドを記載。

```ruby:reaction_bot.rb
def web_client
  @web_client ||= Slack::Web::Client.new
end

def real_time_client
  @real_time_client ||= Slack::RealTime::Client.new
end
```

_real_time_client_を用いることで、botが参加しているchannelのメッセージをポーリングできるようなので、特定のユーザーが呟いた瞬間に、スタンプを押すという嫌がらせを実行できるようにしてみました。

````ruby:reaction_bot.rb
TARGET_USER_ID = {ターゲットにしたいユーザーのID}
def execute
  real_time_client.on :message do |message|
    if message.user == TARGET_USER_ID
          web_client.reactions_add(name: 'yasei_1', channel: message.channel, timestamp: message.ts)
          web_client.reactions_add(name: 'yasei_2', channel: message.channel, timestamp: message.ts)
          web_client.reactions_add(name: 'yasei_3', channel: message.channel, timestamp: message.ts)
          web_client.reactions_add(name: 'yasei_4', channel: message.channel, timestamp: message.ts)
          web_client.reactions_add(name: 'yasei_5', channel: message.channel, timestamp: message.ts)
          web_client.reactions_add(name: 'yasei_6', channel: message.channel, timestamp: message.ts)
          web_client.reactions_add(name: 'yasei_7', channel: message.channel, timestamp: message.ts)
          web_client.reactions_add(name: 'yasei_8', channel: message.channel, timestamp: message.ts)
          web_client.reactions_add(name: 'yasei_9', channel: message.channel, timestamp: message.ts)
          web_client.reactions_add(name: 'yasei_10', channel: message.channel, timestamp: message.ts
    end
  end
  real_time_client.start!
end
```

これをRakeタスクで実行。

<img width="544" alt="スクリーンショット 2017-12-08 19.44.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/217122/9a660fa7-77a3-68fd-9c1d-b3736c86ae7d.png">

見事に引っ掛かりました。


………そんな冗談も行いながら笑

実際には、messageの内容をDBに保存していき、その履歴と新しく来たメッセージを比較してそれに合ったスタンプ押してくというものを作りました。


ご興味ある方は、お試しあれ。

次回は、Uploadされた画像を顔認識させて、スタンプを作るbotを作ってみようと思います。