📡

Google Drive の変更通知を Google Apps Script で受け取る

2022/04/23に公開

Google Apps ScriptGoogle Drive のファイル変更を検出したくなり、変更通知(プッシュ通知)を Google Apps Script で受信する方法を試してみました[1]

Google Drive の変更通知とは

ざっくり書くと「Google Drive のドライブやファイルに変更があったとき Webhook で通知を受け取る」機能です。

詳細については丸投げになってしまいますが、以下の記事が参考になります。

Google Apps Script プロジェクトのセットアップ

Google Drive API の変更通知を受け取るためには以下の設定が必要となります。

  • Drive サービスの追加
  • 「アクセスできるユーザーが全員」の Web アプリとしてデプロイ

これらは appsscript.json を編集することで対応できます。

appsscript.json
{
  "timezone": "america/new_york",
  "dependencies": {
    "enabledadvancedservices": [
      {
        "usersymbol": "drive",
        "version": "v2",
        "serviceid": "drive"
      }
    ]
  },
  "exceptionlogging": "stackdriver",
  "runtimeversion": "v8",
  "webapp": {
    "executeas": "user_deploying",
    "access": "anyone_anonymous"
  }
}

Google Drive から変更通知を受け取るコード

基本的には前述の記事にある Go のコードを Google Apps Script で記述することになりますが、いくつか固有の対応が必要になります(リクエストヘッダーの扱いなど)。

今回はドライブ全体を扱いたいのもあったので、以下のようにしました。

  • startPageToken などはスクリプトプロパティへ保存

  • X-Goog-Resource-State での通知の種類判定は行わない

    • かわりに doPoste.postData.contents 有無で判定する
  • Channel の有効期限対策として、時間指定のトリガーで Channel を再作成する

  • 変更の記録としてスプレッドシートへファイル名と id を書き込む

    • startPageToken がよれてしまわないように念のためスクリプトロックで順序を制御

以下のリポジトリにコードが記載されています。

実際に受信してみる

プロジェクトとコードが用意できたので変更通知を受信してみます。

スプレッドシート

通知されたファイル名が書き込まれるスプレッドシートを作成し id とシート名をメモしておきます。

デプロイと設定

  • git clone https://github.com/hankei6km/test-drive-chages.git . && npm install でリポジトリーをクローン
  • クローンしたリポジトリで clasp create を実行し webapp のスクリプトを作成
  • clasp pushclasp deploy でデプロイを作成

ここでデプロイの URL が必要になります。これは clasp では確認できないので、スクリプトエディターの「デプロイ」「デプロイの管理」を利用します。

図 4-1 URL をコピー

スクリプトエディターでデプロイの URL をコピーできる画面を表示しているスクリーンショット

その後、スクリプトプロパティへ以下の内容を設定します。

  • address - デプロイの URL
  • sheet_id - スプレッドシートの id
  • sheet_name - シート名

受信開始

スクリプトエディターで reset() 関数を実行すると Google Drive から通知が行われます。ドライブ内のファイルを変更するとスプレッドシートへファイル名と id が書き込まれます。

図 4-2 更新の状況がスプレッドシートへ書き込まれる
Google Drive に複数ファイルをコピーし、その後ファイルを 1 つ削除している動画

永続化

channel の有効期限より短い間隔(今回にコードでは 31 分)で reset() 関数を実行すると永続的に受信できます。

受信終了

確認が終わったら stop() 関数を実行して channel を破棄します。

ログ表示

今回はスプレッドシートへ書き込んでいますが、通常は console.log などを利用したくなります。しかし、自分以外がリクエストした POST による関数実行ではログの内容が確認できません。

これは GCP プロジェクトへ変更することで対応できますが、今回は割愛します(検索すると方法はすぐに見つかります)。

おわりに

Google Drive の変更通知を Google Apps Script で受信してしました。

今回のコードを 1 日ほど動かしてみたところ自分の使い方ではパンクすることなく、概ね変更を検出できていました[2]

これで Google Apps Script でもファイルの変更を扱いやすくなったので、作成中のツールでも変更のあったファイルをほぼリアルタイムに操作できそうです。

脚注
  1. 最初は時間指定を利用してみましたが、編集してからしばらく更新されないのはやはり違和感が大きかったです。 ↩︎

  2. 通知には throttle 的な処理が入っているようなので抜けは出てしまいます。 ↩︎

GitHubで編集を提案

Discussion