開発チームメンバーの情報発信を後押しする為にやってみたこと

## はじめに

社内のチャットなどで雑談や技術情報を共有するチャンネルを作っていることもあると思います。 
弊社でもそんなチャンネルがあるのですが、ただ部屋を用意するだけでは一部の人が投稿するだけで、参加はしているけど直接質問でもされない限り発信をしない方も一定数は存在しています。

自ら発信しない人の中には、ただ業務として部屋に参加しているだけだしそこまで関わりたくないという人もいれば、人に聞かれれば答えるけど自分からは積極的に発信しない人など、発信しない(しづらい)理由はその人ごとにあると思います。[^1]

[^1]: そもそも心理的安全性が低い環境だと...というのはあるかと思いますが、今のチームは低い状態ではないです。オンラインで会話する時も話のタネがあれば雑談で盛り上がったりしている状態なのでどちらかというと高めな方だと思っています。


今回は**人に聞かれれば答えるけど自分からは積極的に発信しない人**を後押しする為にSlack Appを作ったという話になります。


## つくったもの

とりあえずSlackにした理由とかはあとにして、作ったものはこちらです。 


部屋に追加した Bot(SlackApp)が部屋に参加してるユーザーにランダムで DM を送ります。
![sa1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/0a743e63-eb35-f975-b1b9-cbcaeb7d4ad9.png)
入力欄に回答を入力して投稿するとメッセージが回答済みのメッセージに入れ替わります。
投稿先への遷移ボタンと間違った場合の削除ボタンを加えています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/784cdd31-a484-548b-60d7-877f85c64d95.png" width="360">
メッセージが切り替わったタイミングで部屋にもメッセージが投稿されます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/f8793a6c-3b00-74f2-5965-29ab7b07529e.png" width="360">
---
**当初、開発者だけで運用するつもりだったのでBolt.jsで作っていましたが、デザイナーチームの人も使ってみたいということを言われたので質問をスプレッドシートで管理するように変更しました。**

新しい方ではBolt.jsを削除してclaspでの管理に書き換えていたりボタンイベントを追加しています。

またGASでSlackのアクションイベントをフックする際の`Verification Token`の検証については[Google Apps Script (GAS) で Slack 連携を実装する前に知っておくとよい 5 つのこと](https://qiita.com/seratch/items/2158cb0abed5b8e12809)の記事を参考にさせていただきました。

作り直したプロジェクトはこちらです。
[Chatty-for-GAS](https://github.com/mittsu333/Chatty-for-GAS)

前回作った時はREADMEに設定手順を箇条書きで書いていたので分かりづらかったと思い、手順を書き直しています。

<details><summary>設定手順を表示する(長いです)</summary><div>

## 環境

-   node v16.0.0
-   TypeScript v4.5.4
-   clasp v2.4.1

## 設定

### Slack App の登録

[Slack App](https://api.slack.com/apps)でアプリ作成(`Create New App`)する
**作成時に `From an app manifest (BETA)` を選択しておくと yml 貼るだけで権限登録の手続き減るのでおすすめです**

![s1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/77e3c13a-e5c7-2c24-b37c-7d9d59318380.png)

対象のワークスペースを選択します

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/8afef392-7d96-aa7a-fa50-ba07033cd166.png" width="360">

次に下の yaml を貼り付けて権限周りなどの設定の登録をします

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/df08e863-5295-50ac-5919-7f516211b16b.png" width="360">

## yaml の中身

**`request_url`の値は後に Google Apps Script の公開 URL に変更します。**

```.yaml
display_information:
  name: Chatty
features:
  bot_user:
    display_name: Chatty
    always_online: true
oauth_config:
  scopes:
    bot:
      - chat:write
      - im:history
      - im:read
      - im:write
      - mpim:read
      - mpim:write
      - channels:history
      - channels:read
      - groups:history
      - groups:read
      - groups:write
settings:
  interactivity:
    is_enabled: true
    request_url: https://script.google.com/
  org_deploy_enabled: false
  socket_mode_enabled: false
  token_rotation_enabled: false
```

登録が終わったら`Create`します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/332e9f08-bf9d-ad07-8de7-32745706136c.png" width="360">

後でスプレッドシートの環境変数に登録する 2 つのトークンを作成、保存しておきます。

### Slack Bot Token 取得

最初に Slack の Bot トークン(`xoxb`で始まるトークン)を取得します。
サイドメニュー -> `OAuth & Permissions` -> `OAuth Tokens for Your Workspace` -> `Install to Workspace`で作成できます。


![s5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/9f737885-6b39-11b2-a40b-7de27d196583.png)

ワークスペースに追加していきます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/2e3a4d73-cb9d-c408-d49f-0a2f4657543d.png" width="360">

無事にワークスペースに追加されるとトークンが取得できます。

![s7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/40d505d2-2f0e-6b71-97be-6f635b985b05.png)

### Slack Verification Token 取得

次に`Verification Token`を取得します。
これは最初から生成されているので値をコピーするだけです。
サイドメニュー -> `Basic Information` -> `App Credentials` -> `Verification Token`から取得できます。

![s8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/c4ddd6f4-26d1-0a23-b21d-9feb641dc900.png)

### Google Apps Script API を有効にする

Google Apps Script API が有効でなければ有効化しておく必要があります。
[ここからオンに切り替え](https://script.google.com/home/usersettings)できます。

![s9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/1f177480-df7f-4dc2-5ae7-eb19d5436003.png)
![s10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/312ab853-0f96-f642-a084-538ff050c7cc.png)

### clasp インストール と ログイン（初回のみ）

コードの管理がしやすいように[clasp](https://github.com/google/clasp)を使用しています。

インストール

```
npm install -g @google/clasp
```

ログイン

```
clasp login --no-localhost
```

URL が出てくるのでアクセスして許可して、出てきたコードをコマンドプロンプトに入力します。
成功するとユーザールート階層に`.clasprc.json`が作られます。

### スプレッドシートとスクリプトプロジェクトの作成

このプロジェクトを clone してプロジェクト直下で  
次のコマンドを実行するとマイドライブの下にスプレッドシートが作成されます。

```
clasp create --type sheets
```

![s11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/689f7719-1a7d-5213-3a50-9adf21590395.png)

成功するとスプレッドシートとスクリプトの URL が表示されます。

### シートの編集

シートが作成されたら質問を記入します。
**A 列の質問を読み取る**ようにしています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/85b995b9-6f49-f2e9-04ec-cd27d201c14b.png" width="360">

### プロジェクトの push と確認

まだ Apps Script 内も空なのでプロジェクトを push していきます。
clasp は TypeScript にも対応しているのでこのまま push すると変換してくれます。

```
clasp push
```

シートの拡張機能からか、次のコマンドでスクリプトページを開く事も可能です。

```
clasp open
```

### スクリプトプロパティの登録

古いエディターの方で設定できるので切り替えていきます。

![s13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/d5cade78-215b-b4a3-09f3-d27c63942c0d.png)

メニューからプロパティの各項目を設定していきます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/1da0f529-9cfb-48ee-b2c4-0cdfb5785c8c.png" width="360">

-   SLACK_BOT_TOKEN
    -   [Slack Bot Token 取得の項目を参照](https://qiita.com/c48e615ab53d24587079#slack-bot-token-%E5%8F%96%E5%BE%97)
-   SLACK_VERIFICATION_TOKEN
    -   [Slack Verification Token 取得の項目を参照](https://qiita.com/c48e615ab53d24587079#slack-verification-token-%E5%8F%96%E5%BE%97)
-   CHANNEL_ID
    -   投稿先のチャンネル ID メニューの`Open channel details` -> `about`の一番下などから取得できる`C0`から始まる文字列になります。
-   BOT_ID
    -   Slack App の詳細で Bot の MemberID が取得できます

Bot の MemberID 取得場所

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/25a1c5af-932a-7acc-c344-b11cb8c14f5c.png" width="360">

設定ができたら更新します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/93e7d3c3-3f56-1ec0-ac80-29fb31d7e4f8.png" width="360">

### GAS の公開

メニュー -> 公開 -> ウェブアプリケーションとして導入... を選択します

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/314428ff-3332-a313-b37b-e53fd0f7af15.png" width="360">

デプロイ画面でバージョンやアカウント、Who has access to the app の項目は`Anyone, even anonymous`を選択します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/ef64ba1b-680c-99ba-b4c2-5c84cf5790e2.png" width="360">

初回の公開時には許可の確認が求められます。
警告などが表示されますが、内容を確認しながら赤枠の項目から許可をしていきます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/86307d92-036f-e593-e1e6-2dbff58d477f.png" width="360">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/c3afb40e-b424-df68-954e-3da48023a583.png" width="360">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/bc7b1a77-045f-66bd-7fe2-dbb80ac13962.png" width="360">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/a5b9bca8-122d-4bec-486d-88dd9a5ded88.png" width="360">


無事に公開が完了すれば URL が取得できるのでこれを**[Slack App の登録の request_url](https://qiita.com/c48e615ab53d24587079#yaml-%E3%81%AE%E4%B8%AD%E8%BA%AB)**に設定していきます。
yaml 内のrequest_urlの値を上書きして保存します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/fbea4794-6cfb-0258-f932-552f1304459d.png" width="360">

### 動作確認

チャンネルを作成して、自分と Slack App を追加して関数（postQuestion）を実行すると冒頭の流れになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64426/5cd73bdc-f53c-4b3f-efab-8a54b132d123.png" width="420">

無事に動作しているなら、あとは定期実行などの処理を設定すれば完了です。

</div></details>

<details><summary>前に作ったBolt.jsのSlackApp</summary><div>

## 開発

Slack Appの作成は初めてでしたが、公式ページの入門ガイドで動きを把握してから、GitHubのTypeScriptで作られたプロジェクトのサンプルをベースに作りました。

[Bolt 入門ガイド](https://slack.dev/bolt-js/ja-jp/tutorial/getting-started)
[GitHub bolt-js/examples/getting-started-typescript](https://github.com/slackapi/bolt-js/tree/main/examples/getting-started-typescript)

[Chatty](https://github.com/mittsu333/Chatty)
Slack Appの画面で登録設定さえしてもらえれば手元で動作確認は可能です。
手順はREADME.mdに記載しています。
質問を自分たちで編集したり、社内で運用する目的で作成したのでSlack Appディレクトリに公開はしていません。

あと、これは試作段階で用意したサンプルになります。
実際に運用しているプロジェクトは別にあります。

</div></details>

## なぜSlackなのか

弊社はフルリモートワークなので、最初はチームの雰囲気を作りながら情報交換する流れを作れるかなと思い、[Gather](https://www.gather.town/)や[Teamflow](https://www.teamflowhq.com/)などのバーチャルオフィスツールを導入しようかと考えましたが、開発メンバーはそれぞれ別のプロジェクトに参加していて、ミーティングの時間帯が違うことや、プロジェクトが忙しい時は参加するのは難しいかもという声も多くありました。
その中で社内で普段使用しているSlackでの情報共有が一番負担が少なくできそうという考えは共通していたので、Slackで情報交換する場をもっと活性化させていこうと考えた事がきっかけです。

## Collaとの出会いと開発動機

活性化させるには情報発信に抵抗がある人たちにも投稿してもらいたいが、投稿依頼などするのも何か違うなと考えていたところ、弊社では元々別の雑談部屋に[Colla](https://colla.jp/)を導入しているのを思い出し、人と比べてBotからの質問なら無視をしても気にならないし、**質問された事を答えているという体**なので何もないところから投稿するよりも心理的な負担が少なくなるかなと考えました。

雑談でのコミュニケーション活性化ならCollaの質問のバリエーションや機能が豊富で優れているのですが、質問パターンに雑談だけでなく技術に関わる質問も用意したかったのとCollaは回答を一定時間ストックするような仕様があった為、社内用に作成することにしました。

## 運用ルール

ざっくり決めたルールはこんな感じです。

* 質問Botはcronで週１回の営業日にチャンネル参加メンバーの中からランダムで数名抽出する（毎回全員に送るようなことはしない）
* 質問はランダムで選ばれるが、他の質問を要求できるので答えれる質問だけに答えれば良い
* Botからの質問は答えたいときに回答してOK（気分が乗らない時は無視しても良い）

ゆるく情報交換できる文化の土台ができればとよいと考えているので、部屋に参加してもらう以外の強制は極力しない方針にしています。  
こういった事を始めるときには、ある程度の強制力もないと難しく失敗してしまうこともあるのですが、個人がガチガチに決めたルールで作られた場よりも、少しの決まりだけで時間をかけながら徐々に自分たちに合った形ができあがってくる方が理想に近かった為、ゆるいルールで進めています。

## 運用してみて

導入したばかりなので結果はこれから見えてくると思います。
ある程度は作り替えていければと考えていますが、チームに合わなければ全く別の方法に変更もしていくと思います。

## おわりに

弊社もこれからずっとリモートワークが続いていくので全てのことがオンラインで成り立つように今後も色々と取り組んでいきたいです。
今回の事もこれだけで全てが上手くいくとは考えていませんが、目に見えるところから少しづつ変化をつけていければと思います。