Skip to content

Instantly share code, notes, and snippets.

@leoherzog
Last active May 9, 2024 15:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leoherzog/7720187290603303c403551ce2dbf3e9 to your computer and use it in GitHub Desktop.
Save leoherzog/7720187290603303c403551ce2dbf3e9 to your computer and use it in GitHub Desktop.
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