突発的に会議を開催する「突然の会議ジェネレーター」を、ZoomとGoogleCalendarとSlackのAPIを使って作った

この記事は、「Qiita Engineer Festa 2022」に参加するために執筆した記事です。

https://qiita.com/official-events/86d8555146e1b14fef24

# TL;DR
* ランダムに社員４人を抽出し、Google CalendarのAPIで空き時間を取得し、ZoomのAPIで会議を作成し、SlackのAPIで通知するBotを作った
* 各APIは基本的にOAuthの仕様に沿っているので、一度作り方を覚えると応用が効いて楽。一回やってみてほしい。
* ZoomのAPIは思ったよりいろんなことができるのでもっと面白いこともできそうだなと思った。
* ただ、Zoomのイベントの取得については欲しい情報が取れなくてちょっと残念。

# 挨拶と背景
こんにちは、[株式会社dott](https://thedott.io/)でエンジニャー🐱をしているHALと申します。

弊社は社員数が二十数名で拠点が東京と福島県にあるのですが、自分は長野に住んでいたり、仙台や札幌に住んでいるメンバーがいたりと、フルリモートでの仕事をしているメンバーがたくさん・・・というかほとんどになっています。

コロナ禍の前からそんな働き方をしている会社なので、特にフルリモートでも不都合のないような文化ができており、比較的うまく仕事を回せている会社じゃないかなと思っています。

フルリモートだとどうしても必要なコミュニケーションしか取らず、なかなか相手の人となりが掴みづらい、みたいな課題が発生しがちですが、そこもSlackでのライトなコミュニケーションや、週に１、２度状況を共有したり雑談をする時間が取られているので、うまくやれていると思います。

# コミュニケーションの課題
とはいえ課題が全くないわけではなく、どうしても同じ仕事をしているメンバーとは仲良くなりやすいけど、そうでないメンバーは直接コミュニケーションを取る機会は限られる、という問題があります。

リアルなオフィスがあれば、ちょっと休憩した時間に雑談したり、遠目に仕事をしている様子を見たりと、その人の雰囲気を知る機会はちょくちょくあるわけですが、フルリモートではそれは難しいです。
仕事上大きく問題になっているわけではありませんが、もうちょっとなんとかできたらなぁと考えていました。

恐らくこれは、リアルなオフィスでも、階が違っていたりビルが違っていたりすると、同様に起きる問題だと思います。
全ての社員と仲良くなる必要はないでしょうが、何かの機会に一緒に仕事をすることになった時、なんとなくでも知っている人との方が、仕事を進めやすい、ということはあるでしょう。

そんな課題を多少解決してくれるかもしれない？ものとして、「突然の会議ジェネレータ」を作りました。

# 「突然の会議ジェネレーター」とは
こんなSlack Botです。

![スクリーンショット 2022-06-06 9.54.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571256/30c60c98-31a1-6aab-4b17-249e65f9fe71.png)

* 指定した時間の中から３０分選択する（弊社の場合大体みんながいるのが11時〜１8時くらいの中から連続した３０分）
* 特定のチャンネル参加者の中から選択した３０分に予定が空いているメンバーをランダムに4名を選ぶ（Google Calendarから予定を取得する）
* Zoomミーティングを自動作成し、Slackで会議案内を送りつける

半ば強引に雑談するための時間を設けることで、普段話す機会のない人とも会話する時間を作ろう！というものです。
とりあえず試作で作った状態なので、いくつか検討しなければならないこともあります。

* 開催頻度、開催時間（30分）はどれくらいが適切か？
* 開催する際の人数は何人がベストか？

また、こんな機能もつけると面白そうだなぁと妄想したりしています。

* 雑談のテーマをランダムに選んでくれる
* 話のネタとしてミーティングの開始時に投票機能でお題に投票させる（Zoom APIの使用）
* メンバーのDMに対して会議案内を送ることで、誰が参加してくるかミーティングに参加するまでわからない「ミステリー会議」

※この方法が向いているチームと向いていないチーム、好むメンバーと好まないメンバーがいると思います。
　導入の是非や導入方法については各チームで相談して検討してくださいね！

# 実装方法についての抜粋
実装を全て説明すると長すぎるので、かいつまんで説明します。
ソースコードはこちらに上げてあるので、書かれていない部分はこちらも見てみてください。

https://github.com/hareruya-maro/sudden-meeting-generator?a=a

## Slack Botの作成
Slack Botの作成についてはいろいろな記事で解説してくださっている方がいらっしゃるので、詳細は割愛します。
使用するのはBot Tokenのみで、以下の権限を付与します。

* app_mentions:read　...　Google Calendar/ZoomとのOAuth連携用URLを取得する際にメンションを利用します。
* channels:read ... チャンネルの参加者リストを取得するために利用します。
* chat:write ... 会議案内やOAuth連携用URLを通知する際に利用します。
* users:read ... ユーザーのメールアドレスを取得するために利用します。
* users:read.email ... ユーザーのメールアドレスを取得するために利用します。

ユーザーのメールアドレスは、Google Calendarでユーザーの空き時間を取得する際のカレンダーIDとして利用するため取得しています。
Slackの登録メールアドレスとGoogle Calendarのアカウントが異なるとこの方法は使用できないので注意してください。

また、メンションのイベントを利用するため、Event Subscriptionの設定もしておきましょう。

## Google Calendar APIの利用準備
ユーザーの空き時間を調べるため、Google Calendar APIのfreebusy APIを利用します。

https://developers.google.com/calendar/api/v3/reference/freebusy/query

このAPIを利用すると、指定したカレンダーの予定の空いている時間帯（free）と予定の入っている時間帯（busy）が取得できるようです。
ただ、予定の登録の際に「予定あり/予定なし」のどちらを選ぶかによって取得できるものが変わるようです。
「予定あり」のみを使っている場合はbusyのみ取得できるので、freeは取得できないことが多いかな？という感じです。

とりあえず、Google Calendar APIを使うため、APIやOAuthの設定が必要です。
以下の設定をGCPコンソールで行います。

* Google Calendar APIの有効化
* OAuth２.0クライアントの作成（ウェブアプリケーション・firebaseプロジェクトを作った際のデフォルトクライアントでも可）
* OAuth同意画面の作成

詳細な手順は割愛します🙇
この辺とか、わかりやすくて参考になるかと思います。

https://www.y-hakopro.com/entry/google_oauth_api

## Zoom APIの使用準備
Zoomミーティングの作成はZoom APIを使用します。
今回はOAuth Appとして作成しました。
こちらの記事を参考に実施しています。

https://qiita.com/yosuke-sawamura/items/514e791afb4cb02fd956

利用しているscopeとしては今回は「meeting:write」のみを利用しています。
今回は社内でテストしてみている段階ですので、パブリッシュのための準備などは行っていません。
公開できるような設定にするにはデータの持ち方などもうちょっと考慮が必要そうです。

## firebaseプロジェクトの準備・デプロイ
今回、botを実際に動かすのはfirebase functionsを使用しました。
そのため、firebaseプロジェクトの作成が必要となります。
また、functionsで外部APIを利用するため、プランはFreeからBlaze（従量課金）への変更が必要ですので注意してください。
（テストで使う程度なら、お金はほとんどかからないと思いますが・・・）

また、認証情報の保持にfirestoreを利用していますので、そちらも有効にしておく必要があります。
そのほかは特に特殊な設定などは使用していないのですぐにデプロイできると思います。

なお、デプロイ時にfirebase functions:config:setを使用して幾つかの値を設定する必要があります。

* slack.bot_token
* slack.target_channel（現状、チャンネル固定してます。）
* calendar.client_id
* calendar.client_secret
* zoom.client_id
* zoom.client_secret

これらを設定した上でdeployするようにしてください。

# botの使用方法
botの使用方法は以下の通りです。

* Slackでどこかのチャンネルにbotを追加する
* botにメンションを送る
* 送られてきた２つのURLにそれぞれアクセスし、Google CalendarとZoomへの連携を設定する

![スクリーンショット 2022-06-06 12.09.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571256/fa3122c6-7f28-cfeb-8716-31eb83bda1c9.png)

以上で準備は完了です。
あとは平日９時になったら突然の会議案内が送られてくるでしょう。
なお、テストのためにcurlで随時起動することも可能です。

# Zoom APIを使ってみた印象
今回、ZoomのAPIを初めて使ってみました。
（Slack/Google Calendarは過去に使ったことがあった）
使い始めるにあたって、OAuthを利用したアプリを作ったことがあれば、さほど難しくなく使うことができました。
OAuthは一度何かで実装してみると、いろいろなAPIで利用できるので良いですね。

ミーティングの作成のほか、ブレークアウトルームの制御や投票機能の利用などもAPIからできるので、うまく活用するともっと色々できそうだなと感じました。
特に、よく使うミーティングの設定を自動化できると、ミーティング開始時の設定漏れや間違いのストレスを軽減して、ミーティングそのものに集中することができるので良さそうだなと感じました。
この辺はGoogle Meetにはないメリットなのでもっと活用できると良いなぁと思います。

また、イベントもいくつか用意されているため、この辺もうまく使えそうです。
ミーティングへの参加者の追加時に動作させる機能や、ミーティング終了時に自動的にメッセージを送るなど、こちらもアイデア次第で色々活用できそうです。

ただ、イベントについてちょっと残念だったのは、ユーザーに紐づいたイベントが少ないというところですね。
今回、当初は自分がZoomミーティングに参加・退出した際に、家族に通知を送るような機能を作ろうとしていました。
しかし、~~ユーザーのミーティングへの参加・退出をサブスクライブすることはできず~~、あくまでも「ミーティングに誰かが参加した」というイベントのみでした。
また、この場合は会議を作成したホストが、作成したアプリをインストールしている必要があり、自分がホストになったミーティングは問題ないですが、お客さんがホストとなっているミーティングでは利用できません。

ミーティングを中心に据えた思想のサービスなので仕方ないかもしれませんが、ユーザーごとのイベントを取得しやすくなると、
さらに活用できる幅が広がって良いなぁと感じました。

2022/06/08追記
「ユーザーのミーティングへの参加・退出をサブスクライブすることはできず」と書いていましたが、`user.presence_status_updated`のWebhook Eventで取得できるかも？と言うことに気づきました。
今度はこれを使ってみようと思います。

# 最後に
今回はZoom / Google Calendar / Slackの３つのAPIを活用して（ネタ的な）botを作成しました。
最近は多くのサービスでAPIを公開していて、組み合わせると意外と面白いことができると思います。

普段仕事やプライベートで使っているサービスのAPIがあるか、どんなものが用意されているかを調べてみて、自分用のカスタマイズを施した連携アプリやbotを作ってみるのはいかがでしょうか。
自分の開発についての知見も広められますし、ちょっと便利になったりして一石二鳥になりますよ！