Google Apps Script 活用ミートアップ #8
2021/11/22 nikkie
始まります!!🙌 フフッヒ
10/15, 16開催の Py thon Con ference JP 2021の座長🇨🇭でした
=PyCon JP 2021の開催に責任を持つ人
スタッフ活動の中で、自分が繰り返しているタスクを 自動化 してきました
決まった期間、Slackで繰り返し投稿
Googleフォームに回答があったことの確認
「Googleフォームの回答を通知」という要件の実装について話します
PyCon JP 2020のスタッフ活動の中で、Pythonで実装しました
2021年の活動の中で、 GASでの実装に切り替え ました
要件「Googleフォームの回答を通知」
Pythonで通知を実装
GASで通知を実装
スタッフ応募、スポンサー応募、レビュアー応募など、至るところでGoogleフォーム を使う
フォームからスプレッドシートに連携する機能もよく使う
Confluence Google Documents(Slides/Sheets/Docs...)
スタッフ用のSlack workspaceがある
Confluence Slack
通知にはIncoming Webhookを使う
curl -X POST --data-urlencode "payload={\"text\": \"Spam ham\"}" \
https://hooks.slack.com/services/...
スタッフマニュアルの記載 に沿って生成
Incoming Webhookの設定ページ内の例を参照
このあと話す、GASでの実装です
要件「Googleフォームの回答を通知」
Pythonで通知を実装 (2020)
GASで通知を実装(2021)
フォームと連携した スプレッドシート を読み取って通知する
この処理を定期的に動かす
各行について 通知済みか否かを記録 するための列を追加
質問A |
質問B |
通知済み |
---|---|---|
1件目の回答A |
1件目の回答B |
◯ |
2件目の回答A |
2件目の回答B |
ライブラリ gspread
でスプレッドシートを読み書きする
通知する必要のある行の分だけ、Incoming Webhookを通してSlackに投稿(urllib)
スプレッドシートを読み取り、通知するスクリプトを AWS Lambda の関数に移植
Amazon CloudWatch Events でLambda関数を定期的に実行する(例:半日に1回)
Slackを見ているだけでGoogleフォームの応募に気付けるようになった🙌
伸びしろは 即時性 (リアルタイムでない)
半日に1回起動する設定なので、通知が最大で半日遅れる
要件「Googleフォームの回答を通知」
Pythonで通知を実装(2020)
GASで通知を実装 (2021)
フォームが送信されたイベントをトリガーに、Slackに通知する処理を実行する
=フォームの応募が 即時通知 される!
Pythonではできないが、Google App Script(GAS)なるものでできるらしい
Pythonと比べたら、JavaScript(GAS)全然スラスラ書けない・・・
先人のアウトプットを参考にする
Qiita Googleformからのslack通知設定方法
Slack通知は、GASからIncoming Webhookにリクエストする
フォーム送信イベントがトリガー: イベントを引数に受け取る関数 を実装
From form - On form submit
でその関数が実行されるようにTriggerを作る
const url = "Incoming Webhook URL";
const options = {
"method": "POST",
"contentType": "application/json",
"payload": JSON.stringify({text: "Spam ham"}),
};
UrlFetchApp.fetch(url, options);
https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetch(String,Object)
From form - On form submit
イベントhttps://developers.google.com/apps-script/guides/triggers/events#google_forms_events
このイベントのプロパティ
source
response
👈 こちらのデータにアクセス
FormResponse
オブジェクトフォームの回答 を表す
getItemResponses()
メソッドで ItemResponse
からなる配列を取得
function onFormSubmit(e) { // From form - On form submit イベントに登録する
const itemResponses = e.response.getItemResponses();
// 続くスライドをお楽しみに
}
ItemResponse
オブジェクト質問文は getItem().getTitle()
で取れる
回答は getResponse()
で取れる
function onFormSubmit(e) {
const itemResponses = e.response.getItemResponses();
const qaPairs = itemResponses.map((formData) => {
let question = formData.getItem().getTitle();
let answer = formData.getResponse();
return [question, answer];
});
}
スタッフ活動中はQiitaの記事の通りで動かしていた(動いて価値を出しているのは正義)
質問文に応じて条件分岐する switch
文、やや変更しづらい
このLTを機に、質問文をキー、回答を値 とする Map
を組み立てるように変更
function onFormSubmit(e) {
const itemResponses = e.response.getItemResponses();
const qaPairs = itemResponses.map((formData) => {
let question = formData.getItem().getTitle();
let answer = formData.getResponse();
return [question, answer];
});
const questionToAnswer = new Map(qaPairs);
const name = questionToAnswer.get("呼ばれたいお名前");
const text = `${name}さんの申込みがありました!`;
// Slackに送る処理を呼び出す
}
フォームの回答通知をPythonに代えて GASにしたことで、通知の即時性 がもたらされた
フォーム送信イベントをトリガーにするので、Pythonスクリプトを定期実行していたような 環境も不要 に
Incoming Webhookのやり方がlegacyになっていることに気付いた
新しいやり方(Slack App作成?) に移行せねば
今回のLTを機にGASのドキュメントを当たる 👉 他のフォームにも流用できるスクリプト完成!
新しいフォームに対してテンプレートを埋める形でGASを作り、他のスタッフも使えるように したい
フィードバック歓迎!もっといいやり方思いついた方は教えてください