Binary Diary

ありのままでいいのかな

GASで自作トリガー!ClockTriggerBuilder を使ってトリガーをカスタマイズしてみた!

どうもこたにんです。

GASで自作トリガー!ClockTriggerBuilder を使ってトリガーをカスタマイズしてみた!

ちょっくら作りたいものがありましてですね。

Gmailで受信するメールのうち、特定のメールを受信した時にスクリプトを実行させたい。

前回は、GAS側からGmail受信トレイを検索して特定のメールを拾う、というのをやりました。

今回は続き、そのスクリプトを1分間隔で実行するためにトリガーを設定してみます。

 

 

 

 

GAS標準のトリガーは起動時刻を固定できない

GAS標準のトリガーに「時間主導型」というトリガーがあります。
時間主導型は、以下6種類。

タイプ

概要

特定の日時

固定日付を指定し1回だけ実行する

 YYYY-MM-DD HH:MM

分ベース

一定の分間隔で実行する

 1/5/10/15/30 分おき

時間ベース

一定の時間間隔で実行する

 1/2/4/6/8/12 時間おき

日付ベース

1日1回、特定の1時間の中で実行する

 各時間帯(0-1時/1-2時/2-3時…)

週ベース

1週間1回、特定の曜日の中で実行する

 毎週月火水木金土日

月ベース

1ヶ月1回、特定の日付の中で実行する

 毎月固定日付(1日/2日/3日…)

これらを、画面上で簡単に設定することができます。

今回やりたいこと、1分間隔のトリガーも、簡単に設定できます。

f:id:Kotanin0:20200202063537p:plain

できた!
ただしこれでは、1日1440分、1440回叩かれることになります。

そうなんです。
コンソール上で設定できるトリガーは、ちょっとかゆいのです。
バシッとスケジューリング、ができないのです。
日付ベースで設定しても、1時間のうち何分に実行されるのかがわからないのです。
crontab を使い慣れている勢としては、かゆくてしかたがないのです。

なので今回はスクリプト側から、任意の時間帯で発動できるようにします。

具体的に文字にすると、こういう動きを実現してみます。

「8:00-10:00まで1分間隔で動くトリガー」

1440回ではなく、たった120回だけ動くようにしたいです。
画面上で設定するトリガーでは実現できないので、GAS内に用意されているクラスに頼ることにしましょう。

ClockTriggerBuilder でトリガーをカスタマイズする!

通常の時間主導型トリガーは、起動したり停止したりすることができません。
なので「起動・停止を行うスクリプトを実行する」という方式を取ります。
その際に利用するのは ClockTriggerBuilder クラス。 

このクラスを利用することで、画面上で設定するトリガーと同じことをスクリプトで実現できます。

ここからは「8:00-10:00まで1分間隔で動くトリガー」を実際に作っていきましょう。

8:00-10:00まで1分間隔で動くトリガーの完成イメージ

今回実現するカスタムトリガーを図示します。

f:id:Kotanin0:20200202095140p:plain

箇条書きで流れを説明します。

  • 0時:トリガーを2つ登録するスクリプト main を実行
  • 8時:mailTrigger を登録するスクリプト minuteTrigger を実行
  • 8〜10時:メイン処理が走る
  • 10時:mailTrigger を削除するスクリプト deleteMailTrigger を実行

百聞は一見にしかず、スクリプトを見ていきましょう。

起動時刻指定でトリガーを作成する

まずは、8時起動・10時起動の2つのトリガーを作るmain関数を作ります。

function main() {
deleteTrigger('minuteTrigger');
var registerDate = new Date();
registerDate.setHours(08);
registerDate.setMinutes(00);
ScriptApp.newTrigger(
'minuteTrigger').timeBased().at(registerDate).create();

deleteTrigger('deleteMailTrigger');
var registerDate = new Date();
registerDate.setHours(10);
registerDate.setMinutes(00);
ScriptApp.newTrigger('deleteMailTrigger').timeBased().at(registerDate).create();
}

function deleteTrigger(triggerName) {
ScriptApp.getProjectTriggers().forEach(function(trigger) {
if (trigger.getHandlerFunction() == triggerName) {
ScriptApp.deleteTrigger(trigger);
}
});
}

GAS内でトリガーを作成するには ScriptApp.newTrigger() を利用します。
引数にトリガー名を渡すと、その名前でトリガーを作成してくれます。
newTrigger() は TriggerBuilder クラスでチェーンできるので、時間主導型トリガーを示す timeBased() メソッドをつなぎます。
timeBased() はさらに ClockTriggerBuilder クラスでチェーンできます。
at() メソッドで起動時刻を指定してやりましょう。
最後に create() でバシッと作っておわり。

また、このmain関数は1日1回起動するため、前日に登録していたトリガーを削除する処理も組み込んでおきましょう。
deleteTrigger()メソッドをさくっと自作しておきました。

1分間隔のトリガーを作成する

1分間隔でメイン処理を動かすトリガーを作るminuteTrigger関数を作ります。

function minuteTrigger() {
deleteTrigger('mailTrigger');
ScriptApp.newTrigger(
'mailTrigger').timeBased().everyMinutes(1).create(); }

作り方は先ほどとほとんど同じです。
ただ、1分間隔を設定するため everyMinutes() メソッドで1分を指定します。

ここで注意なのが、関数名を先に登録したトリガー名と合わせておくこと。
関数名とトリガー名が紐付くので。

メイン処理を書く

残すはメイン処理です、さくっと書きましょう。

function searchMail() {
var threads = GmailApp.search('subject:返却完了 label:unread'); GmailApp.getMessagesForThreads(threads).forEach(function(msg) { var date = Utilities.formatDate(msg[0].getDate(), 'Asia/Tokyo', 'yyyy-MM-dd HH:mm:ss'); sendSlack('返却完了 ' + date); msg[0].markRead(); }); }

これは前回記事で作成済みなので、説明も省略。

カスタムトリガー完成!

これで完成です!
作った関数を実行させてトリガーを画面で確認するとちゃんとできていることがわかります。

f:id:Kotanin0:20200202103119p:plain

あとは、メイン関数を1日ごとのトリガーとして登録しておけば、動くぞ。

考察:カスタムトリガーの応用

今回はやりたいことが細かったので少し複雑なカスタムトリガーになりました。
が、作り方によっては、もっとライトなものも作れます。

  • 毎日9:00に実行する
  • 火曜と金曜の23:30に実行する
  • 12:00-13:00/18:00-19:00実行する

無理のない頻度でスクレイピングしたり、スプレッドシート反映したり。
やりたいことに合わせて好きなようにカスタマイズできそうです。

好きなだけ好きなようにトリガーをカスタマイズして素敵なGASライフ!!