Google Calendar から Notion ページを作成する : Notion 解説(20)

はじめに

昨日はics からNotion に一括登録する記事を書きました。また、今朝は繰り返しイベントの登録を実施しました。3 本目は Calendar イベント登録時に Notion タスクページを自動登録します。繰り返しイベントでは、時間手動型のイベントを使いましたが、今回はカレンダー更新をトリガーにして、Notion API に送ります。

似たようなことをやっている人がいるだろうと検索したところ、以下の記事を見つけました。カレンダーデータの取得部分については、これを真似ればできそうです。 qiita.com

準備

Google Calendar API の有効化

Google Calendar API が必要とのことなので、API を有効にします。以下のリンク先で設定します。 console.developers.google.com

API ライブラリから、「Google Calendar API」を選びます。以下の画面になるので、「有効にする」をクリックします。

f:id:hkob:20210515182919p:plain
Google Calendar API

自分のアカウントからのアクセスになるので、認証情報などを追加する必要はないようです。

カレンダーの準備

Google Calendar には Notion という専用のカレンダーを準備しました。このカレンダーの「設定と共有」を表示して、「カレンダーID」を取得しておきます。

f:id:hkob:20210515221514p:plain
カレンダーID の準備

Google Apps Script の修正

まず、Google Calendar API を使えるようにするために、サービスを追加します。まず、サービスの右の「+」をクリックします。

f:id:hkob:20210515221820p:plain
サービスの追加

Google Calendar API を選択して、「追加」をクリックします。

f:id:hkob:20210515204007p:plain
Google Calendar API を追加

詳しい説明は省略しますが、スクリプトは以下のようになりました。終了時間の設定もしたいので、前回の繰り返し登録関数の日付部分も少し修正しています。

// 初回認証のためだけのテスト呼び出し関数
function readCalendar() {
  let calendarId = "この部分にカレンダーIDを書きます。";
  let token = getSyncToken(calendarId);
  Logger.log(token);
}

function postNotion(payload){
  let MY_NOTION_TOKEN = "この部分にIntegration Token を書きます。";
  let url = "https://api.notion.com/v1/pages"; // API URL
  let options = {
    "method" : "POST",
    "headers": {
      "Content-type": "application/json",
      "Authorization": "Bearer " + MY_NOTION_TOKEN,
      "Notion-Version": "2021-05-13",
    },
    "payload" : JSON.stringify(payload)
  };
  Logger.log(options);
  UrlFetchApp.fetch(url, options);
}

function createPayload(title, date_hash) {
  let DATABASE_ID = "この部分にDatabase ID を書きます";

  payload = {
    "parent": {
      "database_id": DATABASE_ID
    },
    "properties": {
      "タスク名": {
        "title": [
          {
            "text": {
              "content": title
            }
          }
        ]
      },
      "日付": {
        "type": "date",
        "date": date_hash
      },
      "非ポモ?": {
        "type": "checkbox",
        "checkbox": true
      }
    }
  }
  return payload;
}

function doCalendarPost(event) {
  let calendarId = event.calendarId; // カレンダーIDのの取得
  let token = getSyncToken(calendarId); // 前回実行時に取得したカレンダーTokenの取得
  let events = Calendar.Events.list(calendarId, {'syncToken': token}); // Token から後のカレンダーを取得
  let filteredItems = events.items.filter(e => {return e.status == "confirmed"}); // ステータスを見て登録、もしくは更新の予定のみにフィルタリング

  filteredItems.map(e => {return eventToPayload(e)}).filter(e => {return e}).forEach(p => {
    postNotion(p);
  }); // 予定を Notion に通知する
  saveSyncToken(events.nextSyncToken); // 今回のTokenを保存する(次回のScript実行時に利用)
}

// 前回保存したカレンダーのSyncTokenを取り出す、前回保存分が無い場合は今回のSyncTokenを利用する
function getSyncToken(calendarId){
  var token = PropertiesService.getScriptProperties().getProperty('SYNC_TOKEN');
  if (token) {
    return token;
  }
  let events = Calendar.Events.list(calendarId, {'timeMin': (new Date()).toISOString()});
  return events.nextSyncToken;
}

function eventToPayload(e) {
  let hash = null;
  if ('dateTime' in e.start){
    hash = {
      "start": e.start.dateTime.replace("T", " "),
      "end": e.end.dateTime.replace("T", " ")
    }
  }
  if ('date' in e.start) {
    hash = {
      "start": e.start.date
    }
  }
  return hash ? createPayload(e.summary, hash) : null;
}

// SyncTokenをプロパティに保存する
function saveSyncToken(token){
  PropertiesService.getScriptProperties().setProperty('SYNC_TOKEN', token);
}

function weekToStr(date) {
  let w = Utilities.formatDate(date, "JST", "u");
  return ["日", "月", "火", "水", "木", "金", "土"][w]
}

function doEverydayPost() {
  let today = new Date();
  let date_hash = {"start": Utilities.formatDate(today, "JST", "yyyy-MM-dd")};
  let week_str = weekToStr(today);
  let title_base = "雑務・振り返り M/d (" + week_str + ")";
  let title = Utilities.formatDate(today, "JST", title_base);
  // テストのためのデバッグ出力
  //  Logger.log(createPayload(title, date_hash));
  postNotion(createPayload(title, date_hash));
}

認証を取得

この後の設定を先にやっていたのですが、認証に失敗してしまいました。テストのために、スクリプトの一番上に書いた「readCalendar」をエディタから実行したところ、アカウントの認証画面に遷移しました。ここで認証をするとこの後の作業も無事に進みました。以下のように readCalendar を選択した状態で、一度だけ実行をクリックしてください。

f:id:hkob:20210515222907p:plain
readCalendar を実行

カレンダートリガの設定

ここまでできたら、カレンダーの更新トリガを設定するだけです。関数として「doCalendarPost」を選択し、イベントのソースを「カレンダーから」とします。カレンダーオーナーのメールアドレスに、上で取得した「カレンダーID」を登録すれば終了です。

f:id:hkob:20210515192608p:plain
カレンダーのトリガー

デプロイ

ここまでできたら、デプロイをしておきます。説明は省略します。

実行

ここまでできたら、実際にカレンダーを登録してみます。

時間指定イベントの作成

まずは、時間が指定されたイベントの登録です。Google Calendar にて時間指定イベントの登録をおこないます。

f:id:hkob:20210515223527p:plain
時間指定イベントを追加

Notion を見てみると無事にタスクが登録されています。

f:id:hkob:20210515223713p:plain
Notion に登録された時間指定イベントタスク

終日イベントの作成

今度は時間指定のない終日イベントを登録してみます。

f:id:hkob:20210515223839p:plain
終日イベントの追加

こちらも問題なく終日イベントとして登録されています。

f:id:hkob:20210515224046p:plain
Notion に登録された終日イベントタスク

おわりに

カレンダー登録で自動的にタスクに入ってくれるのは、かなり楽ですね。Notion をメインにしてから、カレンダーがスカスカになってしまっていたのが復活しそうです。上の設定では「非ポモ?」をデフォルトで true にしてしまっていますが、タスクをポモドーロで実施する可能性もあるので、実際にはこの設定を外そうと考えています。


はてなブログに書いた Notion 記事一覧