Slackアプリ内で問い合わせの送受信ができる仕組みを作って公開した話

Slackのアプリ開発をしています。 @geeorgey です。
SlackアプリをApp Directoryに登録する時に見かけたのですが、 /feedback みたいなコマンドを作ってユーザーからのフィードバックを得られるようにしてほしいと書かれてたんですよね。
確かにそれはそうだよなと。
そこで、簡単に作ったんですよ。最初の仕組みはシンプルに、フィードバックコマンドをつつくと、このようにモーダルが現れて、ユーザーはメッセージを入力したら送信ボタンを押すというもの。
![Slack___news-jp___Leave_a_Nest_Co__ltd_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/0470791e-9042-e827-6c98-a9a1d0da4cf7.png)

送信された内容は、管理者の指定するチャンネルに流れてくるという仕組みになっていました。

![Slack___tips-support___Leave_a_Nest_Co__ltd_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/c929c608-67d7-cf4b-af36-54da3b2978c0.png)

ユーザーには、メールで返信するのでお待ち下さいというメッセージを送信していました。

ただ、思うじゃないですか。
Slackから問い合わせているのに返信がメール！？って。
ということで、作ってみたんですSlack完結型の問い合わせの仕組み。

## 動作イメージ
仕組みは3つあります。

- 1：ユーザーがフィードバックコマンドを使ってフィードバックしてくるパターン
- 2：管理者がユーザーにDMを送信して遣り取りをするパターン
- 3：アプリのホームボタンから問い合わせボタンを押して問い合わせ開始するパターン

まずは1についてです。
送信されたメッセージは管理者にこのような形で届きます。

![Slack_____tips-support___Leave_a_Nest_Co__ltd_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/20738257-49c6-0d55-7394-1387611610e5.png)

変わったのは下部にある入力フォームです。
ここにレスポンスを記入して送信すると、ユーザーにメッセージが届くという仕組みです。
ユーザーにはDMで同様のメッセージフォームが届きますので、そこに返信するとデベロッパー向けにメッセージが届きます。

### やり取りはスレッド化される
ユーザーサポートの文脈なので、一つのやり取りは一つのスレッドに集約されます。これはデベロッパーもユーザーも同じです。一つのスレッドを追っておけば、質問事項についてのやり取りが解決するという仕組みになっています。
![Slack___tips-support___Leave_a_Nest_Co__ltd_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/583a2701-1fd7-d9b6-ee52-129c0017e9dc.png)

##2：管理者がユーザーにDMを送信して遣り取りをするパターン
アプリを作ってて思うことは、アップデート情報をどうやって送信するかということでした。
これは、アプリ管理者のみがDM配信できるような仕組みを作ることで解決しています。
アプリのホーム画面に、特定のユーザーだけに表示されるメニューを配置しました。
![Slack___Timeline___Leave_a_Nest_Co__ltd_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/cf4bc6b0-fdd0-cb3f-29a4-9b13cc7ea170.png)
このメニューボタンを押すと、入力フォームが立ち上がります。
![Slack___Timeline___Leave_a_Nest_Co__ltd_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/39df5977-f6e1-24cb-2eca-17422ff9978e.png)
特定のユーザーにDMを送りたい場合は、右上の選択リストからユーザーを選択して送信します。
未選択の場合は、インストールユーザ全員にDMが送られます。
![Slack___Timeline___Leave_a_Nest_Co__ltd_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/98140dcd-a330-68f9-e214-04c34f3a2ab9.png)
確認画面で内容を確認して、送信ボタンを押せばDMが送信されます。
送信された中身は、上に書いたものと同じで、フィードバックを受けることも出来ます。

##3：アプリのホームボタンから問い合わせボタンを押して問い合わせ開始するパターン
![Slack___local_vue_flask_template___George_Dev___2_個の新しいアイテム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/c2497596-e466-c7c6-6e75-9986248eae32.png)

Slackの @seratch さんより、スラッシュコマンドがコンフリクトすると、あとにインストールしたコマンドが優先されるので、スラッシュコマンドよりはホーム画面からのボタンの方が安定するというコメントをもらったのでホーム画面に設置しました。
それに伴い、若干コードを改変しましたが、やり取りの流れは同じです。

## まとめ
以上のような形でユーザーサポートの仕組みを作りました。
Slackアプリの配信を考えている人は必要になる機能だと思いますので、ソースコードを公開します。
改善点あればプルリクください！
https://github.com/geeorgey/vue_flask_template

## コードの細かい所
### 環境変数の追加

```.env
export SLACK_SCOPES=chat:write,users:read,users:read.email,channels:join,groups:write,im:write,mpim:write,channels:read,app_mentions:read,im:read,mpim:read,channels:history,groups:history,im:history,mpim:history,commands
export APP_OWNER_WS_ID="Txxxxxxx"
export APP_OWNER_CONTACT_CHANNEL_ID="Cxxxxxxx"
export APP_OWNER_ID="Uxxxxxx"
export APP_OWNER_TOKEN="xoxb-"
export SLACK_FEEDBACK_COMMAND="/app_feedback"
export APP_NAME="APP NAME"
```
SCOPEを追加してあります
加えて、オーナー関連の設定が必要です
APP_OWNER_WS_ID： 問い合わせを受け取るワークスペースのIDを入れます
APP_OWNER_CONTACT_CHANNEL_ID： 問い合わせを受け取るワークスペース内のチャンネルIDを入れます
APP_OWNER_ID： アプリのオーナーIDを入れます。 | 区切りで複数人数を入れることが出来ます
APP_OWNER_TOKEN： アプリのオーナーのSlackInstallations のbot_token を入れてください
SLACK_FEEDBACK_COMMAND: アプリに登録したスラッシュコマンドを入れます。入れ方は下に書きます。
APP_NAME： アプリ名を入れてください。メッセージ内に表示されます

### home画面にボタンを追加するには
まずはSlackアプリの管理画面
APP HOMEでホームタブをONにする必要があります。
![Cursor_と_Slack_API__Applications___George_Dev_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/a171b354-fa20-692f-6750-92b1238f6063.png)
次に、Event Subscriptions画面からapp_home_opendのSCOPEを追加してください。そうすることでアプリのホームタブを開いたという情報をbot側でキャッチできるようになります。
![Slack_API__Applications___George_Dev_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/92e07743-4b20-f376-1d5f-737cc087dfbd.png)

ホームタブを開いたときの挙動はこの辺に書いてあります。
https://github.com/geeorgey/vue_flask_template/blob/72e58b5de38346fbc110783fd1d44cc43e760e90/backend/bolt.py#L344

### フィードバック用のスクリプトたち
全体的な流れはこちらを参照してください
https://github.com/geeorgey/vue_flask_template/blob/main/backend/feedback.py

###開発の始め方
GitHubのREADMEを参照ください
https://github.com/geeorgey/vue_flask_template
順番としては、
- ローカル環境にPostgreSQLでDBを作る
- Slackにアプリを作る
- 適当なワークスペースにインストールして、ClientID,ClientSecret,ClientSigningSecretを取得する
- Ngrokを立ち上げてトンネル用のURLを取得する
- pipenv install -r requirements.txt で必要なライブラリをインストールする
- macの場合且つpsycopg2のインストールでエラーが出る場合は[こちらを参照](https://dev.classmethod.jp/articles/mac-psycopg2-install/)して、環境変数を追加してください

```
$ export LDFLAGS="-L/usr/local/opt/openssl/lib"
$ export CPPFLAGS="-I/usr/local/opt/openssl/include"
```

- インストールできたら、flask db upgrade でデータベースを作ってください
- あとは flask runでアプリを立ち上げます
- ngrokで生成したURLを設定していきます
- Slackのアプリ画面に行って、設定を行いましょう。
- リダイレクトURLを登録する。アプリの設定画面からやります。これをやらないとインストールが出来ません。インストールするURLは ngrokのURL/slack/oauth_redirect です

![Slack_API__Applications___George_Dev_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/e0801f04-13c2-fec2-06b1-0567d4900a16.png)

- Event SubscriptionsのRequestURLを設定します

![Slack_API__Applications___George_Dev_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/966956e4-7f69-c615-b4f0-99266b996d43.png)
URLが正しく入ってると、Verified！とチェックしてくれるのでわかりやすいです。
URLはngrokのURL/slack/events です

- スラッシュコマンドを登録する
![Slack_API__Applications___George_Dev_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/3a39afe5-0aef-dfcf-3433-741de10b7385.png)
コマンド名は何でも良いですが、
export SLACK_FEEDBACK_COMMAND="/app_feedback"
で設定したものに合わせてください。大文字小文字も判定するので注意。
URLは先程と同様にngrokのURL/slack/events です

ここまでで設定が出来ました。
次はインストールしてみましょう。
ngrokのURL/slack/install
にアクセスしてください。
インストール画面が現れると思います。
この状態だと、最初にインストールした組織にしかインストールできずないのでテストが出来ません。複数ワークスペースにインストールできるように設定していきます。

SlackアプリのManage distribution画面から、こちらをチェックして保存するだけです。
![Slack___Slack_API__Applications___George_Dev.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/c9a41f45-a7e0-9c03-4401-3ee377d5ad05.png)
変数をハードコードしてませんよチェックを入れましょう。
これを行うことで他の組織にもインストールすることができるようになります。

さて、インストールしたら、データベースをのぞいてみてください。
slack_installationテーブルにインストールしたデータが入っているはずです。

![slack_installations_–_template_–_vue_flask_template_Local_と_transferred_–_ddg4f8m3mk5jn9_–_Timeline_Develop_と_transferred_–_d94tsrgrequ57c_–_TimeLine_Production_Heroku.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/b18a3d15-30d3-8fd0-13f6-87d35a72cbf1.png)

問い合わせを受けるワークスペースのteam_id,bot_token,user_idが必要になります。
export APP_OWNER_WS_ID="Txxxxxxx"
export APP_OWNER_ID="Uxxxxxx"
export APP_OWNER_TOKEN="xoxb-"
それらを上の環境変数に入れて、ターミナルで実行してください。
最後に、問い合わせを受けるチャンネルをワークスペースに作成し、チャンネルIDを取得したらこちらに入れて実行です。
export APP_OWNER_CONTACT_CHANNEL_ID="Cxxxxxxx"

チャンネルIDは、チャンネルクリックメニューから呼び出すURLから取得しましょう。
![Slack___contact___George_Dev___2_new_items.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/3f220875-4cb3-c1ea-229c-15d5ee6efa9a.png)

## テストする
### １：ユーザーからの問い合わせのテスト
インストールしたワークスペースからコマンドを立ち上げてください
/app_feedback
入力画面が表示されたらテキストを入れて送信してみましょう。
先程設定したチャンネルに問い合わせ内容がPostされればOKです。

### ２：ユーザーからの問い合わせに返信するテスト
先程投げられた投稿の返信欄にテキストを入れて送信してください。
元のユーザーにDMが入れば成功です

### ３：デベロッパーからの返信にユーザーから返信するテスト
ユーザーにも送信欄付きのメッセージが届きますので、なにか入力して送信しましょう。
デベロッパー側は、１で投稿されたメッセージのスレッドに返信が入ることが確認できます

### 4：ユーザー側のスレッドに入ったかを確認する
先程スレッドに入ったメッセージから返信してみてください。
ユーザー側のスレッドに入れば完成です

### 5:DM機能をテストする
アプリの管理者のワークスペースを開くと、ボタンが表示されているはずです。

![Slack___local_vue_flask_template___George_Dev.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/eb88d5c1-5865-ba72-8401-8b5acec58af9.png)
これを押して、メッセージを送信してみましょう。

![Slack___local_vue_flask_template___George_Dev.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/1c22c627-0219-51af-a79b-97ed6dcadaf6.png)

ユーザー未選択ならインストールしたユーザー全員に送られます。
選択するとその人にだけ送られます。

以上、長くなりましたが問い合わせの送受信システムを作りました。
Slackアプリ開発者に届くと嬉しいです。

## TimeLine for Slackを作っています
こちらは宣伝ですが、TimeLine for Slackというアプリを作っています。
機能概要としては
- 公開チャンネルのpostを一つのチャンネルに全て転送するTimeLineチャンネル機能
- 自分の好きな複数のチャンネルのpostを一つのチャンネルにまとめるミックスチャンネル機能
- postの転送時にDeepL翻訳で希望する言語に翻訳する機能
- Slack解析機能
    - １日にどれだけpostされているのかをグラフ表示
    - 今盛り上がっているチャンネルがどこなのかが分かるランキング機能
    - トレンドアラート機能（DM/チャンネルへのpost)
        - 24時間以内のユーザーpost数ランキング
        - 24時間以内のチャンネルpost数ランキング

実際に、TimeLineチャンネル機能を作って見ていると、社内全体の中でどんなやり取りが成されているのかが分かるようになってきます。オフィスにいると、メンバーの会話から今盛り上がっている話が聞こえてくると思うのですが、Slackでそれができるようになる感じがします。Slackの提唱するDigitalHQがまさに実現するのでは？という印象を受けました。

盛り上がってるチャンネルリストを見るとこんな感じです。
![Slack___Timeline___Leave_a_Nest_Co__ltd_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/460eb3a7-e6f3-5f72-5fac-289632c51da5.png)
今盛り上がってるチャンネルを、1時間〜24時間以内で集計して表示してくれます。
アプリのホーム画面さえみていれば、みんながどこでやり取りを多くしているのかを把握することが出来ます。

## 是非一度インストールしてみてください！
詳細資料はこちら : https://lne.st/wr21
![twitter_446e3bf64ec4ec7c6838b096cf47ca57.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/a4d1d4a0-e388-33f8-3ad9-2a468d930df4.jpeg)

## 関連リンク
- [pythonを使ってリアクティブなWebアプリをお手軽に1分で作りたい](https://qiita.com/geeorgey/items/ace37bd92841c9d1a378)
- [pythonを使ってリアクティブなWebアプリを作りたい【基礎編】](https://qiita.com/geeorgey/items/3f86b207cd412680b835)
- [pythonを使ってリアクティブなWebアプリを作りたい【開発編】](https://qiita.com/geeorgey/items/ea60afe0c44a5f9db483)
- [pythonを使ってリアクティブなWebアプリを作りたい【開発編2】](https://qiita.com/geeorgey/items/961c1d1092ec60bb06bd)
- [pythonを使ってリアクティブなWebアプリを作りたい【開発編3】](https://qiita.com/geeorgey/items/1f5544b12e7d26a1216c)
- [pythonを使ってリアクティブなWebアプリを作りたい【開発編3-2】](https://qiita.com/geeorgey/items/54b4fb22351a3e941cf6)
- [pythonを使ってリアクティブなWebアプリを作りたい【開発編4】パスワードの暗号化](https://qiita.com/geeorgey/items/85905a4772903b180fad)
- [pythonを使ってリアクティブなWebアプリを作りたい【開発編5】Herokuの開発環境と本番環境](https://qiita.com/geeorgey/items/b080617f5332ab7255c4)
- [pythonを使ってリアクティブなWebアプリを作りたい【開発編5】Slack boltの組み込み](https://qiita.com/geeorgey/items/ca2942ff054e30587c78)
- [pythonを使ってリアクティブなWebアプリを作りたい【開発編6】Slack bolt アンインストール時対応
](https://qiita.com/geeorgey/items/0614ea9f64072a33c985)
- [Slackアプリ内で問い合わせの送受信ができる仕組みを作って公開した話](https://qiita.com/geeorgey/items/5091e94943337e4e1781)←イマココ