Skip to content

Instantly share code, notes, and snippets.

@leoherzog
Last active Feb 23, 2021
Embed
What would you like to do?
Google Drive Folder Change Notifier
/**
* This script checks a Google Drive folder for any new files and/or folders added to it, and emails you if there are changes!
* To get started:
* 1. Go to script.google.com and log in as the user that you want to do the automated "checking".
* 2. Click "New Project".
* 3. Rename the project at the top from "Untitled project" to something else (ex. "Folder Change Notifier") and copy/paste this code over the default "myFunction" stuff that's currently there.
* 4. Add the folder IDs to the "foldersToCheck" array on line 16 below, in quotes, comma-separated. It should look something like:
* const foldersToCheck = ["1J5d673365fd944334be51d4163cd8294d", "1c5d63119b730c8224a218222e5faedcad"];
* 5. Add the email address that you want to notify for when there's changes on line 18 below. It should look something like:
* const emailToNotify = "name@gmail.com";
* 6. Click "▷ Run" on the top toolbar. You should get an email with all of the "additions" as the script checks for and remembers the contents for the first time. It will now check every hour for changes!
* You can always add more folder IDs to the array on line 16 at any time.
*/
const foldersToCheck = ["1J5d673365fd944334be51d4163cd8294d", "1c5d63119b730c8224a218222e5faedcad"];
const emailToNotify = "";
/*
╭────────────╮
│ Do not │
│ edit below │
╰┬──────────┬╯
*/
function check() {
let properties = PropertiesService.getScriptProperties();
for (let id of foldersToCheck) {
let folder;
try {
folder = DriveApp.getFolderById(id);
} catch(e) {
console.error(e.message);
console.error("Does the folder " + id + " exist, and are you able to view it as " + Session.getActiveUser().getEmail() + "?");
continue;
}
let contents = getFolderContents_(folder);
let lastCheck = JSON.parse(properties.getProperty(id));
if (!lastCheck) { lastCheck = {"folders": [], "files": []}; }
let removedFiles = lastCheck.files.filter(x => !contents.files.includes(x));
let addedFiles = contents.files.filter(x => !lastCheck.files.includes(x));
let removedFolders = lastCheck.folders.filter(x => !contents.folders.includes(x));
let addedFolders = contents.folders.filter(x => !lastCheck.folders.includes(x));
if (removedFiles.length || addedFiles.length || removedFolders.length || addedFolders.length) {
console.info("Differs from last check!");
let subject = 'New Change in "' + folder.getName() + '" Folder';
let htmlBody = '<p><strong>New change detected in the 📁 <a href="' + folder.getUrl() + '" target="_blank">' + folder.getName() + '</a> folder.</strong></p>';
if (removedFiles.length) {
console.log("Files removed: " + JSON.stringify(removedFiles));
htmlBody += '<p>';
htmlBody += removedFiles.length + ' file(s) removed:';
htmlBody += '<ul>';
for (let id of removedFiles) {
let file = DriveApp.getFileById(id);
htmlBody += '<li>📄 <a href="' + file.getUrl() + '" target="_blank">' + file.getName() + '</a></li>';
}
htmlBody += '</ul>';
htmlBody += '</p>';
}
if (addedFiles.length) {
console.log("Files added: " + JSON.stringify(addedFiles));
htmlBody += '<p>';
htmlBody += addedFiles.length + ' file(s) added:';
htmlBody += '<ul>';
for (let id of addedFiles) {
let file = DriveApp.getFileById(id);
htmlBody += '<li>📄 <a href="' + file.getUrl() + '" target="_blank">' + file.getName() + '</a></li>';
}
htmlBody += '</ul>';
htmlBody += '</p>';
}
if (removedFolders.length) {
console.log("Folders removed: " + JSON.stringify(removedFolders));
htmlBody += '<p>';
htmlBody += removedFolders.length + ' folder(s) removed:';
htmlBody += '<ul>';
for (let id of removedFolders) {
let file = DriveApp.getFileById(id);
htmlBody += '<li>📁 <a href="' + file.getUrl() + '" target="_blank">' + file.getName() + '</a></li>';
}
htmlBody += '</ul>';
htmlBody += '</p>';
}
if (addedFolders.length) {
console.log("Folders added: " + JSON.stringify(addedFolders));
htmlBody += '<p>';
htmlBody += addedFolders.length + ' folder(s) added:';
htmlBody += '<ul>';
for (let id of addedFolders) {
let file = DriveApp.getFileById(id);
htmlBody += '<li>📁 <a href="' + file.getUrl() + '" target="_blank">' + file.getName() + '</a></li>';
}
htmlBody += '</ul>';
htmlBody += '</p>';
}
htmlBody += '<p><small>Generated from the <a href="https://script.google.com/home/projects/' + ScriptApp.getScriptId() + '/edit" target="_blank">' + DriveApp.getFileById(ScriptApp.getScriptId()).getName() + '</a> script</small></p>';
let plainBody = htmlBody.replace(/(<([^>]+)>)/ig, "");
MailApp.sendEmail(emailToNotify, subject, plainBody, {"htmlBody": htmlBody});
console.log("Sent email with changes");
properties.setProperty(id, JSON.stringify(contents));
} else {
console.log("No changes since last check.");
}
}
verifyScheduled_();
}
function getFolderContents_(folder) {
let contents = {"folders": [], "files": []};
// check folders
let folderIterator = folder.getFolders();
while (folderIterator.hasNext()) {
let subfolder = folderIterator.next();
contents.folders.push(subfolder.getId());
}
contents.folders.sort();
// check files
let fileIterator = folder.getFiles();
while (fileIterator.hasNext()) {
let file = fileIterator.next();
contents.files.push(file.getId());
}
contents.files.sort();
console.log('Gathered contents for "' + folder.getName() + '" folder:');
console.log(JSON.stringify(contents));
return contents;
}
function verifyScheduled_() {
let triggers = ScriptApp.getProjectTriggers();
if (!triggers.length || triggers.length >= 2 || triggers[0].getHandlerFunction() !== "check") {
console.warn("Deleting all existing triggers and rescheduling hourly trigger.");
for (let trigger of triggers) {
ScriptApp.deleteTrigger(trigger);
}
ScriptApp.newTrigger("check").timeBased().everyHours(1).create();
console.info("Scheduled to run every hour!");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment