🐣

Googleカレンダーの2日分の予定をslackに通知する

2023/05/11に公開

背景・概要

自分は日々のタスク管理にGoogleカレンダーを活用しているのですが、こちらは今日と明日のGoogleカレンダーの予定をslackで通知させるGASです。
予定の優先度は随時変わりますが、2日分をslackで通知することでざっくり把握できます。

土日祝はSlack通知をスキップさせる設定にしています。

slack通知のサンプル

---
■ 2023/05/08(月)
カレンダー1
- 10:30-11:30 予定が入る
カレンダー2
- 13:30-14:30 予定が入る
- 14:30-15:30 予定が入る
- 16:00-17:45 予定が入る
---
■ 2023/05/09(火)
カレンダー1
- 09:45-15:15 予定が入る
- 12:30-13:30 予定が入る

Googleカレンダーの2日分の予定をslackに通知する

  • トリガーを毎日特定の時間に動くように設定してください。土日祝はスキップする設定になっています。
    • 金曜日に通知されますが、金曜日が祝日の場合は木曜日に通知されます。
  • カレンダーIDとSlackのWebhook URLを定数に設定してください。
    • 複数のGoogleカレンダーを設定できます。
function checkWhenToSendNotification() {
  const today = new Date();
  const dayOfWeek = today.getDay();

  if (isBusinessDay(today)) {
    if (dayOfWeek === 5) {
      sendUpcomingWeekScheduleNotifications(3, 4); // 月曜日と火曜日の予定を通知
    } else {
      sendUpcomingWeekScheduleNotifications(0, 1); // 今日と明日の予定を通知
    }
  } else if (dayOfWeek === 4 && !isBusinessDay(new Date(today.getTime() + 24 * 60 * 60 * 1000))) {
    sendUpcomingWeekScheduleNotifications(3, 4); // 金曜日が祝日の場合、木曜日に次の月曜日と火曜日の予定を通知
  }
}

function sendUpcomingWeekScheduleNotifications(startOffset, endOffset) {
  const calendarIds = [
    "calendarId1を入れる",
    "calendarId2を入れる",
    "calendarId3を入れる"
  ]; // Add more calendar IDs here.
  const slackWebhookUrl = "slackWebhookUrlを入れる";

  const slackPayload = {
    "text": "",
    "link_names": 1
  };

  const today = new Date();

  for (let dayOffset = startOffset; dayOffset <= endOffset; dayOffset++) {
    const date = new Date(today.getTime() + dayOffset * 24 * 60 * 60 * 1000);
    const dateStr = Utilities.formatDate(date, "JST", "yyyy/MM/dd");
    const dayOfWeek = ["(日)", "(月)", "(火)", "(水)", "(木)", "(金)", "(土)"][date.getDay()];
    let dailySchedules = {};

    for (const calendarId of calendarIds) {
      const calendar = CalendarApp.getCalendarById(calendarId);
      const events = calendar.getEventsForDay(date);

      if (events.length > 0) {
        for (const event of events) {
          const title = event.getTitle();
          const start = event.getStartTime();
          const end = event.getEndTime();
          const startStr = Utilities.formatDate(start, "JST", "HH:mm");
          const endStr = Utilities.formatDate(end, "JST", "HH:mm");
          const timeStr = `${startStr}-${endStr}`;

          if (!dailySchedules[calendarId]) {
            dailySchedules[calendarId] = [];
          }
          dailySchedules[calendarId].push(`${timeStr} ${title}`);
        }
      }
    }

    if (Object.keys(dailySchedules).length > 0) {
      slackPayload.text += `\n---\n\n*■ ${dateStr}${dayOfWeek}*\n`;
      for (const calendarId in dailySchedules) {
        const calendarName = CalendarApp.getCalendarById(calendarId).getName();
        slackPayload.text += `\n*${calendarName}*\n`;
        dailySchedules[calendarId].forEach(schedule => {
          slackPayload.text += `- ${schedule}\n`;
        });
      }
    }
  }

  if (slackPayload.text === "") {
    return;
  }

  const options = {
    "method": "post",
    "contentType": "application/json",
    "payload": JSON.stringify(slackPayload)
  };
  UrlFetchApp.fetch(slackWebhookUrl, options);
}

function isBusinessDay(date) {
  const dayOfWeek = date.getDay();

  // 土日は営業日ではない
  if (dayOfWeek === 0 || dayOfWeek === 6) {
    return false;
  }

  // 祝日は営業日ではない
  const calendar = CalendarApp.getCalendarById("ja.japanese#holiday@group.v.calendar.google.com");
  const holidays = calendar.getEventsForDay(date);
  if (holidays.length > 0) {
    return false;
  }

  // 営業日の場合はtrueを返す
  return true;
}

GitHubで編集を提案

Discussion