【ソースコード付き】GoogleDriveでファイルが追加・更新されたらメールで通知する
01
- 9月
2017
Posted By : boomin
【ソースコード付き】GoogleDriveでファイルが追加・更新されたらメールで通知する
Advertisements

概要

google driveでファイルの変更(追加や削除、更新)を監視、変更があった場合に、 指定した宛先にメールで通知するシステムです。

開発の背景

もともとは、遠方の家族と写真を共有するために開発しました。 DropBoxではデフォルトで通知が行えるので、これが使えればよかったのですが。 残念ながら、デバイスというかOSの機能で通知を行うために、 それに対応するPCなりデバイスを持っていることが必要となります。

Google Driveなら、

  • アカウントさえ持っていればファイルの共有は簡単
  • Google App Scriptなら サーバ不要
  • メール通知なら、ガラケーへも通知できる

という理由で、選びました。Googleってインフラを抑えちゃってるから、やっぱり強いですよね。

想定している使われ方

  • 仲間内で、共同で資料共有、編集などを行うとき
  • 遠方の両親に、孫の写真を共有するとき

いちいち、編集や追加するたびに、連絡するのもかったるいですからね。
ITの知識を多少かじっているなら、これくらいサクッと作っておきたいものです。

1.1 前提条件

  • google accountを持っていること
  • google documentが使える状態であること
Advertisements

1.2 事前に準備するもの

以下のものが必要となります。 1つずつ、説明していきます。

#作成するもの説明
1Google Driveのフォルダ共有する写真などのファイルを配置するフォルダ
2Google DriveのフォルダのID#1のフォルダのID
3スプレッドシートフォルダの更新情報を保存するためのスプレッドシート
4スプレッドシートのID#3のスプレッドシートのID
5スプレッドシートのシート名スプレッドシートの中の、実際に情報を録するシート名

#1 Google Driveのフォルダ

何はともあれ、監視対象となるフォルダがないと話になりません。
フォルダを作成しましょう。名前は何でもよいです。

#2 Google DriveのフォルダID

対象とするGoogle DriveフォルダのIDが必要です。
これは、ブラウザでアクセスして、URLを見れば分かります。

塗りつぶしていますが、選択状態にある、青く反転させられている部分が、フォルダのIDになります。
フォルダーの場合、/folders/ の後に続いている、半角英数字の羅列です。

#3 スプレッドシート

スプレッドシートを1つ作成してください。 ファイル名、場所のどちらも、適当でかまいません。

ここでは、folderlist という名前のスプレッドシートを用意しました。 さらに、中を以下のように編集します。

要するに、情報を一覧にする際の、ヘッダーを作成しています。

#4 スプレッドシートのID

Google DriveフォルダのIDと同様、ブラウザでアクセスして、URLを見れば分かります。

塗りつぶしていますが、選択状態にある、青く反転させられている部分が、フォルダのIDになります。
スプレッドシートの場合、spreadsheets/d の後に続いている、半角英数字の羅列です。

#5 スプレッドシートのシート名

エクセルのシート名と同じです。

1.3 Google App Scriptを用意する

それでは、Google App Scriptを実装して、動かしてみます。
以下のような感じで、スクリプトを書いていきます。

実際のコード全文は、以下の通りです。

//対象とするGoogleDriveフォルダのID ブラウザでアクセスしてURL見れば分かる
var PHOTO_FOLDER_ID = "*************************";
//更新日時を記録するのスプレッドシートのID ブラウザでアクセスしてURL見れば分かる
var UPDATE_SHEET_ID = "*************************";
//スプレッドシートのシート名(下に表示されるタブのやつ)
var UPDATE_SHEET_NAME = "シート1";
//宛先
var SEND_MAIL_ADDRESS = ["aaa@gmail.com", "bbb@gmail.com"]
//送り主
var SENDER_MAIL_ADDRESS = ["ccc@gmail.com"]

//フォルダ内を再帰的に探索してすべてのファイル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();
    filesIdList = filesIdList.concat(getAllFilesId(child_folder));
  }
  return filesIdList;
}

function updateCheck() {
  var photoFolder = DriveApp.getFolderById(PHOTO_FOLDER_ID);
  var folders = photoFolder.getFolders();

  var folderData = {};

  // 写真フォルダ配下の最終更新日時を取得。
  while (folders.hasNext()) {
    var folder = folders.next();

    // フォルダ最終更新日時
    var lastFolderUpdateDate = folder.getLastUpdated();
    // フォルダ内のファイルの最終更新日時が新しい場合もあるのでそれに対応
    var files = folder.getFiles();
    while (files.hasNext()) {
      var fileobj = files.next();
      if (fileobj.getLastUpdated() > lastFolderUpdateDate) {
        // Logger.log("update LastUpdated: " + lastFolderUpdateDate + ", " + fileobj.getLastUpdated())
        lastFolderUpdateDate = fileobj.getLastUpdated();
      }
    }

    // 情報を連想配列に格納
    folderData[folder.getName()] = {
      name: folder.getName(),
      lastUpdate: lastFolderUpdateDate, // フォルダ最終更新日時
      filenum: getAllFilesId(folder).length, // フォルダ内のファイル数
      url: folder.getUrl(), // フォルダのURL
      diff: 0
    };

  }

  // スプレッドシートに記載されているフォルダ名と更新日時を取得。
  var spreadsheet = SpreadsheetApp.openById(UPDATE_SHEET_ID);
  var sheet = spreadsheet.getSheetByName(UPDATE_SHEET_NAME);
  var data = sheet.getDataRange().getValues();

  // 取得したデータをMapに変換。
  var sheetData = {};
  //  headerがあるので2から開始
  for (var i = 1; i < data.length; i++) {
    sheetData[data[i][0]] = {
      name: data[i][0],
      lastUpdate: data[i][1],
      filenum: data[i][2],
      url: data[i][3],
      rowNo: i + 1
    };
  }

  // 実際のフォルダとスプレッドシート情報を比較。
  var updateFolderList = [];
  for (key in folderData) {
    if (key in sheetData) {
      // フォルダ名がシートに存在する場合。
      if (folderData[key].lastUpdate > sheetData[key].lastUpdate | folderData[key].filenum != sheetData[key].filenum) {
        // フォルダが更新されているか、ファイルが追加されている場合。
        updateFolderList.push(key);
        folderData[key].diff = folderData[key].filenum - sheet.getRange(sheetData[key].rowNo, 3).getValue();
        Logger.log(key+", folderData[key].diff: " + folderData[key].diff);
        sheet.getRange(sheetData[key].rowNo, 2).setValue(folderData[key].lastUpdate);
        sheet.getRange(sheetData[key].rowNo, 3).setValue(folderData[key].filenum);
        sheet.getRange(sheetData[key].rowNo, 4).setValue(folderData[key].url);
      }
    } else {
      // フォルダ名がシートに存在しない場合。
      var lowno = sheet.getLastRow() + 1
      sheet.getRange(lowno, 1).setValue(key);
      sheet.getRange(lowno, 2).setValue(folderData[key].lastUpdate);
      sheet.getRange(lowno, 3).setValue(folderData[key].filenum);
      sheet.getRange(lowno, 4).setValue(folderData[key].url);
      updateFolderList.push(key);
    }
  }

  // 削除されたフォルダをチェックして、フォルダ一覧から削除
  var deleteFolderList = [];
  for (key in sheetData) {
    if (!(key in folderData)) {
      Logger.log(key + " is deleted. row" + sheetData[key].rowNo)
      sheet.deleteRow(sheetData[key].rowNo)
      deleteFolderList.push(key);
    }
  }

  // 新規及び更新された情報をメール送信
  if (updateFolderList.length != 0 | deleteFolderList.length != 0) {

    var bodyText = photoFolder.getName() + "フォルダに、" + updateFolderList.length + "個のフォルダが追加(変更)されました。\n";
    bodyText += photoFolder.getUrl() + "\n\n";

    // フォルダ名、フォルダ更新日時、フォルダ内のファイル数
    if (updateFolderList != 0) {
      bodyText += "フォルダ名        \t枚数\tURL\n";
      for (key in updateFolderList) {
        fld = updateFolderList[key];
        bodyText += fld + "\t" + folderData[fld].filenum;
        if (folderData[fld].diff != 0) {
          //変更されたフォルダがある場合
          bodyText += "(" + folderData[fld].diff + ")";
        }
        bodyText += "枚" + "\t" + folderData[fld].url + "\n";
      }
    }

    if (deleteFolderList != 0) {
      bodyText += "\n以下のフォルダが削除されています。" + "\n";
      for (key in deleteFolderList) {
        fld = deleteFolderList[key];
        bodyText += fld + "\t" + sheetData[fld].filenum + "枚" + "\n";
      }
    }

    bodyText += "\n\nこのメールに返信しても見れませんので返信しないでください。";
    // Logger.log(bodyText)

    var titletext = "フォトアルバム【" + photoFolder.getName() + "】更新連絡通知";
    MailApp.sendEmail(DIST_MAIL_ADDRESS, SENDER_MAIL_ADDRESS, titletext, bodyText);

  } else {
    Logger.log("通知する更新情報がありません")
  }
}

2. 動かしてみる!

2.1 コードの修正

先頭部分の、以下の内容は、実行環境に応じて修正してください。

//対象とするGoogleDriveフォルダのID ブラウザでアクセスしてURL見れば分かる 
var PHOTO_FOLDER_ID = "*************************"; 
//更新日時を記録するのスプレッドシートのID ブラウザでアクセスしてURL見れば分かる
var UPDATE_SHEET_ID = "*************************"; 
//スプレッドシートのシート名(下に表示されるタブのやつ) 
var UPDATE_SHEET_NAME = "シート1"; 
//宛先 
var SEND_MAIL_ADDRESS = ["aaa@gmail.com", "bbb@gmail.com"] 
//送り主 
var SENDER_MAIL_ADDRESS = ["ccc@gmail.com"]

2.2 実行!

以下のようにして、updateCheck を実行させて下さい。

特に問題がなければ、以下のようなメールが届いているはずです。

3. 自動実行

それでは、最後にこれを自動で実行させるための設定を行いましょう。
これを設定しておけば、Google Driveにファイルが追加、更新、削除があった場合に、自動でこれを検知して、その変更内容とともにメールを送ってくれます。

よりリアルタイムに更新情報が欲しい場合は、「分タイマー」 に設定しておくとよいでしょう。

おわりに

自前でサーバを立てなくても、こういうことができちゃうのは、便利ですよね。

Advertisements

コメントを残す