【NotionAPI】GASからNotionAPIで日記ページのプロパティを毎日更新する

## 概要
### この記事で実現すること
:::note info
繰り返し設定で毎日作成される日記ページの日付プロパティに今日の日付を設定したかったため、今回はGAS上でNotionAPIを使って実現します。
:::

<details><summary>実現に至った背景(補足)</summary>

- 2022年11月8日のNotionアップデートにより、データベーステンプレートを繰り返し複製するように設定できるようになりました。これにより、日記などのテンプレートに繰り返し設定をしておくと、自動で毎朝ページを作成することができます。

- ただし、これまで日記ページにカスタムの日付プロパティを用意して管理していた場合、現時点では自動で日付を登録することができません。代替案として、関数型プロパティで作成日時から日付抽出することもできましたが、カレンダービュー上で動かせなくなるなど自由度が下がってしまいます。

- そのため、今回は勉強も兼ねてNotionAPI経由で設定してみることにしました。

</details>


### この記事から分かること
1. データベースへのクエリによる、ページ情報の取得方法
1. 特定ページのプロパティを更新する方法

## 環境・事前準備
- Notion-Version：2022-06-28　
- GAS上でプロジェクトを作成しておく（参考記事は[こちら](https://www.teijitaisya.com/gas-create-script/)。スタンドアローン型でOKです）
- NotionのAPI用トークンを発行しておく(参考記事は[こちら](https://developers.notion.com/docs/create-a-notion-integration)。 Step1から3まで実施しましょう)
- Notionのコネクト機能でGASと接続しておく(参考記事は[こちら](https://qiita.com/katakata_/items/c18625cb7859e216170f)。)

## コード
```javascript:NotionDailyUtil.gs
//スクリプトプロパティからトークン及びDBのidを取得
const prop = PropertiesService.getScriptProperties().getProperties();
const notion_token = prop.MY_NOTION_TOKEN;
const database_id = prop.DATABASE_ID;

//header情報を定義
const headers = {
  'Content-Type': 'application/json; charset=UTF-8',
  'Authorization': 'Bearer ' + notion_token,
  'Notion-Version': '2022-06-28',
};

//DBにクエリを実行して、ページの検索結果を取得する
function GetNotionPages(payload) {

  //リクエストURL
  var url = 'https://api.notion.com/v1/databases/' + database_id + '/query';

  //methodやheader,リクエストbodyなど
  var options = {
    "method": "post",
    "headers": headers,
    "payload": JSON.stringify(payload)
  };

  //リクエストを実行し、検索結果を返却
  var response = UrlFetchApp.fetch(url, options);
  return JSON.parse(response).results;
}

//ページのプロパティを更新する
function PatchNotionPage(page_id, payload) {

  //リクエストURL
  var url = 'https://api.notion.com/v1/pages/' + page_id;

  //methodやheader,リクエストbodyなど
  var options = {
    "method": "patch",
    "headers": headers,
    "payload": JSON.stringify(payload)
  };

  //リクエストを実行し、プロパティを更新
  UrlFetchApp.fetch(url, options);
}

//指定するクエリ
function myQuery() {

  //今回は、「作成日時」プロパティが今日の0時以降　かつ　タイトルが「今日の予定」である　ページをフィルタする
  var today = new Date();
  today.setHours(0);
  today.setMinutes(0);
  today.setSeconds(0);
  var todayStr = Utilities.formatDate(today, 'JST', 'yyyy-MM-dd HH:mm:ssZ');//時差設定が必要

  var query = {
    "filter": {
      "and": [
        {
          "timestamp": "created_time",
          "created_time": {
            "on_or_after": todayStr
          }
        },
        {
          "property": "タスク名",
          "title": {
            "equals": "今日の予定"
          }
        }
      ]
    }
  }

  return query;
}

//指定する更新箇所
function myUpdate() {

  //今回は、「作業予定日」プロパティを今日の日付にする
  var today = new Date();
  var todayStr = Utilities.formatDate(today, 'JST', 'yyyy-MM-dd');
  var update = {
    "properties": {
      "作業予定日": {
        "date": {
          "start": todayStr
        }
      }
    }
  }

  return update;
}

//メインの関数
function myFunction() {

  try {

    //ポイント１：myQueryで定義したフィルタで、ページ検索結果を取得する
    var results = GetNotionPages(myQuery());

    //ポイント２：ページ検索結果からpage_idを取得する
    var page_id = results[0].id;

    //ポイント３：myUpdateで定義したプロパティで、ページを更新する
    PatchNotionPage(page_id, myUpdate());

  } catch (e) {
    Logger.log(e.message);
  }

}

```
### ポイント１
- データベースのページに検索をかけるには、フィルタを定義してPOSTリクエストすることで、該当するページを配列形式で取得することができます。

https://developers.notion.com/reference/post-database-query

- 基本的には、何のDBに対してクエリをかけるかをリクエストURLで指定します（ここではdatabase_idというプロパティから設定）

- クエリとなるJSONに関しては、何というプロパティに対して何の型でどのように比較するか、を指定します。TimeStampに関してはちょっと書き方が異なるみたいです。(created_timeは今回on_or_afterで比較しました。Notionの繰り返しタスクでは毎日0:10に作成するようにしたので、GAS側ではそれ以降に実行するようにすれば、今日作られた日記ページのみをフィルタすることができます)

https://developers.notion.com/reference/post-database-query-filter

![WS-000015.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251204/89bd63cf-7211-ccf7-dc4f-6652adf2e5d4.jpeg "繰り返し設定")


### ポイント２
- 検索結果はJSONでパースした後、resultsという配列を返却しています。
- この中にフィルタされたページの情報が入りますが、今回必要なのは今日作成された日記ページ一つなので、results[0].idでページidを取得しています。
- このページidは後のページ更新処理で必要になります。

### ポイント３
- 日記ページには「作業予定日」という日付型のカスタムプロパティを作っています。
![WS-000014.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251204/e83f0f0e-93a8-5e26-d792-c56c4aa522fb.jpeg)
- このプロパティに今日の日付をいれるべく、myUpdate()内で更新内容を定義します。（更新の際はPOSTではなくPATCHメソッドとなるためご注意ください）

https://developers.notion.com/reference/patch-page

## まとめ
- あとは、このスクリプトを以下のようにトリガー(定期実行)設定すれば、Notionの繰り返し設定で生成された日記ページの日付プロパティに今日の日付が入ります。
![WS-000016.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251204/58360e9b-2710-c187-967c-644e9d3163cc.jpeg)
![WS-000013.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251204/23d69a34-58ef-6efb-d615-01d78323c382.jpeg)


## 参考
https://qiita.com/g-iki/items/cc44fa7573dc3f6e39de

https://ensei1375.com/notion-repetition/#toc7

https://auto-worker.com/blog/?p=6383

https://qiita.com/motoo1789/items/b38018b73efa50ff3920

https://qiita.com/g-iki/items/9b16e86fde331ed67155

https://www.pnkts.net/2021/05/16/gas-notion-api

## おまけ
- ちなみに、コードをわざわざ書かなくても「Make」という機能で実現できるそうなので、なるべく簡単に実現したいという方は以下をご参照いただければ幸いです。

https://twitter.com/shogocat/status/1591743982924877830