[第一弾] TROCCO®︎を使ってSlackからチャット情報を抽出しBigQueryに集約する

# 目的
株式会社primeNumberでテクニカルサポートエンジニアとして働いている@kimura34です。
弊社が提供しているサービスTROCCO®︎ではEssentialプラン以上のお客様にはslackを利用したサポートを提供しており、
エラーなどのトラブル発生時や、利用方法などに関する相談があるときはslack上でコミュニケーションを取っています。

入社したばかりの頃はTROCCO®︎のことを知るための教科書として、過去の問い合わせ履歴から学んでいました。
今でも問い合わせを受けた時はSlackやSalesforceで検索をかけて、過去に同じような事例がないか確認しています。
しかし自分が参加していないSlackチャンネルの履歴までは確認できないので過去の事例に辿り着かないこともよくありました。
チャンネルへの参加有無関係なく、過去のチャット履歴を検索することができたらハッピー！なのに、と何度思ったことか。。。

ナレッジをCS内で共有するために
<strong>Slackのチャンネルからチャット情報（お客様からの問い合わせ履歴）を取得して、
過去の問い合わせを資産として扱い、今後の問い合わせ対応の効率化に結びつけていくことが今回の施策の目的です。</strong>

３部作でお送りします〜！
第一弾 TROCCO®︎を使ってSlackからチャット情報を抽出しBigQueryに集約する
第二弾 （仮）TROCCO®のワークフローからDataformを動かす
第三弾 （仮）TROCCO®とBigqueryで作る簡単LLM

# 第一弾 TROCCO®︎を使ってslackからチャット情報を抽出しBigQueryに集約する
**SlackAPIを利用してチャット情報を取得し、BigQueryに転送**

を行なっていきます！

## 事前準備
Slack APIを利用するための準備をしておきます。
### Botアプリを指定のワークスペースに作成、追加
[ここ](https://api.slack.com/apps?new_app=1)からアクセスします。

"Create New App"をクリックします。
![slack_api_①_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/af6a441e-493b-fd58-2c2a-6462396b09d8.png)

情報を入れて"Create App"をクリックします。
![slack_api_①_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/7eebfa88-ce82-9876-414b-d74e6ebb0a17.png)

### 適切なスコープを付与
"OAuth & Permissions"を開きます。
![slack_api_②_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/83246f35-285e-2168-09fd-dc5fce3baafc.png)

"Scopes"の"Add an OAuth Scope"にて、必要なScopeを付与します。
- 今回利用するAPIに必要なスコープは`channels:history`と`groups:history`
    - `channels:history`：パブリックチャンネルのチャット情報取得時に必要
    - `groups:history`：プライベートチャンネルのチャット情報取得時に必要
![slack_api_②_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/146bc2e6-5250-d6e5-f4b3-a75908c5cab7.png)

### Botを取得対象のチャンネルに追加
該当チャンネルの左上にあるチャンネル名をクリックします。
![slack_api_③_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/58f61f84-1a51-5ce2-d8b8-f0239f37fbd6.png)

 "インテグレーション"タブの"アプリを追加する"にて、作成したアプリを追加します。
![slack_api_③_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/69ca4d8e-1b4a-2e76-ba0b-16577b407339.png)

### Bot User OAuth Access Tokenを取得
"OAuth & Permissions"を開きます。

"Scopes"の"Add an OAuth Scope"にて、必要なScopeを付与します。
    ※ SlackAPI上で適切なScopeの付与が先に行われている必要があります

"Install to Workspace"をクリックします。
![slack_api_④_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/b415ceee-ab9d-9e94-6dad-9065fabdefd2.png)

右下の"許可する"をクリックします。
![slack_api_④_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/36958086-04f9-8a47-b244-56240b0dcacc.png)


<strong>※ Scopeを上記手順の後新たに追加した場合、Bot User OAuth TokenをReinstallする必要があります。上記3、4の手順を再度行っていただくだけ問題ございませんが、Reinstall忘れにご注意ください。</strong>

## 転送設定を作成
ここからTROCCO®︎を利用してslack -> BigQueryにデータを転送していきます。

TROCCO®︎の転送元コネクタにslackはあるのですが、取得可能なデータが`users.list`のみなので、今回取得予定の`conversations.history`と`conversations.replies`は転送元slackでは利用できません。

TROCCO®︎で提供しているコネクタ以外も転送元として利用したい・・・。そんな時に試して欲しいのが<strong>転送元コネクタHTTP・HTTPS</strong>です！！
<br>
転送元HTTP・HTTPSはAPIの提供がある外部サービスだと利用が可能となります。
※ 利用実績や検証の相談のれますのでいつでもご連絡ください〜
Slack APIは転送元HTTP・HTTPSでデータ取得ができたので、HowToを説明していきます。

### STEP1
まず転送元HTTP・HTTPS → 転送先BigQueryの転送設定を作成します。
![etl_configurations1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/47a5cc47-7535-dcba-2af9-6bb9c838d5b7.png)

カスタム変数を使って動的にパラメータの値を変更できるようにしたいので、まずカスタム変数を作成します。

今回動的に変化させたいのがチャンネルIDと取得する期間の始まりと終わりです。
SlackAPIでは取得する期間を絞ることができるのですが、Unix timestampでの指定が必須なのでデータ型は文字列で作成します。
![etl_configurations2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/b7d859c0-e378-cd3c-34fc-a768809a1d1c.png)

URLにエンドポイントを入力します。今回はチャットの情報を取得する`conversations.history`のAPIを利用するので、`https://slack.com/api/conversations.history`を入力しました。

HTTPメソッドはPOSTなので`POST`と入力します。

入力ファイル形式には`JSONPath`を指定します。 

JSONPath には`$.messages`を入力します。

パラメータにはSlack APIの仕様書に載っているパラメータを設定することができます。
ここで先ほど作成したカスタム変数を埋め込むことで、実行時に動的に展開することができます。
パラメータの名前はAPIの仕様書に載っているキー名を入力してください。
![etl_configurations3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/8a57c0c7-35f7-bf38-754e-200f8c871332.png)

HTTPヘッダに認証情報を定義します。
SlackAPIの場合は事前準備で取得したトークンを`Bearer 発行したトークン`の形式で入力します。マスキングにチェックをつけると画面上では***で表示されるので安全です。
![etl_configurations4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/adc84774-41b8-e0e4-0a3e-e303ee404b70.png)

転送先BigQueryの設定に関しては割愛します。

### STEP2
設定に問題がない場合、STEP2のデータ設定タブ内「カラム定義」がこんな感じで自動作成されます。
![スクリーンショット 2024-11-22 15.57.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/00a6b4c2-c03d-f591-3376-7099a6ed1b5b.png)

必要なデータだけ取得するための絞り込みを行います。
今回はts（チャットのタイムスタンプ）のデータだけ取得、後続で`conversations.replies`を使ってチャットに紐づくスレッド情報を取得しようと思います。
そのためにchannel_idも併せてtsと管理しておきたいので、取得したデータ内にはないですが、STEP1で作成したカスタム変数を埋め込みchannel_idも転送します。
![スクリーンショット 2024-11-22 16.00.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/2f263572-1021-d1dd-757a-a4a76d6acb19.png)

プレビューを実行すると必要なデータのみを抽出することができました。
![スクリーンショット 2024-11-22 16.00.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/eb67afb5-e07d-aee1-ffa8-590b2efc0785.png)

## ワークフローを作成
先ほど作成した転送設定をワークフローに組み込んでみます。
![スクリーンショット 2024-11-22 16.16.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/bf9b987c-53c0-3fb1-a1c9-15996b3611c1.png)

転送設定作成時にカスタム変数をリクエストのパラメータに埋め込んでいたのですが、ここで動的に展開することができます。該当の転送設定をクリックして編集します。
![スクリーンショット 2024-11-22 16.18.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/cb191a21-21f2-34b2-fb6c-c9da31efaef5.png)

カスタム変数でループ実行にチェックをつけると、ループの種類を選択することができます。
今回はBigQuery上に用意しておいたチャンネルIDのリストからチャンネルIDを取得してループ実行したかったので、「Google BigQueryのクエリ結果でループ」を選択しました。
対象のカスタム変数に展開したいカスタム変数を選択します。
![スクリーンショット 2024-11-22 16.08.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465735/be331ef2-57a1-03eb-d3cf-af1ac9faa98e.png)

2ヶ月分のチャット情報を取得したいと考えたので以下のようなクエリを書きました。
対象カスタム変数で選択した順番に合わせて展開したいのでSELECT文の順番に注意が必要です。
```SQL
    WITH tmp AS (
      SELECT
        channel_id,
        channel_name
      FROM
        dl_slack_rawdata.dwh_slack_id_add
    )
    
    SELECT
      channel_id,
      UNIX_SECONDS(TIMESTAMP(DATE("2024-08-01"), "Asia/Tokyo")) AS oldest,
      UNIX_SECONDS(TIMESTAMP_SUB(TIMESTAMP(DATE("2024-10-01"), "Asia/Tokyo"), INTERVAL 1 SECOND)) AS oldest,
      channel_name
    FROM
      tmp
```

# 最後に
今回紹介したのはチャットのタイムスタンプを取得するところまでですが、チャンネルIDとtsを使ってチャットに紐づいているスレッド情報を取得する転送設定を作成し、それらをワークフローで繋げることでスレッドの情報取得が可能になります。

これにて第一弾は終了です〜〜！
TROCCO®︎を使った良いところは、一回設定してしまえば定期実行でデータを貯めていけるので、とても楽にデータを抽出、管理することができるところですね。