Skip to content

Instantly share code, notes, and snippets.

@WhatsARanjit
Created September 9, 2026 21:30
Show Gist options
  • Select an option

  • Save WhatsARanjit/e75970b0f5e5be9103d5784e4e6b66c5 to your computer and use it in GitHub Desktop.

Select an option

Save WhatsARanjit/e75970b0f5e5be9103d5784e4e6b66c5 to your computer and use it in GitHub Desktop.
Calendar Colorizer
/**
* Lists the next X upcoming events in the user's default calendar.
* @see https://developers.google.com/calendar/api/v3/reference/events/list
*/
function listNextEvents(e) {
// Set pre-configured label IDs
const CUSTOMER_LABEL_ID = 'C25E7F70-3C29-4D46-B87F-7FB449468931';
const TRAVEL_LABEL_ID = 'A1CB409D-AC99-414E-A079-1767AAAFC0D8';
const PERSONAL_LABEL_ID = 'A5E64B30-404C-4047-8F2E-25198C6A1286';
const BLOCK_LABEL_ID = 'A5E64B30-404C-4047-8F2E-25198C6A1286';
const FORUM_LABEL_ID = '7B358992-640C-458C-8B9A-76A6C25972CB';
const ONE_LABEL_ID = '9DCC45FC-5489-4036-90EE-6B8004640566';
const ONE_WAITING_LABEL_ID = '89873B19-681B-4DF2-9532-E84A64AE244D';
const FORUM_MIN = 15;
const MAX_EVENTS = 25;
// Search for last Monday to 7 days ahead
const calendarId = 'primary';
const now = new Date();
const day = now.getDay();
const daysSinceMonday = (day + 6) % 7;
const startTime = new Date(now);
//startTime.setDate(now.getDate() - daysSinceMonday);
startTime.setHours(9, 0, 0, 0);
// Max MAX_EVENTS results
const events = Calendar.Events.list(calendarId, {
timeMin: startTime.toISOString(),
singleEvents: true,
orderBy: "startTime",
maxResults: MAX_EVENTS,
showHiddenInvitations: true,
});
if (!events.items || events.items.length === 0) {
console.log("No events found.");
return;
}
// Domains to ignore, my domain and Google Meet rooms
const internalDomains = [
Session.getActiveUser().getEmail().split("@")[1],
'whatsaranjit.com',
]
// Iterate through results
for (event of events.items) {
if (event.start.date) {
// All-day event.
const start = new Date(event.start.date);
//console.log("%s (%s)", event.summary, start.toLocaleDateString());
continue;
}
const start = new Date(event.start.dateTime);
// Name the meeting
console.log(event.summary);
// There might be no attendees
const allAttendees = event.attendees || [];
const attendees = allAttendees
.map(attendee => attendee)
.filter(entry => entry.resource !== true)
// Filter out internal domains
const externalAttendees = attendees
.map(attendee => attendee.email.split('@')[1].toLowerCase())
.filter(domain => !internalDomains.includes(domain))
const internalAttendees = attendees.filter(
entry => !externalAttendees.some(
excluded => excluded.email === entry.email
)
);
// If we find more domains, they're external
if (externalAttendees.length > 0) {
console.log(`External meeting: ${event.id}`);
// Update color
updateColor(event, CUSTOMER_LABEL_ID);
}
// Next check for 2 internal attendees (including myself) ignoring the room
else if (internalAttendees.length == 2) {
console.log(`Internal meeting: ${event.id}`);
const accepted_one = attendees
.map(attendee => attendee.responseStatus)
.filter(response => response != 'accepted')
if (accepted_one.length > 0) {
// Find if your 1:1 hasn't been accepted yet
console.log(`Internal meeting - pending acceptance: ${event.id}`);
// Update color
updateColor(event, ONE_WAITING_LABEL_ID);
console.log(`Awaiting response to 1:1 from ${accepted_one}`);
}
else {
// Find if your 1:1 has been accepted yet
console.log(`Internal meeting - all accepted: ${event.id}`);
// Update color
updateColor(event, ONE_LABEL_ID);
}
}
// Next check for attendees greater than FORUM_MIN
else if (attendees.length > FORUM_MIN) {
console.log(`Forum meeting: ${event.id}`);
// Update color
updateColor(event, FORUM_LABEL_ID);
}
// Next check for Travel events
else if (event.summary.match(/Travel/)) {
console.log(`Travel meeting: ${event.id}`);
// Update color
updateColor(event, TRAVEL_LABEL_ID);
}
// Next check for Lunch events
else if (event.summary.match(/Lunch/)) {
console.log(`Lunch meeting: ${event.id}`);
// Only worry about solo events that I created
if ((event.attendees || []).length > 1) {
continue;
}
// Update color
updateColor(event, PERSONAL_LABEL_ID);
}
// Next look for personal blocks
else if (event.summary.match(/Block/)) {
// Only worry about solo events that I created
if ((event.attendees || []).length > 1) {
continue;
}
console.log(`Blocked meeting: ${event.id}`);
// Update color
updateColor(event, BLOCK_LABEL_ID);
}
else {
console.log(`Uncategorized meeting: ${event.id}`);
// Clear color
updateColor(event, null);
}
}
}
function updateColor(event, color, calendarId = 'primary') {
console.log(`Current label: ${event.eventLabelId}`);
// Don't make update if the color is already set
if (event.eventLabelId == color) {
return;
}
console.log(`Updating ${event.id} to ${color}`);
try {
const eventu = {
eventLabelId: color,
};
Calendar.Events.patch(
eventu,
calendarId,
event.id, {
eventLabelVersion: 1
}
);
console.log(`Successfully updated event: ${event.id} to ${color}`);
}
catch (e) {
console.log(`Fetch threw an exception: ${e}`);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment