Last active
July 29, 2022 16:33
-
-
Save cmbuckley/587f913627c843f4becc8c5db9d4a82e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const config = { | |
'[email protected]': { | |
prefix: 'Source', | |
color: CalendarApp.EventColor.PALE_RED, | |
visibility: 'private' | |
}, | |
}; | |
function onCalendarChanged(trigger) { | |
copyEvents(trigger.calendarId); | |
} | |
function copyAll() { | |
Object.keys(config).forEach(copyEvents); | |
} | |
function copyEvents(sourceId) { | |
if (!config[sourceId]) { | |
throw new Error('Missing config for ' + sourceId); | |
} | |
// avoid multiple scripts running at the same time | |
const lock = LockService.getScriptLock(); | |
lock.tryLock(1000); | |
if (!lock.hasLock()) { | |
console.log('Process already running'); | |
return; | |
} | |
console.log('Copying events from ' + sourceId); | |
const summaryPrefix = (config[sourceId].prefix ? `[${config[sourceId].prefix}] ` : ''); | |
const syncDays = config[sourceId].syncDays || 14; | |
const targetId = Session.getActiveUser().getEmail(); | |
// start and end dates | |
let startDate = new Date(); | |
let endDate = new Date(); | |
endDate.setDate(startDate.getDate() + syncDays); | |
// delete and recreate in case things move | |
// @todo if there's no prefix, it'll delete everything in your calendar! | |
if (summaryPrefix) { cleanup(syncDays, summaryPrefix); } | |
// get all events | |
const listResponse = Calendar.Events.list(sourceId, { | |
timeMin: startDate.toISOString(), | |
timeMax: endDate.toISOString(), | |
singleEvents: true, | |
}); | |
// loop over and copy | |
listResponse.items.forEach(function (event) { | |
const summary = (event.summary || '(No title)'); | |
console.log('Copying event: ' + summary + ' (' + (event.start.dateTime || event.start.date) + ')'); | |
Calendar.Events.insert({ | |
start: event.start, | |
end: event.end, | |
summary: summaryPrefix + summary, | |
description: event.description, | |
conferenceData: event.conferenceData, | |
colorId: config[sourceId].color || 0, | |
visibility: config[sourceId].visibility || event.visibility, | |
attendees: event.attendees ? [{ | |
email: targetId, | |
responseStatus: event.attendees.find(a => a.self).responseStatus | |
}] : [] | |
}, targetId, { | |
conferenceDataVersion: 1 | |
}); | |
Utilities.sleep(500); | |
}); | |
lock.releaseLock(); | |
console.log('All events copied'); | |
} | |
function cleanup(daysAhead, titlePrefix) { | |
let calendar = CalendarApp.getCalendarById(Session.getActiveUser().getEmail()); | |
let startDate = new Date(); | |
let endDate = new Date(); | |
endDate.setDate(startDate.getDate() + daysAhead); | |
calendar.getEvents(startDate, endDate).forEach(function (event) { | |
if (event.getTitle().startsWith(titlePrefix)) { | |
console.log('Deleting event: ' + event.getTitle() + ' (' + event.getStartTime().toLocaleString('en-GB') + ')'); | |
try { | |
event.deleteEvent(); | |
} catch (e) { | |
console.log('Failed to delete: ' + e); | |
} | |
Utilities.sleep(500); | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Copy Calendar Events
This Apps Script copies calendar events from any number of source calendars. This can be useful
when use multiple work calendars and need colleagues to see your true availability.
Note
This script currently deletes events from your target calendar and recreates them. Not only is this a naïve approach, it is risky that it might delete events not part of the sync that just happen to have a similar title.
Installation
Code.gs
with the contents ofcopyCalendarEvents.gs
. Update the configuration appropriately (see below).Configuration
The script begins with a config object taking the following options:
<source_calendar>
<source_calendar>.prefix
Prefix
, the title is prefixed with[Prefix]
. Defaults to empty string, which adds no prefix to the title.<source_calendar>.color
EventColor
enum values. Defaults to 0, which does not change the event's colour.<source_calendar>.visibility
"default"
,"public"
or"private"
. Overrides the source calendar event's visibility, for instance to hide sensitive information. Defaults to the event's existing visibility.<source_calendar>.syncDays