mofmofでは毎日朝会をやっていて、発言の順番は全メンバーをシャッフルしたものをGASでSlack通知してます。これの課題が「全メンバー」って部分で、稼働日でないメンバーや子供の送迎や通院などで朝会欠席するメンバーも含まれてるんですよね。
なので「この人とこの人いる?あ、いない?じゃあ飛ばして…ああ、自分の番か」という大変な認知負荷が朝っぱらからかかることになっています。つらい。
つくったもの
- ZoomのWebhookで、Zoomに人がくるたびFirebaseのFunctionsを呼ぶ
- 来た人をFirestoreに突っ込んでおく
- スケジュール設定しておいたFunctionsからSlack通知する
といった具合です。現状の致命傷は、スケジュール通りに起動してはいるものの通知が遅いってことですね。 朝会は9:45-10:00なんですが、通知が来るのが9:50なんですよね。遅いでしょ…。あとサボったのでシャッフルしてないです。
それはさておき、ZoomのWebhookやFunctionsの紹介をしていきます。
Firebase
Zoomの設定をするためにWebhookの通知先が必要なので、先にFirebase側の作業をしておきます。
一般的なセットアップの手順は省略します。FunctionsとFirestoreが使えるようにしてください。Functions使うためには従量課金プランにしておかないといけないので、その点だけご注意ください。
パッケージとして dayjs
と node-fetch
を使うので入れておきます。functionsディレクトリで以下のコマンドを実行してください。
npm install dayjs npm install node-fetch@2
そしたらindex.jsを編集しましょう。
const functions = require("firebase-functions"); const admin = require("firebase-admin"); const dayjs = require("dayjs"); const fetch = require("node-fetch"); admin.initializeApp(); const db = admin.firestore(); exports.add = functions.https.onRequest((req, res) => { const headers = req.headers; if (headers.authorization !== "<あとで埋めます>") { return res.status(403).send("Invalid"); } const participatedUserName = req.body.payload.object.participant.user_name; functions.logger.info("userName", participatedUserName); const targetDate = dayjs().format("YYYY-MM-DD"); db.collection("dates").doc(targetDate).get().then((documentSnapshot) => { if (documentSnapshot.exists) { const participated = documentSnapshot.data().users; documentSnapshot.ref.set({ users: [...participated, participatedUserName], }); } else { db.collection("dates").doc(targetDate).set({ users: [participatedUserName], }); } }); res.send("completed!"); }); exports.notify = functions.pubsub .schedule("every day 9:47") .timeZone("Asia/Tokyo") .onRun((context) => { console.log("running"); const targetDate = dayjs().format("YYYY-MM-DD"); db.collection("dates") .doc(targetDate) .get() .then((querySnapshot) => { const participants = []; querySnapshot.data().users.forEach((user) => { participants.push(user); }); fetch("<あとで埋めます>", { headers: { "Content-type": "application/json" }, body: JSON.stringify({ "text": participants }), }, function (err, res, body) { console.log(body); }); }); return null; });
一旦これでOKです。ZoomやSlackから発行される部分は<あとで埋めます>になってます。 addのほうはうまいこと参加者をFirestoreに突っ込み、notifyのほうはいい感じにSlack通知をしてくれます。
addのエンドポイントがほしいので、デプロイしておきましょう。
firebase deploy --only functions
デプロイ完了したら https://ドメイン/~/add
というURLが発行されるはずなので、それを控えておきます。
Zoom
Zoom App Marketplaceからログインします。 https://marketplace.zoom.us/
したらヘッダから Build App
をクリックしましょう。
開いたページの、Webhook OnlyのCreateをクリックします。モーダルが出てくるので適当に名前を埋めてください。
このあたりは適宜埋めてください。
Event Subscriptionsのスイッチをクリックしてアクティブにしましょう。
したらEventsを追加します。 Add Events
をクリックするとモーダルが表示されるので、Meeting > Participant/Host joined meeting にチェックを入れます。
先ほどfunctionsをデプロイしたときに発行されたURLをここに入れましょう。ここまでの作業が終わったらこんな画面になっているはずです。できたらSaveしてください。
するとValidation Tokenが発行されるはずです。
これをコピーして、addの冒頭に入れてあげましょう。
exports.add = functions.https.onRequest((req, res) => { const headers = req.headers; if (headers.authorization !== "<あとで埋める>") { // ここです return res.status(403).send("Invalid"); }
以上で完了です。再度デプロイしておきましょう。
このWebhookは現在ログイン中のZoomアカウントで有効になっているので、自分でZoomを立ち上げてmeetingに入ってみましょう。Firestoreのdates > YYYY-MM-DD > users に自分の名前が入るはずです。
Slack
このあたりを参考に、Webhookを設定してください。発行されたURLをfunctions > notify > あとで埋めます に設定すれば完了です。
fetch("https://hooks.slack.com/services/~~~", {
これで時間になったらFirestoreを読んでSlack通知してくれるFunctionsが完成しました。
以上です!