KEIS BLOGは株式会社ケイズ・ソフトウェアが運営しています。

KEIS BLOG

ChatGPTに聞きながらランダム指名Slack botを作った話(後編)


後編です!

さて、ここまでちゃっぴーに作ってもらったところで、GASのトリガーについて考えていきます。
今回作ってもらって、定期的に動かしたい関数は3つ。

  • notifyRandomEmployee:Slackにメッセージを投下するメインの関数
  • createTrigger:notifyRandomEmployee関数のトリガーを作成する関数(chatGPTは、「初回実行時に手動で設定する必要あり」とコメントしていますね。)
  • importJapaneseHolidays:祝日をスプレッドシートにインポートする関数

気をつけたいことは、GASのトリガーって、毎日9:30 という設定ができないんですよね。

GASのGUIから確認しても、日付ベース(毎日)のトリガーだと一時間ごとにしか選択できません。これだと、「9時〜10時の間のどこか」で「指名されるかもしれない…」というナゾのドキドキ感を味わうことになります。
ちゃっぴーが書いてきた以下のコードも、実は9:30前後(おそらく前後15分?)に実行されるっていう引っ掛けコードです。(nearMinuteと言っています。。)


function createTrigger() {
ScriptApp.newTrigger('notifyRandomEmployee')
.timeBased()
.atHour(9)
.nearMinute(30)
.everyDays(1)
.create();
}

9:30ぴったりに実行したかったので、このコードを変更することにします。
ググったら結構みんな同じことで悩んでいるようで、毎日「特定の日時」に実行されるトリガーを作成する、という方法でハックしてるみたいです。先人たちにならい、以下のようにcreateTrigger関数を変更しました。


// トリガーのセットアップ(毎日決まった時間に実行)
function createTrigger() {
  var allTriggers = ScriptApp.getProjectTriggers();
  var existingTrigger = null;

  // すでに存在するnotifyRandomEmployeeトリガーを探す
  for (var i = 0; i < allTriggers.length; i++) {
    if (allTriggers[i].getHandlerFunction() === 'notifyRandomEmployee') {
      existingTrigger = allTriggers[i];
      break;
    }
  }

  // すでに存在するトリガーがあれば削除
  if (existingTrigger !== null) {
    ScriptApp.deleteTrigger(existingTrigger);
  }

  var triggerDay = new Date();
    triggerDay.setDate(triggerDay.getDate() + 1);
    triggerDay.setHours(9);
    triggerDay.setMinutes(30);
    triggerDay.setSeconds(0);

  ScriptApp.newTrigger('notifyRandomEmployee')
    .timeBased()
    .at(triggerDay)
    .create();
}

この関数は、毎日10時〜11時のどこかで実行するようにセットしました。
notifyRandomEmployeeを翌日9:30にセットしてくれます。かつ、実行済みの古いnotifyRandomEmployeeのトリガーがあれば削除してくれます。
これで3つのうちの2つの関数はトリガーが定まりました。

残すはimportJapaneseHolidaysですが、これは正直いつでもいい。年一でもいいので、手動で実行するでも全然いい。でも、せっかくだしな〜ということで、ちゃっぴーに以下のお願いをしてコードを書き換えてもらいました。

毎月1日の0時に定期実行するようにするから、当月の祝日リスト取得に直して

できたものはこちら

function importJapaneseHolidays() {
  const calendarId = 'ja.japanese.official#holiday@group.v.calendar.google.com'; // 日本の祝日カレンダーID
  const today = new Date();
  
  // 当月の1日
  const startOfMonth = new Date(today.getFullYear(), today.getMonth(), 1);
  // 翌月の1日
  const startOfNextMonth = new Date(today.getFullYear(), today.getMonth() + 1, 1);

  // 当月の祝日を取得
  const events = CalendarApp.getCalendarById(calendarId).getEvents(startOfMonth, startOfNextMonth);

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(HOLIDAY_SHEET_NAME);
  if (!sheet) {
    throw new Error('祝日シートが見つかりません');
  }

  // シートをクリアして、新しいデータを追加
  sheet.clear();
  sheet.getRange(1, 1).setValue('祝日');

  // 祝日を1列目に書き込む(日本時間に変換)
  events.forEach((event, index) => {
    const startTime = event.getStartTime();
    
    // タイムゾーンを日本時間に変更して日付を取得
    const dateInJapan = Utilities.formatDate(startTime, Session.getScriptTimeZone(), 'yyyy-MM-dd');
    
    sheet.getRange(index + 2, 1).setValue(dateInJapan);
  });
}

いいね!

というわけで、importJapaneseHolidaysは毎月1日の0〜1時の間に動いています。
メッセージやアイコンを自分好みに直したら、完成です!

こまかい話ですが、最初にちゃっぴーに書いてもらったnotifyRandomEmployee内ではJSTの考慮がなされていないので、つい先日の祝日は誤って実行されてしまいました。ごめんよ、指名されてしまった人。現在は修正したので祝日には実行されないです。

 

まとめ

Slackリマインダー、便利なんですが、+αなにかしたい、というときに良いツールがほしいなと思ってたんですよね。
今回GASに触れたことで、大分ハードルが下がりました。ちゃっぴーのサポートも手厚いですし、積極的に使っていきたいと思います。
Enjoyプロンプトライフ!