こんにちは。AMDlabの掛田です。
今回はGoogle Apps Script(以下GAS)を使って、
Google Driveのファイル一覧をNotion APIを用いてNotionのデータベースに登録することで、Google DriveにどういうファイルがあるかをNotion上で見られるようにしてみます。
今回の記事の使用ケースとしては、情報管理にNotionを使用していて、ファイル管理にGoogle Driveを使用している場合に、Notionに情報が集約されることで便利になる内容になっています!
GASでは書いたプログラム自体をバッチ処理のようなイメージで何時間おき、何分おきと実行間隔を設定できるので、
一定の間隔でプログラムを実行し、Google DriveとNotionにファイルデータの差分があれば自動でNotionに登録させる動きにします。
※今回はあくまでどういうファイルがあるかだけを登録するので、実際のファイルをみるときはNotionに登録するファイルのリンクからGoogle Driveを参照する必要があります。
GASとは?
Googleが提供しているプラットフォームで、JavaScriptベースで記述されたプログラムを手軽に実行できます。
また、GoogleドキュメントやGoogleスプレッドシート等のGoogleの各種サービスと連携するプログラムが作りやすいという特徴があります。
GAS上でプログラムを実行できるので、手元に開発環境を揃える必要はありません。
GASの事前準備
Google Driveにアクセスし、右上の「新規」ボタンを押すとメニューが出るので、
「その他 > Google Apps Script」を選択し、GASのプロジェクトを作成します。
必要な情報の事前準備
今回の記事のプログラムでは以下3種類の情報を事前に取得しておく必要があります。
- Google DriveのフォルダID
- Notion APIのシークレット
- NotionのデータベースID
Google DriveのフォルダID
今回のプログラムの対象とするフォルダIDをGoogle Driveから取得したいので、
Google Driveで対象のフォルダを開きます。
URLをみてみると、URL後半のfolders/以降にランダムな文字列があり、これがフォルダIDです。
Notion APIのシークレット
添付の画像の手順でAPIのシークレットを作成し、取得します。
↓
↓
↓
NotionのデータベースID
Notionで対象のデータベースをフルページで表示し、リンクを取得します。
リンクは以下のような形式で、手前のランダム文字列がデータベースIDです。
https://www.notion.so/{ランダム文字列}?v={ランダム文字列}&pvs=4
Notionの事前準備
先程フルページで表示していたデータベースのページで、ページ右上の三点リーダーからコネクトの設定をおこないます。
Notion APIを作成時に設定した名前が選択肢にあるはずなので、そちらを選択すると
Notion APIを用いてデータベースの情報を取得・登録がおこなえるようになります。
この設定を省いてしまうと、Notion APIをプログラムから使用してもエラーになってしまいます。
GASで書いたプログラムについて
Notion側のデータベースには以下のプロパティは2種類を用意しました。
- ファイル名(プロパティ種別:タイトル)
- URL(プロパティ種別:URL)
この2種類のプロパティを持つデータを1レコードとしてプログラムから登録できるようにします。
全体の流れ
- Google Drive上の特定のフォルダに入っているファイルを、子階層も含めて全て取得する(取得関数を再帰的に実行することで子階層も取得します)
- Notion上のデータベースに入っているファイルを全て取得する
- 1で取得したファイル一覧と2で取得したファイル一覧の中身を比較し、Notionのデータベースに未登録のファイルを抽出する
- 3で取得した未登録のファイル一覧をNotion APIでNotionのデータベースに登録する
実際のプログラム
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
// 事前に取得したドライブのフォルダIDを入れる const DRIVE_FOLDER_ID = "" // 事前に取得したNotionのシークレットを入れる const NOTION_INTEGRATION_SECRET = "" // 事前に取得したNotionのデータベースIDを入れる const NOTION_DATABASE_ID = "" function myFunction() { const driveFolder = DriveApp.getFolderById(DRIVE_FOLDER_ID) // GoogleDriveからファイル一覧を取得 const driveFiles = getFilesRecursiveFromDrive(driveFolder) // Notionからファイル一覧を取得 const notionFiles = getFilesFromNotion() // GoogleDriveとNotionのファイルデータを比較して差分を抽出 const unregisteredDriveFiles = driveFiles.filter((driveFile) => { const isRegistered = notionFiles.some((notionFile) => notionFile.properties["URL"]["url"] === driveFile.url) return !isRegistered }) // unregisteredFilesをNoiton APIでデータベースへ登録 unregisteredDriveFiles.map((file) => { addFileToNotion(file.name, file.url) }) // 実行結果をログに表示 const count = unregisteredDriveFiles.length const fileNames = unregisteredDriveFiles.map((file) => file.name) Logger.log(`新規ファイル:${count}件\n${fileNames.join("\n")}`) } function getFilesRecursiveFromDrive(driveFolder) { const driveFiles = driveFolder.getFiles() let files = [] // driveFolder配下のファイルを取得 while (driveFiles.hasNext()) { const driveFile = driveFiles.next() const file = { name: driveFile.getName(), url: driveFile.getUrl() } files.push(file) } const subDriveFolders = driveFolder.getFolders() while (subDriveFolders.hasNext()) { const subDriveFolder = subDriveFolders.next() const subDriveFiles = getFilesRecursiveFromDrive(subDriveFolder) files = [...files, ...subDriveFiles] } return files } function getFilesFromNotion() { let files = [] let hasMore = true let startCursor = undefined while (hasMore) { const payload = { start_cursor: startCursor } const options = { headers: { Authorization: `Bearer ${NOTION_INTEGRATION_SECRET}`, "Notion-Version": "2022-06-28", }, contentType: "application/json", method: "POST", payload: JSON.stringify(payload) } const response = UrlFetchApp.fetch(`https://api.notion.com/v1/databases/${NOTION_DATABASE_ID}/query`, options) const data = JSON.parse(response.getContentText()) files = [...files, ...data.results] startCursor = data.next_cursor hasMore = data.has_more } return files } function addFileToNotion(fileName, fileUrl) { const properties = { parent: { 'database_id': NOTION_DATABASE_ID, }, properties: { "ファイル名": { "title": [ { "text": { "content": fileName } } ] }, "URL": { "url": fileUrl } } } const options = { headers: { Authorization: `Bearer ${NOTION_INTEGRATION_SECRET}`, "Notion-Version": "2022-06-28", }, contentType: "application/json", method: "POST", payload: JSON.stringify(properties), } try { UrlFetchApp.fetch(`https://api.notion.com/v1/pages`, options) } catch(e) { Logger.log(`予期せぬエラーが発生しました\n${e}`) } } |
関数は大きく分けて4つ作成しました。
- myFunction()
- getFilesRecursiveFromDrive(フォルダID)
- getFilesFromNotion()
- addFileToNotion(ファイル名, ファイルURL)です。
myFunction()をメイン処理とし、他の関数を呼ぶなど全体の流れを記述しました。
ほとんどはJavaScriptの構文ですが、GASではAPIのコールにはUrlFetchAppというクラスを使用するようでした。
Notion APIをコールする際にヘッダーに指定しているNotion-Version
はNotionのAPIバージョンの指定で、2022-06-28が現時点では最新のようです。
プログラムの実行タイミングを設定
GASの左のサイドバーからトリガー(実行タイミング)を設定できます。
今回は5分間隔でmyFunctionを実行するよう設定してみました!
……5分後
Notionにファイル情報が登録されていることが確認できました。
もっと欲をいうとNotionに登録する際にGoogle Driveのフォルダ構造を保ちつつ登録できたらベストなのですが、、、
締め
今回はGASでGoogle Driveのファイル一覧でNotionで見られるようにするプログラムを書いてみました。
GASでは他にもGoogleスプレッドシートやGoogleフォームなど連携できるサービスは多そうです。
アイデア次第でさまざまな使い方ができるので、Googleのサービスと連携しつつ自動で何かを実現したいときに選択肢の1つとして考えていただければと思います!
COMMENTS