Notonのページの最終変更の内容を取得してみる


専用のAPIがあればいいですけど、ウォッチ系のAPIは無さそうなので実装してみます

## Page IDからブロックIDを取得する

Notionだとページの中身を取得するAPIが無い模様です。

ブロックという概念になっていてブロックに対してAPIを使っていくみたいですね。

こちらの記事の概念図がすごく分かりやすかったです。

https://qiita.com/senju797/items/0e3bfb1c8f0b7b035f46#pagesblocks

[Retrieve block children](https://developers.notion.com/reference/get-block-children)

Database > Page > Blockといった階層構造のイメージで大丈夫だと思います。

めちゃめちゃpage.contentみたいな感じで一発で取得したいですが...苦笑

## 親のBlockIDはPageIDでOK

ということでBlockの中身を取りたいのですが、APIのサンプルをみるとこれが分からなくて最初戸惑いました。

サンプルだとこのような形でブロックIDを指定して子要素を取得せよ、みたいなサンプルになってますが、重要な親のBlockIDをPageIDから取得する方法がわかりませんでした。

```js
const blockId = `ブロックID`;
const response = await notion.blocks.children.list({block_id: blockId});
```

↓

```js
const blockId = `ページIDでOK`;
const response = await notion.blocks.children.list({block_id: blockId});
```

こんな感じでページIDを指定してみたらそのまま動いてくれたので親のBlockID = PageIDの模様です。


```js
const main = async () => {
    const response = await notion.databases.query({
        database_id: studentDBId,
        filter: {
          or: [
            {
              property: '学籍番号',
              rich_text: {
                contains: 'po-07'
              }
            }
          ],
        },
    });
    const items = response.results;
    
    //ここまではDatabaseオブジェクト
    
    //Retrieve block childrenだけどPageIdをそのままBlockIDとしてAPI呼び出し
    const users = [];
    for await (const item of items) {
        const blockId = item.id; //本来はpageid
        const response = await notion.blocks.children.list({
          block_id: blockId,
          page_size: 50,
        });
        users.push(response.results);
    }
    
    console.log(user[1]); //二人目のUserページの中身

}

main();
```

これでブロックが丸っと取得できます。

## last_edited_timeでソート

ブロックのリストが入っている状態になりますが、最終変更の時間はlast_edited_timeに入ってるのでソートします。

```js

省略
    const obj = users[1];
    // console.log(users[1]);

    //最終編集が新しい順でソート
    const result = Object.keys(obj).map(function(key) {
        return obj[key];
    }).sort(function(a, b) {
        return (a.last_edited_time > b.last_edited_time) ? -1 : 1;
    });
```

## Blockのタイプによってオブジェクトのキーが変わる

Notionのブロックは箇条書きや段落、画像など色々な種類がありますが、種類によってAPIが返してくるデータの形も変わってしまいます。

箇条書きの場合は`obj.bulleted_list_item`になり、通常のテキスト（段落）の場合は`obj.paragraph`を参照する形になるという、厄介な仕様です。


- 箇条書き

```json
{
  object: 'block',
  id: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
  parent: { type: 'page_id', page_id: 'xxxxxxxxxxxxxxxxxxxxxxxxxx' },
  created_time: '2022-12-03T06:58:00.000Z',
  last_edited_time: '2022-12-07T08:08:00.000Z',
  created_by: { object: 'user', id: 'xxxxxxxxxxxxxxxxxxxxxxxxxx' },
  last_edited_by: { object: 'user', id: 'xxxxxxxxxxxxxxxxxxxxxxxxxx' },
  has_children: false,
  archived: false,
  type: 'bulleted_list_item',
  bulleted_list_item: { rich_text: [ [Object] ], color: 'default' }
}
```

- 段落

```json
{
  object: 'block',
  id: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
  parent: { type: 'page_id', page_id: 'xxxxxxxxxxxxxxxxxxxxxxxxxx' },
  created_time: '2022-12-03T06:58:00.000Z',
  last_edited_time: '2022-12-07T08:08:00.000Z',
  created_by: { object: 'user', id: 'xxxxxxxxxxxxxxxxxxxxxxxxxx' },
  last_edited_by: { object: 'user', id: 'xxxxxxxxxxxxxxxxxxxxxxxxxx' },
  has_children: false,
  archived: false,
  type: 'paragraph',
  paragraph: { rich_text: [ [Object] ], color: 'default' }
}
```

ということでこんな感じでtypeのキーをもとに情報を持ってきます。

```js

省略

    const last_edited_block = result[0]; //最新の変更があったブロック

    const lastUpdateType = last_edited_block.type;
    const lastUpdateContent = last_edited_block[lastUpdateType];
    const lastUpdateText = lastUpdateContent.rich_text[0].plain_text;

    console.log(`${last_edited_block.last_edited_time}に変更がありました。 -> ${lastUpdateText}`);
```

結果

```
2022-12-07T08:08:00.000Zに変更がありました。 -> aaaa
```

> ![スクリーンショット 2022-12-07 17.29.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/24260b61-5260-f02a-3728-90615cddb390.png "スクリーンショット 2022-12-07 17.29.56.png")


箇条書きで`aaaa`と書いた内容が最新の変更なのでうまく取れてそうでした。

## 所感

とりあえずできた！って感じです。

Blockは一つのページの中で複数存在する形になっていくので、データベースから検索をかけてくると入れ子構造がエグい感じになっていきますね。

どなたか一発取得のやり方でもっと良い方法あれば教えてください苦笑