【Notion API × Google Apps Script】Notionのテーブル上のデータを定期的にアーカイブする

こんにちは、おしょうです。

6月下旬、ギターを買いました。Taylorの210ceです。
比較的お手頃な価格、カッタウェイ、太めの音色、お店でとても気に入って買っちゃいました。
実は、ギター始めたきっかけは「コブクロの曲弾いてみたい!」という衝動だったんですけど、そのコブクロがとある曲で(別のモデルですけど)テイラーのギター使っていたんですね。
それで、コブクロに憧れた少年おしょうは「次に買うならとりあえずTaylorだ!」と。
これから、いい友になれるように頑張ります!

ちなみに、210ceはちょっとウエストが太めなんです。ギターのシェイプはそのまま女性の体型のタイプだと聞いたことありますけど、確かに私ぽっちゃりが好きですね。最初に言った人すごい!笑

さて、前書きが長くなりましたが、本題です。
Notionのデータベースはさまざまな表示形式があります。そのうちの一つ、「ボードビュー」というのは、プロジェクト管理などでもよく使われる、いわゆる「カンバン型」の表示方法です。
私の場合、すぐに取り掛かる必要がないタスクや、中長期で進捗を追う必要があるタスク、とりあえずこんなことやってみたい!といったアイデアなど、とりあえずバンバン書きためて、進捗を追っていくのに使用しています。
「未着手(Not Started)」「進行中(In Progress)」「完了(Completed)」「保留(In Hold)」というように分類しており、使用していると少しずつ「完了」が増えていくんですよね。達成感もあるんですが、私としてはアーカイブしておきたい。でも都度操作するのは面倒!

こんな時に、Google Apps ScriptとNotion APIの連携が活きますね!

毎月1日0時くらいになったら、Google Apps Scriptが走ってAPIを叩く。
そうすると、完了に分類されたアイテムのみアーカイブされる。

こんな機能があれば、とりあえず手動で項目を選択して削除して、、、みたいな作業が減らせます。
早速作ってみましょう!

1.グローバル定数作成

const ENDPOINT_PAGE = "https://api.notion.com/v1/pages/"
const ENDPOINT_DATABASE = "https://api.notion.com/v1/databases/"
const KEY = "[自分のシークレットkey]"
const HEADERS = {
 "Authorization" : `Bearer ${KEY}`,
 "Notion-Version" : "2021-07-27",
}
const ID_DATABASE = "[データベースのID]"

グローバル領域に、定数として使うものを定義します。
ここでは、APIのエンドポイントの共通部分、シークレットキー、HTTPのヘッダ情報、実際に作用するデータベースのIDを定義しました。

2. メイン関数

function run(){
 let items = getCompletedItems()
 let ids = items.results.map(item => item.id)
 for(i in ids){
   archiveItem(ids[i])
 }
}

トリガーのタイミングが来たら作動する関数です。
まず、完了分タスクを、3章で紹介するサブ関数を用いて抽出し、itemsに代入します。
次にそれらをどんどんアーカイブ化するわけですが、データベース上のアイテム(本記事の場合は完了分タスク)をアーカイブするには、そのアイテムのidがあれば十分です。ただ、この時点では、itemsは情報が多すぎるため、map関数を使いidだけを抽出し、idsという変数で一次元配列として格納します。(返ってくるJSONの構造は本家サイト(英語)をご覧ください。)
最後に、idsに格納されたidを全てを、4章で紹介するサブ関数に通すことで、アーカイブ化していきます。
トリガーについてですが、私の場合、毎月1日0時〜1時の間に動くようにしています。1ヶ月分をどどんと消す寸法です。

3. サブ関数 ①完了分タスクを抽出する関数

function getCompletedItems(){
 let url = ENDPOINT_DATABASE + ID_DATABASE + "/query"
 let filter = {
   "filter" : {
     "or" : [
       {
         "property" : "Status",
         "select" : {
           "equals" : "Completed"
         }
       },
     ]
   } 
 }
 let options = {
   method : "POST",
   contentType : "application/json",
   headers : HEADERS,
   payload : JSON.stringify(filter),
 }
 let result = JSON.parse(UrlFetchApp.fetch(url,options))
 return result
}

まず、指定したデータベースから完了分のみ抽出するサブ関数を作成します。
filterという連想配列がありますが、ここのequalsに対応する値を、ご自分のデータベース上の完了分の分類名に変更しておいてくださいね。
あとは、URLfetchでPOSTし、返ってきたデータをJSON.parseで扱いやすいデータに変えます。

4. サブ関数 ②アイテムをアーカイブする関数

function archiveItem(id){
 let url = ENDPOINT_PAGE + id
 let payload = {
   "archived" : true
 }
 let options = {
   method : "PATCH",
   contentType : "application/json",
   headers : HEADERS,
   payload : JSON.stringify(payload),
 }
 UrlFetchApp.fetch(url,options)
}

引数として、削除するアイテムのidを指定し、それを削除するというAPIを叩きます。
HTTPで{"archived" : true}という情報をPATCHで送信することで、アイテムが削除されます。簡単ですね。
ちなみに今回操作した["archived"]というプロパティは、Notionの全てのページが持っています。他にも色々応用できそうですね。

まとめ

今回も非常にシンプルに実装することができました。
少しずつNotion APIもアップデートされ、APIリファレンスも充実してきて、ますます楽しみなツールになってきましたね。

今回は単純にアーカイブしましたが、プログラムのイメージ的には、毎月大掃除して、月関係なくゴミ箱にまとめてしまう方法です。つまり、その月にいくつのアイデアを消化したかがちょっと分かりにくくなるんですよね。
達成度を見るなら、アーカイブするよりも、何か別のデータベースを用意して、そちらに月毎にまとめて移動させたい。。。ただ、PATCH送信でやってみたんですが、親アイテムを変更するというのはまだ対応していないようです。
アイテムの親アイテム変更ができたら、Notion自由度ほぼMAXみたいなものですよね。今後の開発に期待です。

この記事が気に入ったらサポートをしてみませんか?