Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Configuration object for the script settings.
- * @type {Object}
- * @property {Set<string>} targetColors - A set of Google Calendar colour IDs that indicate events to be made private.
- * The colour IDs and their corresponding colours are as follows:
- * 1: Lavender
- * 2: Sage
- * 3: Grape (Purple)
- * 4: Flamingo
- * 5: Banana
- * 6: Tangerine
- * 7: Peacock
- * 8: Graphite (Grey)
- * 9: Blueberry
- * 10: Basil
- * 11: Tomato
- * @property {string} calendarId - The ID of the calendar to monitor.
- * Use "primary" for the user's default calendar or provide a specific calendar ID.
- * @property {boolean} debug - A flag to enable or disable detailed logging.
- * Set to true for debugging or monitoring and false for production to reduce log noise.
- * @example
- * // Customise configuration
- * const CONFIG = {
- * targetColors: new Set(["2", "4"]), // Sage and Flamingo
- * calendarId: "[email protected]",
- * debug: false // Disable detailed logging
- * };
- */
- const CONFIG = {
- targetColors: new Set(["8", "3"]),
- calendarId: "primary",
- debug: true
- };
- /**
- * Main function triggered by onEventUpdated.
- * Handles the processing of the updated event.
- * @param {object} e - The event trigger object containing calendarId and other metadata.
- */
- const onEventUpdated = (e) => {
- try {
- log_(`Trigger event object: ${JSON.stringify(e)}`);
- validateConfig_();
- const calendarId = e.calendarId || CONFIG.calendarId;
- const recentEvent = fetchLatestUpdatedEvent_(calendarId);
- if (!recentEvent) {
- log_(`No recently updated event found.`);
- return;
- }
- log_(
- `Processing updated event: ${recentEvent.summary || "No Title"} (ID: ${
- recentEvent.id
- })`
- );
- processEvent_(recentEvent);
- log_(`Finished processing the updated event.`);
- } catch (error) {
- logError_(
- `Error processing updated event in calendar ${CONFIG.calendarId}`,
- error
- );
- }
- };
- /**
- * Fetches the latest updated event from the specified calendar.
- * Retries once if the event data is incomplete.
- * @param {string} calendarId - The ID of the calendar to fetch events from.
- * @returns {object|null} The most recently updated event, or null if none found.
- */
- const fetchLatestUpdatedEvent_ = (calendarId) => {
- const now = new Date().toISOString();
- const pastMinute = new Date(Date.now() - 1000 * 60).toISOString(); // 1 minute ago
- log_(`Fetching events updated since ${pastMinute} in calendar ${calendarId}`);
- let response = Calendar.Events.list(calendarId, {
- updatedMin: pastMinute,
- singleEvents: true,
- orderBy: "updated",
- maxResults: 1,
- fields: "items(id,summary,colorId,visibility,recurrence)"
- });
- if (response.items && response.items.length > 0) {
- let event = response.items[0];
- log_(`Fetched event details: ${JSON.stringify(event)}`);
- if (!event.summary || !event.colorId) {
- log_(`Event data incomplete. Retrying...`);
- Utilities.sleep(1000); // Wait 1 second
- response = Calendar.Events.list(calendarId, {
- updatedMin: pastMinute,
- singleEvents: true,
- orderBy: "updated",
- maxResults: 1,
- fields: "items(id,summary,colorId,visibility,recurrence)"
- });
- if (response.items && response.items.length > 0) {
- event = response.items[0];
- log_(`Fetched updated event details: ${JSON.stringify(event)}`);
- return event;
- }
- }
- return event;
- }
- log_(`No recently updated events found.`);
- return null;
- };
- /**
- * Processes the given event object.
- * @param {object} event - The event object from the Calendar API.
- */
- const processEvent_ = (event) => {
- if (!event.summary) {
- log_(`Event has no title (ID: ${event.id}). Skipping.`);
- return;
- }
- if (!event.colorId) {
- log_(`Event has no color (ID: ${event.id}). Skipping.`);
- return;
- }
- if (shouldProcessEvent_(event)) {
- if (event.recurrence) {
- log_(
- `Processing recurring event series: ${event.summary} (ID: ${event.id})`
- );
- handleRecurringEventSeries_(event);
- } else {
- log_(`Processing single event: ${event.summary} (ID: ${event.id})`);
- updateEventToPrivate_(event);
- }
- } else {
- log_(`Event does not meet conditions: ${event.summary} (ID: ${event.id})`);
- }
- };
- /**
- * Determines if an event should be processed.
- * @param {object} event - The event object from the Calendar API.
- * @returns {boolean} True if the event meets processing criteria, false otherwise.
- */
- const shouldProcessEvent_ = ({ visibility, summary, id, colorId }) => {
- if (visibility === "private") {
- log_(`Event already private: ${summary} (ID: ${id})`);
- return false;
- }
- if (!CONFIG.targetColors.has(colorId)) {
- log_(`Event does not match target colors: ${summary} (ID: ${id})`);
- return false;
- }
- return true;
- };
- /**
- * Sets a single event's visibility to PRIVATE.
- * @param {object} event - The event object from the Calendar API.
- */
- const updateEventToPrivate_ = ({ id, summary }) => {
- try {
- Calendar.Events.patch(
- {
- visibility: "private"
- },
- CONFIG.calendarId,
- id
- );
- log_(`Set single event to private: ${summary} (ID: ${id})`);
- } catch (error) {
- logError_(
- `Failed to update event visibility: ${summary} (ID: ${id})`,
- error
- );
- }
- };
- /**
- * Validates the CONFIG object at runtime to ensure proper configuration.
- * Throws an error if validation fails.
- */
- const validateConfig_ = () => {
- if (!(CONFIG.targetColors instanceof Set) || CONFIG.targetColors.size === 0) {
- console.error("CONFIG.targetColors is empty or invalid.");
- throw new Error("CONFIG.targetColors is empty or invalid.");
- }
- if (typeof CONFIG.calendarId !== "string" || !CONFIG.calendarId) {
- throw new Error("CONFIG.calendarId must be a non-empty string.");
- }
- };
- /**
- * Formats a log message with a timestamp.
- * @param {string} level - The log level (INFO or ERROR).
- * @param {string} message - The log message.
- * @returns {string} Formatted log message with timestamp.
- */
- const formatLogMessage_ = (level, message) =>
- `[${level} - ${new Date().toISOString()}] ${message}`;
- /**
- * Logs informational messages controlled by the debug flag in CONFIG.
- * @param {string} message - Message to log.
- */
- const log_ = (message) => {
- if (CONFIG.debug) console.log(formatLogMessage_("INFO", message));
- };
- /**
- * Logs error messages.
- * @param {string} message - Error message to log.
- * @param {Error} [error] - Optional error object for additional context.
- */
- const logError_ = (message, error) => {
- console.error(formatLogMessage_("ERROR", message));
- if (error) console.error(error.stack || error.message);
- };
Advertisement
Add Comment
Please, Sign In to add comment