リマインダーが欲しい!
「毎朝10時05分に、固定メッセージのリマンダーをGoogleチャットに自動で流したい」
ある日、こんな相談が来ました。
よし!じゃあ
1. GAS(Google Apps Script)でGoogleチャットにメッセージを流すコードを作る
2. GASのトリガーで自動実行をセット
これでいけるでしょ😌
トリガーで「05分」が狙えない・・
1. GAS(Google Apps Script)でGoogleチャットにメッセージを流すコードを作る
これは何度も作ってる(使い回している)コードがあるから簡単。
function post2chat() {
const webhook = 【Google Chatのアプリと統合 > Webhookから取得したWebhook URL】;
const sendMessage = 【Google Chatで投稿したいメッセージ】;
// 以下おまじないとしての固定コード
const payload = {
"text": sendMessage
}
const options = {
"method": "POST",
"headers": { "Content-Type": "application/json; charset=UTF-8" },
"payload": JSON.stringify(payload),
"muteHttpExceptions": true
}
UrlFetchApp.fetch(webhook, options)
}
2. GASのトリガーで自動実行をセット
次に、2のトリガー設定を・・・
って、考えたら日付ベースのタイマーの1時間毎だと、5分とか狙った「分」に実行できないぞ😵
「05」分の対策
日付ベースのタイマーでトリガーがセットできない。
じゃあ、「分」を狙ってのトリガー実行は出来ないかというと、そうでもない。
特定の日時のトリガーなら YYYY-MM-DD HH:MM で指定できるので05分を狙うことが可能。
ただ、それだと日付も指定しているので1回きりのトリガーになってしまう。
無理やり分ベースのタイマーで出来ないこともない。分ベースのタイマーは1分毎の実行も可能なので
- 分ベースのタイマーで1分間隔のトリガーにして毎分実行
- 毎分のGAS実行時に、狙った時間(今回であれば10時05分)以外は、GASの処理をやめる
これなら狙った時間に実行できるけど、無駄にGASを実行し続けるのもなんだかなぁ・・🤔
そう思ってネットを検索してみたら、こんな記事が!
GASで特定時刻を時間指定して繰り返し定期実行するトリガー登録方法!
なるほど!特定の日時のトリガーを毎日作るのか。
トリガー操作を実装
トリガーを作成する関数
では、まずさっそく特定の日付を設定するGASを作ってみる。
function setTrigger() {
const today = new Date();
// 時刻を指定
today.setHours(10);
today.setMinutes(5);
// トリガーにセット
ScriptApp.newTrigger(post2chat).timeBased().at(today).create();
}
8行目は「ScriptApp.newTrigger(【実行する関数】).timeBased().at(【実行日時】).create(); 」という形になります。
【実行する関数】で指定するのは、上で作ったGoogle Chatに投げる post2chat です。
次は、post2chatを実行する【実行日時】の設定です。
毎日実行して欲しいので、まず2行目の「const today = new Date();」でGAS実行の日時を取得します。
これで実行日(今日)の日時が取得できます。
次に 10時05分 に実行して欲しいので、new Date() で取得した today の日付を4行目(today.setHours(10);)、5行目(today.setMinutes(5);)で変更します。
これで、その日の10時05分実行のトリガーが作られるはずなので、この setTrigger 関数を実行してみましょう。
実行してから、トリガー画面を確認すると
トリガーができている!
一応中身も見てみると
ん???時間が 10:05 になっていない😵(ちなみにセットされている21:19はsetTriggerを実行した時間)
なぜぇぇぇ?と思いましたが、どうやら過去の日付をセット(今日の10:05を指定したので過去)した場合は、強制的に今の時間になるようです。
なのでsetTriggerは完成ということになります。
トリガーを削除する関数
トリガーが作成できればOKなのですが、上の参照したサイトにも書いてあったように、作りっぱなしにすると1度きりで使用済みのトリガーがどんどん増えてしまいます。
そのため実行したトリガーは消す処理を入れましょう。
function deleteTriggers() {
// 既存トリガーをすべて取得
const triggers = ScriptApp.getProjectTriggers();
// トリガーをすべて削除
for (let i = 0; i < triggers.length; i++) {
ScriptApp.deleteTrigger(triggers[i]);
}
}
3行目の「const triggers = ScriptApp.getProjectTriggers();」で設定してあるトリガーを取得します。
取得したトリガー(triggers)にいくつトリガーが入っているか分からないので、5行目〜7行目でトリガーを一つずつ取り出して、6行目の「ScriptApp.deleteTrigger(triggers[i]);」で削除します。
トリガーの削除は以上です。
完成・・・・してない!?
最後に上で作った、トリガーを作る関数と削除する関数自体を毎日実行させる必要があるので、トリガー指定できるように関数を作ります。
function myFunction() {
// トリガー作成前にトリガーがあったら消す
deleteTriggers()
// トリガーを作る
setTrigger()
}
この myFunction を毎日実行するトリガーを作ったら完成!
・・・いや、違う。
その状態で deleteTriggers を実行したら、毎日実行するこのmyFunctionのトリガーも消えちゃう。
というわけで、deleteFunctionで消すトリガーを、特定の日時のトリガーだけ消すように変更します。
function deleteTriggers() {
// 既存トリガーをすべて取得
const triggers = ScriptApp.getProjectTriggers();
// 既存トリガーをすべて削除
for (let i = 0; i < triggers.length; i++) {
if(triggers[i].getHandlerFunction() === 'post2chat') {
ScriptApp.deleteTrigger(triggers[i]);
}
}
}
setTrigger 関数で指定した実行する関数名(post2chat)は、トリガーオブジェクトの getHandlerFunction で取得できます。
そのため、6行目のように getHandlerFunction が post2chat の時のみ削除するようにします。
よし、ようやく完成。
と思ったら、このままだと休みの日も実行されて、チャットに飛んじゃうので平日のみ動くようにします。
平日判定は、土曜、日曜の判定と、祝日はGoogleカレンダーの日本の祝日を利用すると実装できます。
まず土日判定。
function myFunction() {
const today = new Date();
if(today.getDay() !== 0 || today.getDay() !== 6) {
deleteTriggers()
setTrigger()
}
}
getDay() をすると曜日情報が取れ、曜日は以下の数値として入っています。
日曜 | 月曜 | 火曜 | 水曜 | 木曜 | 金曜 | 土曜 |
0 | 1 | 2 | 3 | 4 | 5 | 6 |
なので、getDayの結果、日曜日の0か土曜日の6以外で実行すれば、平日での実行となります。
次に祝日ですが、祝日は
const calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com');
このコードで、日本の祝日カレンダーを取得でき
const events = calendar.getEventsForDay(today);
このコードで、日本の祝日カレンダーの中の指定日(=今日)のイベントを取得します。
このカレンダーにはイベントとして、祝日(例えば、海の日とか)情報が入っています。
そのため、取得した events の中身を確認し、中身が空(=祝日情報がない)と祝日ではないとなります。
function myFunction() {
const today = new Date();
const calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com');
const events = calendar.getEventsForDay(today);
if(events.length === 0) {
// トリガー作成前にトリガーがあったら消す
deleteTriggers()
// トリガーを作る
setTrigger()
}
}
ということで、土日祝を合体させると以下のようになります。
function myFunction() {
// 土日祝を確認
const today = new Date();
const calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com');
const events = calendar.getEventsForDay(today);
// events.lengthがあれば土日祝なのでトリガー設定を実行
if(events.length === 0 || today.getDay() !== 0 || today.getDay() !== 6) {
// トリガー作成前にトリガーがあったら消す
deleteTriggers()
// トリガーを作る
setTrigger()
}
}
完成!
全コードは以下になります。
この myFunction を毎日任意の時間の日付ベースのタイマーのトリガー設定をすれば完成です!
お疲れ様でした!
function myFunction() {
// 土日祝を確認
const today = new Date();
const calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com');
const events = calendar.getEventsForDay(today);
// events.lengthがあれば土日祝なのでトリガー設定を実行
if(events.length === 0 || today.getDay() !== 0 || today.getDay() !== 6) {
// トリガー作成前にトリガーがあったら消す
deleteTriggers()
// トリガーを作る
setTrigger()
}
}
// トリガーをセット
function setTrigger() {
let today = new Date();
// 時刻を指定
today.setHours(10);
today.setMinutes(5);
// トリガーにセット
ScriptApp.newTrigger('post2chat').timeBased().at(today).create();
}
// 既存トリガーを取得して削除
function deleteTriggers() {
// 既存トリガーをすべて取得
const triggers = ScriptApp.getProjectTriggers();
// 既存トリガーをすべて削除
for (let i = 0; i < triggers.length; i++) { if(triggers[i].getHandlerFunction() === 'post2chat') { ScriptApp.deleteTrigger(triggers[i]); } } } function post2chat() { // 開発テスト用 const webhook = 【Google Chatのアプリと統合 > Webhookから取得したWebhook URL】;
const sendMessage = 【Google Chatで投稿したいメッセージ】;
// 以下おまじないとしての固定コード
const payload = {
"text": sendMessage
}
const options = {
"method": "POST",
"headers": { "Content-Type": "application/json; charset=UTF-8" },
"payload": JSON.stringify(payload),
"muteHttpExceptions": true
}
UrlFetchApp.fetch(webhook, options)
}