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
https://slack.com/intl/ja-jp/help/articles/115005265063-Slack-での-Incoming-Webhook-の利用
このあたりを参考に、Webhookを設定してください。発行されたURLをfunctions > notify > あとで埋めます に設定すれば完了です。
fetch("https://hooks.slack.com/services/~~~", {
これで時間になったらFirestoreを読んでSlack通知してくれるFunctionsが完成しました。
以上です!