専用のAPIがあればいいですけど、ウォッチ系のAPIは無さそうなので実装してみます
Page IDからブロックIDを取得する
Notionだとページの中身を取得するAPIが無い模様です。
ブロックという概念になっていてブロックに対してAPIを使っていくみたいですね。
こちらの記事の概念図がすごく分かりやすかったです。
Database > Page > Blockといった階層構造のイメージで大丈夫だと思います。
めちゃめちゃpage.contentみたいな感じで一発で取得したいですが...苦笑
親のBlockIDはPageIDでOK
ということでBlockの中身を取りたいのですが、APIのサンプルをみるとこれが分からなくて最初戸惑いました。
サンプルだとこのような形でブロックIDを指定して子要素を取得せよ、みたいなサンプルになってますが、重要な親のBlockIDをPageIDから取得する方法がわかりませんでした。
const blockId = `ブロックID`;
const response = await notion.blocks.children.list({block_id: blockId});
↓
const blockId = `ページIDでOK`;
const response = await notion.blocks.children.list({block_id: blockId});
こんな感じでページIDを指定してみたらそのまま動いてくれたので親のBlockID = PageIDの模様です。
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に入ってるのでソートします。
省略
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
を参照する形になるという、厄介な仕様です。
- 箇条書き
{
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' }
}
- 段落
{
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のキーをもとに情報を持ってきます。
省略
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
箇条書きでaaaa
と書いた内容が最新の変更なのでうまく取れてそうでした。
所感
とりあえずできた!って感じです。
Blockは一つのページの中で複数存在する形になっていくので、データベースから検索をかけてくると入れ子構造がエグい感じになっていきますね。
どなたか一発取得のやり方でもっと良い方法あれば教えてください苦笑