GAS + Hangouts Chatで社内シャッフルランチをゲリラ開催した話

# 概要 📔
業務エンジニア経験４ヶ月くらいのヒトガタエンジニアモドキが（ほぼ）一人で`Google Apps Script`(以下、GAS)と`Hangouts Chat`(以下、Chat)でシャッフルランチシステムを構築し、社内でシャッフルランチを開催しました。

今回は、Chatbotを使っておもしろいことをやりたいという手段ありきの発想でしたが、
人を集めるのは厳しいが、イベントを開催してみたい！といった人の参考になればと思い、構築したシステムの概要と、企画から開催まで通しての所感や反省点についてまとめさせていただきます！

実装や設計よりも、構成や企画などの大枠よりの話になります🙇

# 構成 👨‍🔧
システム構成はこのようになっています。
![スクリーンショット 2018-12-20 21.37.33.png](https://qiita-image-store.s3.amazonaws.com/0/206110/6fc0b520-ad2d-3b0f-6224-33ebbf014e19.png)

利用しているのは

- **Hangouts Chat**
- **Google Apps Scpipt**
- **Google スプレッドシート**

となります。
（厳密にいえば、Google Cloud Platformも）

それぞれの役割はざっくり、このような感じです。
**Hangouts Chat**: ユーザーへの通知の送信、ユーザーからのアクションをGASへ受け渡し。
**Google Apps Script**: ユーザーへの通知の送信の実行、ユーザーからのアクションを受け取る、スプレッドシートの書き込み／読み取り、トリガー機能による定期実行の管理など。
**Google スプレッドシート**: DBの代わり。ユーザーへの通知の結果、ユーザーからのアクションの内容を管理。

# シャッフルランチの概要 🍗

流れとしては

1. ユーザーへの参加申込用の投稿を送信
2. ユーザーからの参加申込の受付
3. 参加申込締切（ユーザーへの参加申込用の投稿を削除）
4. グループ割り振り & 通知


## 1. ユーザーへの参加申込用の投稿を送信
![スクリーンショット 2018-12-20 21.52.31.png](https://qiita-image-store.s3.amazonaws.com/0/206110/4079a05b-9761-2704-1ce1-aad0a648d251.png)
**①② GASから参加申込ボタンのついたカード投稿を送信**
 [Google Apps Scriptの日毎のトリガーで時間をもっと細かく設定する](https://qiita.com/sumi-engraphia/items/465dd027e17f44da4d6a)
 こちらの記事を参考に、開催日当日の朝に投稿を送信するように設定しました。

 ボタン付きの投稿については、こちらの公式の記事を参考に作成しました。
 [Google Apps Script bot](https://developers.google.com/hangouts/chat/quickstart/apps-script-bot)
 [Creating interactive cards](https://developers.google.com/hangouts/chat/how-tos/cards-onclick)

**③ スプレッドシートに投稿の送信先一覧を書き込み(送信時にエラーが出た場合は、エラー内容を記録)**
 ユーザー側でGASの実行を承認していないと、送信時にエラーが発生することがあります。
 それを感知できないとつらいので、エラーが起きた場合はエラー文言を記録するようにしました。

## 2. ユーザーからの参加申込の受付
![スクリーンショット 2018-12-20 22.10.45.png](https://qiita-image-store.s3.amazonaws.com/0/206110/e8969358-a5b0-e0c0-6d42-e5d3c84ac0e8.png)
**① ユーザーがカード投稿のボタンをクリック**
 ボタンをクリックされたら、ボタンに設定されているアクションがGASに通知されます。

**② ボタンのアクションを受け取る**
 参加申込用投稿は、
**参加申込** ⇄ **申込キャンセル**
という風にクリックごとに切り替わるようにしました。

なので、GASで今回のユーザーのアクションは申込なのかキャンセルなのかで処理を分岐しました。

**③ スプレッドシートに参加可否を記録**
データは、一行一名で記録しているので
動作としては
参加申込: アクションを起こしたユーザーの行の指定の列に**○をつける**
申込キャンセル: アクションを起こしたユーザーの行の指定の列の**○を削除**
というシンプルな処理になります。

管理しているデータの項目は

- ルームID
- ユーザー名
- メールアドレス
- 参加可否
- エラー情報

です。

## 3. 参加申込締切（ユーザーへの参加申込用の投稿を削除）
![スクリーンショット 2018-12-20 21.52.31.png](https://qiita-image-store.s3.amazonaws.com/0/206110/4079a05b-9761-2704-1ce1-aad0a648d251.png)
**①② GASから参加申込ボタンのついたカード投稿を削除**
 [Method: spaces.messages.delete](https://developers.google.com/hangouts/chat/reference/rest/v1/spaces.messages/delete)
 こちらを参考に、参加申込締切時には投稿を削除し、申込を封じます。

**③ (送信時にエラーが出た場合は、エラー内容を記録)**
 こちらも送信時と同様に、エラーの場合は記録するようにしました。

## 4. グループ割り振り & 通知
![スクリーンショット 2018-12-20 22.41.52.png](https://qiita-image-store.s3.amazonaws.com/0/206110/34ab153c-aa4a-810c-ef9b-c6baabccd922.png)

**① スプレッドシートから申込情報を取得**
 ○の付いている行の以下の情報を引いてきます。

- ルームID
- ユーザー名
- メールアドレス

**② グループ割り振り**
参加者を4名ずつのグループにランダムで割り振ります。
グループごとに、

- グループ名（集合時に確認しやすいように）
- グループのメンバー
- 疑問点などの連絡先

をまとめた文字列を作成します。

**③④ 割り振られたグループと、同チームのユーザー一覧を各ユーザーに通知**
②で作成した文字列を、各ユーザーのグループに応じて通知。

# お悩みポイント🐏
## GASの設計
今までGASではスプレッドシートの操作やリマインダくらいしか行ったことがなく、
一からがっつりしたアプリケーションの開発も行ったことがないので、ファイルの分け方を悩みました。

**唯一知っているMVCに則ろうとしたらぐっちゃぐちゃになりました。**

Modelにスプレッドシートを触る処理を分けて整理できたのはやりやすかったのですが、ViewとControllerの区別があやふやになってしまいました。

ControllerはViewとModelの橋渡しという想定で開発を行っていたら、**トリガー機能で実行される場合はControllerから処理が始まりフローが複雑になってしまいました。**

単純に機能ごとにファイルを分けた方が理解しやすい気がしています。
一人でやってみたいということに固執した結果かと思います。**設計段階で先輩エンジニアに相談してみるべきでした…。**

## 時間帯
- **参加申込用投稿を送る時間**
- **参加申込締切時間**
- **グループ通知時間**
- **シャッフルランチ開催時間**

をそれぞれ決めるのが一番悩みました。

結局、以下のようにしました。
**参加申込用投稿を送る時間**: 始業ちょっと前
→ 朝方では、一番チャットに気付いてもらいやすいタイミングという判断

**参加申込締切時間**: 開催2時間前くらい前
**グループ通知時間**: 開催1時間半くらい前
→ 何か不測の自体が起こっても収拾つけることができるだろう時間の余裕を持ってという理由
  締切から通知まで時間を空けているのは、割り振りが失敗していた場合に手動で対応しようとしていたからです。
シャッフルランチ開催時間: 12:00 ~ 13:00
→ 弊社では割と自由な時間にご飯を食べているので、12時スタート組と13時スタート組で分けるか悩みに悩みました。
  初回で参加人数が読めなかったため、参加人数が割れてしまうことを恐れて12時スタートのみとしました。

## 開催の告知
人が集まらないと開催ができないタイプのイベントなので、告知方法も悩みました。
**Hangouts Chatのbotは招待リンクなどがなく、ユーザーに検索して追加処理を行ってもらう必要があります。**

Chatbotを追加する手順も合わせて伝える必要があったため、口コミで広めるという方法は諦めました。
ポータルサイト上で全社向けに情報を公開できる機能があるので、そこで設定方法のキャプチャをつけて告知を行いました。

# 開催結果 🎉
初回の開催は**無事に終了**し、僕を含めて5名の参加となりました！

参加人数こそ少なかったですが、あまり経験のない個人がイベントを一人で開催でき、なおかつ、今後はトリガーを設定するだけでいつでも開催可能となりましたので、**技術の力ってすげぇな！**と改めて思えました。

# おわりに 🙋‍♂️
筆が遅く、もう少しコードに触れた記事にしようと思っていたのに、大枠の話ばかりになってしまいました…。

業務効率化のためにちょこちょこGASに触ってはいたのですが、Hangouts Chatと連携できるようになって面白いことが色々できるようになり、とても楽しいですね！

今回は色々バグが出てデバッグがつらかったので、
[Google Apps Script用のテストライブラリ「GASUnit」の紹介](https://qiita.com/munieru_jp/items/101ee00c6906847df750)
こちらの記事のテストを入れてみたいです…！

拙い記事ですが、見ていただいてありがとうございました🙇！