Googleカレンダーの社内の予定を(半)自動で「予定なし」にしたい

2024/11/23に公開

TL;DR

  • Googleカレンダーの中の、特定の条件を満たす予定を「予定なし」にするGASスクリプトを紹介します
  • 定期実行の仕組みは未検証だが、「トリガー」とやらを使えばできそう

モチベーション

SpirやGoogleカレンダーの予約スケジュールなどのツールを使った日程調整、便利ですよね。
これらを使うにあたり、あるあるなのが「社内の予定は無視して候補日程を表示してほしい」というものになります。
Googleカレンダーの場合は予定作成時に「予定なし」に設定すれば、カレンダー連携先には空き枠として認識されます。

この設定をうっかり忘れていると日程調整時の枠が大きく減ってしまいます。
自分で予定を作成する際にも「うっかり」忘れることはありますし、社内の他の人が作成した予定に招待された際にも予定なし設定を「うっかり」忘れられるケースもあります。
これらを防止するために社内を啓蒙したり、あるいは週に1回自分の予定を確認する予定を組んだとしても、限界があります。

上記を背景として、社内の予定を確実に「予定なし」にしたい、というのが本記事で紹介する仕組みのモチベーションになります。

手順

  • GASを開く
  • appscript.json というファイルを開き、以下のように入力
{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
    "enabledAdvancedServices": [
      {
        "userSymbol": "Calendar",
        "version": "v3",
        "serviceId": "calendar"
      }
    ]
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    # 以下のスコープ定義が重要
    "https://www.googleapis.com/auth/calendar",
    "https://www.googleapis.com/auth/calendar.readonly",
    "https://www.google.com/calendar/feeds"
  ]
}
  • Calendar というサービスを追加する


  • ここまでやると、以下のような感じになります。

  • コード.gs の編集
// 「予定あり」にしたい予定のタイトルに含まれるキーワード
const visibleEventKeywords = [
  "重要",
  // MTGが入りうる社外関係者の名称を入れる
  "禅株式会社",
  "禅",
  "zenn",
  "srkw"
]

// 何日後までの予定を編集するか
const UPDATE_DURATION = 180

function main() {
  const calendar = CalendarApp.getDefaultCalendar();
  const today = new Date();
  const startDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
  const endDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + UPDATE_DURATION);
  const events = calendar.getEvents(startDate, endDate);

  for (const event of events) {
    try {
      console.log(`processing... ${event.getTitle()}`)
      const calendarId = calendar.getId();

      // event.getId() は通常、 <event_id>@google.com の形式なので @ 以降を取り除いたものをイベントIDとして扱う
      const eventId = event.getId().replace(/@.+$/, '');

      // 休日などの予定を操作対象から除外するためのフラグ
      const isDefaultTypeEvent = event.getEventType().toString() === "DEFAULT"

      const isVisibleEvent = !!event.getTitle().match(new RegExp(`(${visibleEventKeywords.join('|')})`))

      if (isDefaultTypeEvent && isVisibleEvent) {
        // キーワードを含む予定を「予定あり」にする
        Calendar.Events.patch({ transparency: "opaque" }, calendarId, eventId);
      } else if (isDefaultTypeEvent && !isVisibleEvent) {
        // キーワードを含まない予定を「予定なし」にする
        Calendar.Events.patch({ transparency: "transparent" }, calendarId, eventId);
      }
    } catch (e) {
      console.warn(
        `${event.getTitle()}の更新に失敗しました。${e.message}`
      )
    }
  }
}
  • MacだとCommand+S、もしくは「プロジェクトを保存」を押下
  • MacだとCommand+R、もしくは「実行」を押下すると、処理が開始される
    • このとき権限付与関連のポップアップが表示されるはずなので、適当に承認する
  • 処理が開始されるとログがページ下部に表示される

おわりに

上記の準備が整えば、あとは週に1回などの頻度でGASを実行することで、(半)自動で特定の予定を「予定なし」にすることができます。
本来であればこの処理の実行自体も自動化したかったのですが、実現に至れず。軽く調べたところGASに「トリガー」という機能があり、これを使えばうまくいくかもしれません。

Discussion