LoginSignup
2
3

More than 1 year has passed since last update.

NotionAPI×GASでチェックボックスにチェックを入れた日時を記録する

Last updated at Posted at 2021-11-21

概要

GASでNotionAPIを叩いてDBからチェックボックスにチェックが付けられたもの
の日時(タイムラグあり)を記録する方法を紹介します

どこかの記事にFormulaとして prop("完了") ? formatDate(now(), "YYYY/MM/DD") : "" を書けばいい、のような記述がありましたが、now()では当然常に現在時刻を取得するだけなのでそのような記述では実現できなかったので、GASでの実装になります。

GASの時間主導型のトリガーを利用して「チェックされているもの」かつ「日付の入力が無いもの」を取得→更新とするため、その分のタイムラグは発生します。

手順

NotionAPIで使用するトークンの取得

下記記事や、公式ドキュメント等を参考にNotionAPIで使用するトークンの取得と、
更新を行いたいDBに対してインテグレーションの招待を行います。
https://qiita.com/g-iki/items/cc44fa7573dc3f6e39de

コード

properties.gs

/**
 * 手動実行で設定する
 */
function setScriptProps() {
  let scriptProperties = PropertiesService.getScriptProperties();
  Logger.log(PropertiesService.getScriptProperties().getProperties());
  scriptProperties.deleteAllProperties();

  scriptProperties.setProperties({
    'NOTION_VERSION': '2021-08-16',
    'NOTION_TOKEN': 'secret_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
  });

  // データベースとチェックボックスの列名、日付の列名を定義
  // データベースIDはデータベースのページを開き、URLから取得
  // https://www.notion.so/{userName}/{DatabaseID}?v={ViewID} となっているURLの{DatabaseID}の部分
  let checkItemList = JSON.stringify(
    [
      {
        // WebScrap既読日
        'DATABASE_ID': 'XXXXXXXXXXXXXXXXXXXXXX',
        'CHECKBOX_PROPERTY': 'Read',
        'DATE_PROPERTY': 'ReadDate'
      }
    ]
  );

  scriptProperties.setProperties({ 'CHECK_ITEM_LIST': checkItemList });
}

上記コードは環境変数用設定用のコードで手動で実行します。 NOTION_TOKEN は取得したトークン checkItemListで指定している DATABASE_ID はデータベースのID CHECKBOX_PROPERTY はチェックボックスプロパティ名 DATE_PROPERTY は日時を入力したいプロパティ名 を設定します。(配列として複数設定可能)

image.png

↑例えば自分の場合、WebScrapの既読日を記録したいので、
CHECKBOX_PROPERTYReadDATE_PROPERTYReadDateを指定しています。

updateCheckedTime.gs

function UpdateCheckedTime() {
  const props = PropertiesService.getScriptProperties().getProperties();
  const strDate = Utilities.formatDate(new Date(), "JST", "yyyy-MM-dd");
  const list = JSON.parse(props['CHECK_ITEM_LIST']);

  for (let i = 0; i < list.length; i++) {
    const item = list[i];
    const dbID = item["DATABASE_ID"];
    const checkboxPropery = item["CHECKBOX_PROPERTY"];
    const dateProperty = item["DATE_PROPERTY"];
    // チェックボックス=true で日付が空のものを取得
    const getPayload = {
      "filter": {
        "and": [
          {
            "property": checkboxPropery,
            "checkbox": {
              "equals": true
            }
          },
          {
            "property": dateProperty,
            "date": {
              "is_empty": true
            }
          }
        ]
      }
    }

    const nonCheckedItemList = getDatabaseQuery(props, dbID, getPayload);
    Utilities.sleep(1000); // 平均3回/秒のリミット回避のためスリープ

    if (nonCheckedItemList.results.length === 0) {
      Logger.log("更新対象なし")
      continue;
    }

    // 更新処理
    nonCheckedItemList.results.forEach(t => {

      const updatePayload = {
        "properties": {
          [dateProperty]: {
            "date": {
              "start": strDate
            }
          }
        }
      };

      let pageId = t["id"]
      updatePage(props, pageId, updatePayload)
      Utilities.sleep(1000); // 平均3回/秒のリミット回避のためスリープ
    });
  }
}

/**
 * ページの内容を更新する
 * https://developers.notion.com/reference/patch-page
 */
function updatePage(props, pageId, payload) {
  let url = "https://api.notion.com/v1/pages/" + pageId
  let options = {
    "method" : "PATCH",
    "headers": {
      "Content-type": "application/json",
      "Authorization": "Bearer " + props.NOTION_TOKEN,
      "Notion-Version": props.NOTION_VERSION,
    },
    "payload": JSON.stringify(payload)
  };

  try {
    let res = UrlFetchApp.fetch(url, options);
    Logger.log(res);
    return JSON.parse(res);
  } catch (e) {
    Logger.log(e);
    return undefined;
  }

}

/**
 * DBから指定条件に合うものを取得する
 * https://developers.notion.com/reference/post-database-query
 */
function getDatabaseQuery(props, databaseId, payload) {
  let url = "https://api.notion.com/v1/databases/" + databaseId + "/query"
  let options = {
    "method" : "POST",
    "headers": {
      "Content-type": "application/json",
      "Authorization": "Bearer " + props.NOTION_TOKEN,
      "Notion-Version": props.NOTION_VERSION,
    },
    "payload" : JSON.stringify(payload),
    "muteHttpExceptions" : true
  }

  try {
    let res = UrlFetchApp.fetch(url, options);
    Logger.log(res);
    return JSON.parse(res);
  } catch (e) {
    Logger.log(e);
    return undefined;
  }
}

動作確認

環境変数設定用の関数に必要項目を入力後、setScriptProps()を実行して環境変数を設定します。

その後、チェックボックスの状態監視、日付の入力を行いたいDBに
チェックボックスをTrueにしたページを用意して、UpdateCheckedTime()関数を実行し、
日付の更新が行われることを確認します。

GASの定期実行設定

UpdateCheckedTime()関数を時間主導型で実行するように設定します。
頻繁に更新を行いたい場合は1分や5分、1日に1回更新すればいい程度なら日付ベースのタイマーで適当な時間を指定してあげればOKです

おわり

自分はこれを活用して、NotionSaverで後で読むように保存していた記事を読み終わったらチェックをつけて、読んだ日付は自動で入力されるように仕込んでいます。

他にも課題管理の完了チェック+完了日の記録に使ったりできると思います。


役に立ったらモチベーションに繋がるのでLGTMボタンを押して頂けると幸いです。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3