Slack のスレッドでのやり取りを後からドキュメンテーションツールで残せるようにする

## はじめに

- [Qiita夏祭り2020](https://qiita.com/summer-festival) の [Qiita Teamテーマ](https://qiita.com/official-events/b83bafd26f9a44465307) 記事です。
    - テーマは「**情報共有にまつわる Tips を投稿しよう！**」
- Qiita Team を使ってる(弊社で作ってる)ので投稿先は Qiita Team
    - [Qiita Team for Slack](https://slack.teams.qiita.com/) をベースに実装します。
        - 正式に実装して後日リリースしようと思ってます。
        - よって記事中のコードは一部抜粋で雑ですがご了承ください:pray:
        - 認証認可などすっ飛ばしてます

## Slack のスレッドによって情報が埋もれる？

Slack 利用する上でスレッドの機能は、同一チャンネル内の会話を分離でき、議論のコンテキストが追いやすくて便利です。
その反面、「チャンネルにも投稿」をしなければ、スレッドに参加していないひとは、「えっ、そんな話してたっけ？」ってなりがち。
そもそもそのままSlack上で議論がヒートアップして重要な意思決定にもかかわらず、Slack上にしかその議論が残らず、後からどういう経緯で決まった内容なのかわからなくなることがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32147/11cf58b5-f166-5e8c-af0b-784ea40cddfc.png)


## Slack のスレッドをドキュメンテーションツールに投げる

弊社では Qiita Team をドキュメンテーションツールとして使っています。
そこで、Slack のスレッドを指定してSlack上でコマンド実行すればスレッドでのやり取りをまとめた記事を作成できるようにしてみました。

## 実装

### 完成イメージ

Slack 上での実行
![6e8ee023-6b1d-09d2-c8aa-37a29db007ce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32147/af7a9149-a2de-51c8-f88d-4f1861e81b87.png)


投稿された Qiita Team 記事
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32147/3c00d181-71a0-6e1d-7eae-1e89b4de4341.png)


Slack上で `/command` を実行すると引数として渡したメッセージのリンクのスレッドを記事として投稿します。



### 使うもの

- [Slack API](https://api.slack.com/)
- [Qiita Team API](https://qiita.com/api/v2/docs)
- [Qiita Team for Slack](https://slack.teams.qiita.com/)
    - 自社サービスなので Qiita Team で提供している Slack App に組み込んでみます:pray:

### [conversations.replies](https://api.slack.com/methods/conversations.replies) を使ってスレッドについた投稿を取得
#### 必要なパラメータ

- channel_id
- ts (スレッドのタイムスタンプ)

SlackのメッセージはIDがなく、全てタイムスタンプで指定しなければなりません。
この `ts` メッセージのタイムスタンプをどうにか取得できればすぐにできそうですね。

#### 必要なパラメータはリンクから取得

どのスレッドか指定したいと思った時に、パーマリンクを指定するやりかたが良いかなと思いました。

Slackの特定のメッセージのリンクは

`https://[subdomain].slack.com/archives/[channel_id]/p[timestamp * 1,000,000]`

の形式になっています。
これを解体すれば問題なく、欲しいスレッドを指定できそうです。



```rb
    slack_link = params["text"] # URL format is https://[workspace_subdomain].slack.com/archives/[channel_id]/p[timestamp *1,000,000]
    match = slack_link.match(/https:\/\/.*\.slack\.com\/archives\/.*\/p(\d*)/)
    thread_ts = sprintf("%.6f", match[1].to_f / 1_000_000)
```

#### スラッシュコマンドで送られる情報

[Enabling interactivity with Slash Commands | Slack](https://api.slack.com/interactivity/slash-commands#app_command_handling) で確認できますが、`channel_id` や `user_id` などはスラッシュコマンドから呼び出されるエンドポイントへの POST パラメータで取得できます。


#### conversations.replies へリクエスト
`text` パラメータで受け取ったリンクから `thread_ts` を抜き出し、`channel_id` のパラメータを使って `conversations.replies` へリクエストします。

```rb
    replies_params = {
      "token" => @user.team.slack_access_token,
      "channel" => channel_id,
      "ts" => thread_ts,
    }
    
    uri = URI(REPLIES_URL)
    uri.query = URI.encode_www_form(replies_params)
    json = JSON.parse(Net::HTTP.get(uri))

    messages = json["messages"]
    messages
```

conversations.replies のレスポンスは https://api.slack.com/methods/conversations.replies/test で確認できます。(便利:clap:)

#### レスポンスを加工して記事投稿
`messages` を加工して `body` をよしなにつくります。
`title` や `tag` も必要に応じてパラメータを用意して投稿。

```rb
    pramas = {
      "body" => body,
      "coediting" => true,
      "gist" => false,
      "private" => false,
      "tags" => [
        {
          "name" => @user.qiita_tag,
          "versions" => [
            "0.0.1"
          ]
        }
      ],
      "title" => title,
      "tweet" => false
    }

    RestClient.post(
      "https://#{@user.qiita_subdomain}.qiita.com/api/v2/items",
      params,
      {
        "Authorization" => "Bearer #{@user.qiita_token}",
        "Content-type" => "application/json"
      }
    )
```

#### スラッシュコマンドの登録
[Slack API: Applications | Slack](https://api.slack.com/apps) から Slack App にスラッシュコマンドを登録すれば完成です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32147/d0029261-0f17-bc77-c951-35ccd3e78c82.png)



## 最後に
Slack のスレッドは便利ですが情報共有する上でのデメリットもあります。
重要な議論はチャットで埋もれさせないためにも後から簡単に残せる工夫ができると良いなと思います。

実装についての説明が雑ですが参考にしていただければ幸いです:pray:

Qiita Team をご利用の方は [Qiita Team for Slack](https://slack.teams.qiita.com/) へのリリース、しばしお待ちください:bow: