Skip to content

Instantly share code, notes, and snippets.

@hmarr
Last active November 8, 2023 23:10
Show Gist options
  • Save hmarr/01cf506c0400b5ff35a59e053b1f94cb to your computer and use it in GitHub Desktop.
Save hmarr/01cf506c0400b5ff35a59e053b1f94cb to your computer and use it in GitHub Desktop.
Google Apps Script to automatically color calendar events
// Setup instructions
//
// Copy and paste into a Google Apps Script project. Feel free to change the colors below.
//
// Add a trigger to run the colorUpdatedCalendarEvents function the on the "Calendar updated" event of
// your calendar.
const PERSONAL_COLOR = CalendarApp.EventColor.GRAY;
const IN_PERSON_COLOR = CalendarApp.EventColor.BLUE;
const EXTERNAL_COLOR = CalendarApp.EventColor.RED;
const INTERNAL_COLOR = undefined; // Default blue color
function colorUpdatedCalendarEvents(e) {
const calendarId = e?.calendarId ?? "primary";
const calendar = Calendar.Calendars.get(calendarId);
const updatedEvents = getUpdatedCalendarEvents(calendar.id, false);
for (const event of updatedEvents) {
if (event.status === 'cancelled') {
continue;
}
if (event.eventType === "default") {
setEventColor(calendar.id, event);
}
}
}
function setEventColor(calendarId, event) {
const calendarDomain = calendarId.split("@")[1];
console.log("Setting color for", event.summary ?? event.id);
const attendees = [event.organizer, ...(event.attendees ?? [])];
const guestEmails = attendees.filter(a => !a.self).map(a => a.email);
const hasExternalGuest = guestEmails.some(e => e.split("@")[1] !== calendarDomain);
if (event.location && event.location !== "") {
console.log(`${event.summary}: in-person`);
event.colorId = IN_PERSON_COLOR;
} else if (guestEmails.length === 0) {
console.log(`${event.summary}: personal`)
event.colorId = PERSONAL_COLOR;
} else if (hasExternalGuest) {
console.log(`${event.summary}: external`)
event.colorId = EXTERNAL_COLOR;
} else {
console.log(`${event.summary}: internal`)
event.colorId = INTERNAL_COLOR;
}
try {
Calendar.Events.update(event, calendarId, event.id);
} catch (err) {
console.error("error updating event %s: %s", event.id, err.message);
}
}
/**
* Find and return events in the given calendar that have been modified
* since the last sync. If the sync token is missing or invalid, return all
* events from up to a week ago (a full sync).
*
* @param {string} calendarId The ID of the calender to retrieve events from.
* @param {boolean} fullSync If true, throw out any existing sync token and
* perform a full sync; if false, use the existing sync token if possible.
*/
function getUpdatedCalendarEvents(calendarId, fullSync) {
console.log("Fetching updated calendar events, full sync =", fullSync);
const properties = PropertiesService.getUserProperties();
const options = { maxResults: 100 };
const syncToken = properties.getProperty('syncToken');
if (syncToken && !fullSync) {
options.syncToken = syncToken;
} else {
// Sync events up to seven days in the past.
options.timeMin = getRelativeDate(-7, 0).toISOString();
}
// Retrieve events one page at a time.
let events = [];
let pageToken;
let response;
do {
try {
options.pageToken = pageToken;
response = Calendar.Events.list(calendarId, options);
events = events.concat(response.items);
} catch (e) {
// Check to see if the sync token was invalidated by the server;
// if so, perform a full sync instead.
if (e.message === 'Sync token is no longer valid, a full sync is required.') {
properties.deleteProperty('syncToken');
return getUpdatedCalendarEvents(calendarId, true);
}
throw new Error(e.message);
}
pageToken = response.nextPageToken;
} while (pageToken);
properties.setProperty('syncToken', response.nextSyncToken);
return events;
}
/**
* Helper function to get a new Date object relative to the current date.
* @param {number} daysOffset The number of days in the future for the new date.
* @param {number} hour The hour of the day for the new date, in the time zone
* of the script.
* @return {Date} The new date.
*/
function getRelativeDate(daysOffset, hour) {
const date = new Date();
date.setDate(date.getDate() + daysOffset);
date.setHours(hour);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
return date;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment