Rubyを使ってSlack APIを叩く

#Rubyを使ってSlack APIを叩く

本稿はSlack APIを使用するスクリプトをRubyで作成した際のメモである。

## Slack側の設定

Slack APIを実行する場合，最初にアプリを作成する。
以前はワークグループ側でトークンを設定するやり方だったようだが，現在は非推奨とのこと。
以前のやり方は，トークンの設定をすれば無条件に全てのAPIを利用可能だったが，現在はアプリ側で使用可能なAPIを設定し，それをワークグループにインストールするという流れで行う。
アプリの作成や削除，更新は以下の画面から行う。

https://api.slack.com/apps

1. [Create New App]を押下する。
2. アプリ名とインストールするワークグループ名を指定して，[Create App]を押下する。
![スクリーンショット 2019-04-06 13.38.29.png](https://qiita-image-store.s3.amazonaws.com/0/263164/a4949fb9-4403-a9e2-e792-90ff4f401f97.png)
3. [Permissions]を押下する。
![スクリーンショット 2019-04-06 13.39.12.png](https://qiita-image-store.s3.amazonaws.com/0/263164/e38f83e7-9772-0642-3f44-c776ab8e3295.png)
4. 「OAuth & Permissions」のScopesから権限を付与するAPIを設定する。
![スクリーンショット 2019-04-06 13.41.50.png](https://qiita-image-store.s3.amazonaws.com/0/263164/ee783ddb-0d2a-773c-d13a-e6cfdd48b085.png)
Slack APIは　https://api.slack.com/methods  で調べられる。
![スクリーンショット 2019-04-06 13.39.46.png](https://qiita-image-store.s3.amazonaws.com/0/263164/be57e656-3fa2-55e8-08f4-e1eb3ffe0e06.png)
5. [Save Changes]を押下する。
6. 画面の上に戻って[Install App to Workspace]を押下して，アプリをインストールする。
![スクリーンショット 2019-04-06 13.41.50.png](https://qiita-image-store.s3.amazonaws.com/0/263164/353926c2-a510-5fdb-6f8e-2e9a097e9ec9.png)
7.[許可する]を押下する。
![スクリーンショット 2019-04-06 13.42.13.png](https://qiita-image-store.s3.amazonaws.com/0/263164/9bb4a0c0-cae2-335d-80ff-310838515b5a.png)

### 設定メモ

* Slack APIの設定で，パブリックチャンネルは「channels:XXXX」，プライベートチャンネルは「groups:XXXX」を使う。
* アプリを削除する場合は「Basic Information」から可能。
* アプリ名の変更は「Basic Information」から可能。
* 権限を再設定して再インストールしてもトークンはそのまま。

## Slack APIを叩く

単純にアクセスするだけならcurlで以下のようなURLを指定するなり，Webブラウザでアクセスすれば良い。

```
https://api.slack.com/methods/conversations.history?token=XXXXXXXXXX&channel=XXXXX&pretty=1
```

tokenはSlack APIのアプリ画面の「OAuth & Permissions」から取得できる。
channelはSlackのURLから取得できる。チャンネルを開いた時のURLである「 https://hoge.slack.com/messages/XXXXXX/ 」のXXXXXX部分。

上記のようにただアクセスするだけであれば，curlやjqだけでも十分だと思ったが，
以下のようにいろいろな形式変換を楽にしたいと考えると，プログラミング言語を使った方が楽だと感じ，Rubyを使った。

|項目|形式|変換|
|:----|:---|:---|
|URL|URLエスケープ|uriライブラリでURI.escape(XXX)を使用して作成可|
|メッセージ|Unicodeエスケープ形式|jsonライブラリを使用してデコード可|
|&や>などのメッセージ|HTML特殊文字|cgiライブラリのCGI.unescapeHTML(XXX)を使用してデコード可|
|時刻|UNIX時刻|Time.at(XXX)を使用して変換可|

Slack APIを実行する単純なサンプルは以下である。

```ruby
require 'json'
require 'open-uri'

token="XXXXXXXXXXXXXXXXXXXXX"
channel="XXXXXXX"

url="https://slack.com/api/conversations.history?token=#{token}&channel=#{channel}&pretty=1"
v = JSON.load(open(url).read)
p v
```
※XXX部分は実際のトークンやチャンネルを設定する。

上記を基に，検索機能で今日分のメッセージを取得するサンプルは以下である。

```ruby
require 'json'
require 'open-uri'
require 'uri'
require 'cgi'

token="XXXXXXXXXXXXXXXXXXXXX"
channel="XXXXXXX"
ts=Time.new.strftime('%Y-%m-%d') # 今日
query=URI.escape("on:#{ts} in:#XXXX")

url="https://slack.com/api/search.messages?token=#{token}&channel=#{channel}&query=#{query}&pretty=1"
JSON.load(open(url).read)["messages"]["matches"].sort{|a,b| a["ts"].to_f <=> b["ts"].to_f}.each do |msg|
    puts "----------------------------------------"
    puts "from: #{msg["username"]}"
    puts "ts: #{Time.at(msg["ts"].to_f).strftime('%Y-%m-%d %H:%M:%S')}"
    puts
    puts CGI.unescapeHTML(msg["text"])
end
```

group_byでURLからスレッドを分ける場合は以下のような感じ。
(雑だが)

```ruby:スレッドを分ける
require 'json'
require 'open-uri'
require 'uri'
require 'cgi'

token="XXXXXXXXXXXXXXXXXXXXX"
channel="XXXXXXX"
ts=Time.new.strftime('%Y-%m-%d') # 今日
query=URI.escape("on:#{ts} in:#XXXX")

url="https://slack.com/api/search.messages?token=#{token}&channel=#{channel}&query=#{query}&pretty=1"
JSON.load(open(url).read)["messages"]["matches"].group_by{|v| v['permalink'].gsub(/^.*?\?/, '')}.each do |k, v|
  puts "==================================================="
  puts (/^thread_as.*$/=~ k)? "【スレッド：#{k}】" : "【スレッド以外】"

  v.sort{|a,b| a["ts"].to_f <=> b["ts"].to_f}.each do |msg|
    puts "----------------------------------------"
    puts "from: #{msg["username"]}"
    puts "ts: #{Time.at(msg["ts"].to_f).strftime('%Y-%m-%d %H:%M:%S')}"
    puts
    puts CGI.unescapeHTML(msg["text"])
  end
end
puts "==================================================="
```

## 感想

* この手の作業をするとRubyの便利さを改めて感じた。
* Slack APIのページがかなり親切だった。
* 最初にLegacy Tokensを使用したが，無効化方法わからなかった。