読者です 読者をやめる 読者になる 読者になる

uyamazakのブログ

仕事中の問題と解決メモ。PythonとGoogle Cloudがメイン。bizoceanで新規事業の企画と開発担当。 BigQueryを使ったビッグデータ収集・解析・リアルタイム処理プロジェクト進行中 https://github.com/uyamazak/oceanus

Google Driveでフォルダ内のファイルが更新されたらメール通知を送るGoogle Apps Script

Google Drive(以下GD)でファイルを作ったり、更新したときに、メールでいちいち通知するのが面倒といわれ作った。

初めてGoogle Apps Scriptを使ったけど、javascriptライクで、GoogleAPIを簡単に使えて、サーバー代、メンテナンスもかからないのはかなり便利。

yamap55.hatenablog.com
こちらを参考にさせていただきました。


Githubにも置きました
GitHub - uyamazak/gdrive_update_notifier: Google Driveで更新があった際にメール通知を送るGoogle Apps Script。


フォルダを最下部まで探るために、再帰関数を作ったのががんばったところ。

使い方

GD上で記録用のスプレッドシートを作る。

ツール→スクリプトエディタで、下記内容を張り付ける

//対象とするGoogleDriveフォルダのID ブラウザでアクセスしてURL見れば分かる
var TARGET_FOLDER_ID = "";
//更新日時を記録するのスプレッドシートのID ブラウザでアクセスしてURL見れば分かる
var UPDATE_SHEET_ID = "";
//スプレッドシートのシート名(下に表示されるタブのやつ)
var UPDATE_SHEET_NAME = "シート1";
var SEND_MAIL_ADDRESS = ["name@example.co.jp","name2@example.co.jp"]

function updateCheck() {
  var targetFolder = DriveApp.getFolderById(TARGET_FOLDER_ID);
  var folders = targetFolder.getFolders();
  var files = targetFolder.getFiles();

  //フォルダ内を再帰的に探索してすべてのファイルIDを配列にして返す
  function getAllFilesId(targetFolder){
    var filesIdList = [];
    
    var files = targetFolder.getFiles();
    while(files.hasNext()){
      filesIdList.push(files.next().getId());
    }
    
    var child_folders = targetFolder.getFolders();
    while(child_folders.hasNext()){
      var child_folder = child_folders.next();
      //Logger.log( 'child_folder :' + child_folder );

      //Logger.log('getAllFilesId(child_folder):'+ getAllFilesId(child_folder));
      filesIdList = filesIdList.concat( getAllFilesId(child_folder) );
    }
    return filesIdList;
  }
  //Logger.log('getAllFilesId(targetFolder):' + getAllFilesId(targetFolder));
  var allFilesId = getAllFilesId(targetFolder);
  var lastUpdateMap = {};
  //Logger.log(folders)
  allFilesId.forEach(
    function( value, i ){
      var file =DriveApp.getFileById( value );
      lastUpdateMap[file.getName()] = {lastUpdate : file.getLastUpdated(), fileId: file.getId()};
    }
  );          
 
  // スプレッドシートに記載されているフォルダ名と更新日時を取得。
  var spreadsheet = SpreadsheetApp.openById(UPDATE_SHEET_ID);
  var sheet = spreadsheet.getSheetByName(UPDATE_SHEET_NAME);
  //Logger.log(sheet)
  var data = sheet.getDataRange().getValues();
  //Logger.log('data: ' + data)
  // 取得したデータをMapに変換。
  var sheetData = {};
  for (var i = 0; i < data.length; i++) {
    sheetData[data[i][0]] = {name : data[i][0], lastUpdate : data[i][1], rowNo : i + 1};
  }

  // 実際のフォルダとスプレッドシート情報を比較。
  var updateFolderMap = [];
  for (key in lastUpdateMap) {
    if( UPDATE_SHEET_ID == lastUpdateMap[key].fileId ){
      continue;
    }
    if(key in sheetData) {
      // フォルダ名がシートに存在する場合。
      if(lastUpdateMap[key].lastUpdate > sheetData[key].lastUpdate) {
        // フォルダが更新されている場合。
        sheet.getRange(sheetData[key].rowNo, 2).setValue(lastUpdateMap[key].lastUpdate);
        sheet.getRange(sheetData[key].rowNo, 3).setValue(lastUpdateMap[key].fileId);
        updateFolderMap.push({filename:key, lastUpdate:lastUpdateMap[key].lastUpdate, fileId:lastUpdateMap[key].fileId});
      }
    } else {
      // フォルダ名がシートに存在しない場合。
      var newRow = sheet.getLastRow() + 1;
      sheet.getRange(newRow, 1).setValue(key);
      sheet.getRange(newRow, 2).setValue(lastUpdateMap[key].lastUpdate);
      sheet.getRange(newRow, 3).setValue(lastUpdateMap[key].fileId);
      updateFolderMap.push({filename:key, lastUpdate:lastUpdateMap[key].lastUpdate, fileId:lastUpdateMap[key].fileId});
    }
  }
  //Logger.log('updateFolderMap:' + updateFolderMap)
  // 新規及び更新された情報をメール送信。
  var updateText = "";
  for( key in updateFolderMap ){
    item = updateFolderMap[key];
    updateText += 
     item.filename + ' 更新日時:' + Utilities.formatDate(item.lastUpdate, "JST", "yyyy-MM-dd HH:mm:ss") + '\n' 
    + DriveApp.getFileById(item.fileId).getUrl() + "\n\n"
  }
  
  if (updateFolderMap.length != 0) {
    SEND_MAIL_ADDRESS.forEach(function(o,i) {
      MailApp.sendEmail(SEND_MAIL_ADDRESS[i],targetFolder.getName() + "更新連絡通知",
                        "【" + targetFolder.getName() + "】が更新されました。\n\n"+
                        updateText
                        );
    });
  }
}


URLを見て、記録用スプレッドシートのIDをUPDATE_SHEET_IDに入れる

https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxxxx/edit#gid=0


監視対象とするGDのフォルダを開いて、URLからIDをTARGET_FOLDER_IDにコピペ

https://drive.google.com/drive/folders/xxxxxxxxxxxxxxxxxxxx

シート名をいじってなければ「シート1」のまま、変更したらUPDATE_SHEET_NAMEを変える

SEND_MAIL_ADDRESS に送信先メールアドレスを追加


スクリプトエディタで保存して、実行(三角形のやつ)をクリックして、メールが来るか確認する。

初回はすべてのファイルに対して通知がくるはず。

送信元は操作しているアカウントのGmailとなり、送信済みフォルダにメールが入ってしまうのは注意。

手動で動かしてみて、問題がなければ、時計マークをクリックして、トリガーを設定する。

15分とか30分程度がいいかも。