Slackにアップした画像をダウンロードするBotを作ってみた

本記事は [アプレッソ Advent Calendar 2017](https://qiita.com/advent-calendar/2017/appresso) 19日目の記事です。

# みなさん、Slackに写真をアップしますよね？

+ ミーティングで書いたホワイトボードを記録するために
+ ランチで食べた美味しい料理を共有するために
+ 日々の思い出を残すために

さまざまなシーンで写真を撮って、SlackでShareすると思います！
でも、Slackのタイムラインは流れて写真は忘れ去られてしまいます。
そこで、アップされた写真をダウンロードして保存しておけば、いつでも見返すことができますね！

# Slackbotで画像ファイルをダウンロード

Slackbotの作り方は色々ありますが、私は Ruby が好きなので、Ruby で作ります。


## 画像ファイルがアップされるのを待つ

### Botのコードを書く

まず、slackbot用の便利なgem [slack-ruby-client](https://github.com/slack-ruby/slack-ruby-client) を使って、メッセージを監視するコードを書いてみます。

`slack-ruby-client` の使い方は、Bot Token をセットして、RealTime Client のインスタンスを生成するだけです。

```ruby
require 'slack-ruby-client'

Slack.configure do |config|
  config.token = 'xoxb-xxxxxxxxxx'
end

client = Slack::RealTime::Client.new

client.on :hello do |data|
  puts "=== Successfully connected! ==="
end

client.on :message do |data|
  if data.subtype == 'file_share'
    # subtypeが'file_share'の場合、ファイルがアップされたとき
    # ここにファイルを処理するコードを書く
  end
end

client.on :close do |data|
  puts "=== Close ==="
end
```

`:message` イベントが、Slackの投稿を受け取るイベントです。
メッセージデータの subtype がメッセージの種類を表しており、`'file_share'` がファイルをアップロードしたときの値になります。

### Bot Token を発行する

Bot Token は以下の手順で発行することができます。
1. https://[slackサービス名].slack.com/apps にアクセスします。
2. [Bots] を検索して、[Bots] のページを開き、[Install] ボタンをクリックします。
3. Bot名を入力して、Botを追加します。
4. Bot Token (xoxb- から始まる文字列)が生成されているので、コピーします。

このBot Tokenが使える機能は、[こちらのリスト](https://api.slack.com/bot-users)にあるRealTime Message APIのみです。
Botを作成したら、監視したいチャンネルにInviteしておきましょう。

次に、アップロードされたファイルが画像か確認して、ダウンロードします。

## 画像ファイルをダウンロードする

### ダウンロードするコード

ファイルのダウンロードURLにアクセスして、ファイルをダウンロードします。
今回はダウンロード対象を "jpg" に限定しています。
Slackにリクエストを投げる際に、Bearer認証が必要となります。ここで使用するトークンは、User Tokenです。

```ruby
require 'rest-client'

def fetch_and_save_image(file, channel)
  if file.filetype == "jpg"
    File.open(file.name, 'wb') do |f|
      res = RestClient.get(file.url_private, { "Authorization" => "Bearer xoxp-xxxxxxxxxx" })
      if res.code == 200
        f << res.body
      end
    end
  end
end

# 中略

client.on :message do |data|
  if data.subtype == 'file_share'
    fetch_and_save_image(data.file)
  end
end
```

### User Token を発行する

User Tokenは以下の手順で発行することができます。
1. https://api.slack.com/applications にアクセスします。
2. [Create New App] ボタンをクリックします。
3. API の App Name を入力し、連携するWorkspaceを選択します。
4. 左パネルメニューから [OAuth & Permissions] を選択します。
5. Scopes にて [files:read] を選択して、[Save Changes] ボタンをクリックします。
6. OAuth Access Token (xoxp- から始まる文字列) が生成されるので、コピーします。

Slackにはレガシートークン（古いトークン）がありますが、レガシートークンは何でもできる権限を持つため、現在は非推奨です。そのため、上記手順のように、必要に応じて限定された権限を持つトークンを発行する必要があります。

# やってみて困ったこと
- Windows環境でのRuby開発環境構築
    最近までMacしか触っていなかったので、久々にWindowsでRubyの開発環境の構築を試みました。Ruby自体のインストールは簡単ですが、使用したいgemがWindowsに未対応であり断念。結局 Docker で Linux の仮想マシンを使って構築しました。

- SlackのTokenがわかりにくい
    レガシートークンを使った事例がまだまだ多かったり、[Slackのページ](https://get.slack.help/hc/ja/articles/215770388-API-%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E7%94%9F%E6%88%90%E3%81%A8%E5%86%8D%E7%94%9F%E6%88%90)を見ても最初にレガシートークンの発行があったりしたため、レガシートークンを使えということか...と戸惑ってしまいました。よくよく調べた結果、レガシートークンはセキュアではないため、非推奨ということがわかりました。

# さいごに

今回作ったBotでダウンロードした画像ファイルは、DataSpider のファイルトリガーを使って、自動で共有サーバへ保管しています。
スクリプトは非常にシンプルです。

![スクリプト.PNG](https://qiita-image-store.s3.amazonaws.com/0/15643/4d09db93-9f78-c873-25e5-2023a10ad536.png)

DataSpider の基本的な使い方ですが、ファイルの監視、ファイルの移動が簡単に設定できました！

みなさんも、BotやDataSpiderで、業務や雑務を自動化してみてはいかがでしょうか。

##参考記事
- [Slackにアップしたファイルを自動でS3にアップするBOTを作ってみた -ファイルはS3にどんどんしまっちゃおうねぇ～-](https://qiita.com/Mic-U/items/c0234b7801bf1204bfff)