diff --git a/Code.gs b/Code.gs index 87ba8dc..6970e7f 100644 --- a/Code.gs +++ b/Code.gs @@ -87,15 +87,19 @@ var email = ""; // OPTIONAL: If "emailWhenAdded" is set t //!!!!!!!!!!!!!!!! DO NOT EDIT BELOW HERE UNLESS YOU REALLY KNOW WHAT YOU'RE DOING !!!!!!!!!!!!!!!!!!!! //===================================================================================================== function install(){ - //Delete any already existing triggers so we don't create excessive triggers - deleteAllTriggers(); - - if (howFrequent < 1){ - throw "[ERROR] \"howFrequent\" must be greater than 0."; - } - else{ - ScriptApp.newTrigger("install").timeBased().after(howFrequent * 60 * 1000).create();//Schedule next Execution - ScriptApp.newTrigger("startSync").timeBased().after(1000).create();//Start the sync routine + try{ + //Delete any already existing triggers so we don't create excessive triggers + deleteAllTriggers(); + + if (howFrequent < 1){ + throw "[ERROR] \"howFrequent\" must be greater than 0."; + } + else{ + ScriptApp.newTrigger("install").timeBased().after(howFrequent * 60 * 1000).create();//Schedule next Execution + ScriptApp.newTrigger("startSync").timeBased().after(1000).create();//Start the sync routine + } + }catch(e){ + install();//Retry on error } } @@ -104,6 +108,7 @@ function uninstall(){ } var targetCalendarId; +var targetCalendarName; var calendarEvents = []; var calendarEventsIds = []; var icsEventsIds = []; @@ -123,7 +128,7 @@ function startSync(){ sourceCalendars = condenseCalendarMap(sourceCalendars); for each (var calendar in sourceCalendars){ calendarEvents = []; - var targetCalendarName = calendar[0]; + targetCalendarName = calendar[0]; var sourceCalendarURLs = calendar[1]; var vevents; //------------------------ Fetch URL items ------------------------ diff --git a/Helpers.gs b/Helpers.gs index 53b84e8..3837754 100644 --- a/Helpers.gs +++ b/Helpers.gs @@ -34,7 +34,7 @@ function condenseCalendarMap(calendarMap){ function deleteAllTriggers(){ var triggers = ScriptApp.getProjectTriggers(); for (var i = 0; i < triggers.length; i++){ - if (triggers[i].getHandlerFunction() == "startSync" || triggers[i].getHandlerFunction() == "install"){ + if (triggers[i].getHandlerFunction() == "startSync" || triggers[i].getHandlerFunction() == "install" || triggers[i].getHandlerFunction() == "main"){ ScriptApp.deleteTrigger(triggers[i]); } } @@ -113,13 +113,30 @@ function parseResponses(responses){ } var allEvents = component.getAllSubcomponents("vevent"); - var calName = component.getFirstPropertyValue("name"); + var calName = component.getFirstPropertyValue("x-wr-calname") || component.getFirstPropertyValue("name"); if (calName != null) allEvents.forEach(function(event){event.addPropertyWithValue("parentCal", calName); }); result = [].concat(allEvents, result); } + if (onlyFutureEvents){ + result = result.filter(function(event){ + try{ + if (event.hasProperty('recurrence-id') || event.hasProperty('rrule') || event.hasProperty('rdate') || event.hasProperty('exdate')){ + //Keep recurrences to properly filter them later on + return true; + } + var eventEnde; + eventEnde = new ICAL.Time.fromString(event.getFirstPropertyValue('dtend').toString()); + eventEnde = eventEnde.adjust(1,0,0,0);//Avoid timezone issues + return (eventEnde.compare(startUpdateTime) >= 0); + }catch(e){ + return true; + } + }); + } + result.forEach(function(event){ if(event.hasProperty('recurrence-id')){ icsEventsIds.push(event.getFirstPropertyValue('uid').toString() + "_" + event.getFirstPropertyValue('recurrence-id').toString()); @@ -150,7 +167,8 @@ function processEvent(event, calendarTz){ //------------------------ Save instance overrides ------------------------ //----------- To make sure the parent event is actually created ----------- if (event.hasProperty('recurrence-id')){ - newEvent.recurringEventId = event.getFirstPropertyValue('recurrence-id').toString(); + var recID = new ICAL.Time.fromDateTimeString(event.getFirstPropertyValue('recurrence-id').toString(), event.getFirstProperty('recurrence-id')); + newEvent.recurringEventId = recID.convertToZone(ICAL.TimezoneService.get('UTC')).toString(); Logger.log("Saving event instance for later: " + newEvent.recurringEventId); newEvent.extendedProperties.private['rec-id'] = newEvent.extendedProperties.private['id'] + "_" + newEvent.recurringEventId; recurringEvents.push(newEvent); @@ -281,7 +299,7 @@ function createEvent(event, calendarTz){ newEvent.status = status; } - if (event.hasProperty('url')){ + if (event.hasProperty('url') && event.getFirstPropertyValue('url').toString() != ''){ newEvent.source = Calendar.newEventSource() newEvent.source.url = event.getFirstPropertyValue('url').toString(); } @@ -295,8 +313,8 @@ function createEvent(event, calendarTz){ else if (event.hasProperty('summary')) newEvent.summary = icalEvent.summary; - if (addOrganizerToTitle){ - var organizer = parseOrganizerName(event.toString()); + if (addOrganizerToTitle && event.hasProperty('organizer')){ + var organizer = event.getFirstProperty('organizer').getParameter('cn').toString(); if (organizer != null) newEvent.summary = organizer + ": " + newEvent.summary; } @@ -672,28 +690,6 @@ function parseAttendeeResp(veventString){ } } -/** - * Parses the provided string to find the name of the event organizer. - * Will return null if no name is found. - * - * @param {string} veventString - The string to parse - * @return {?String} The organizer's name found in the string, null if no name was found - */ -function parseOrganizerName(veventString){ - /*A regex match is necessary here because ICAL.js doesn't let us directly - * get the "CN" part of an ORGANIZER property. With something like - * ORGANIZER;CN="Sally Example":mailto:sally@example.com - * VEVENT.getFirstPropertyValue('organizer') returns "mailto:sally@example.com". - * Therefore we have to use a regex match on the VEVENT string instead - */ - - var nameMatch = RegExp("organizer(?:;|:)cn=(.*?):", "gi").exec(veventString); - if (nameMatch != null && nameMatch.length > 1) - return nameMatch[1]; - else - return null; -} - /** * Parses the provided string to find the notification time of an event. * Will return 0 by default. @@ -773,7 +769,7 @@ function checkForUpdate(){ var alreadyAlerted = PropertiesService.getScriptProperties().getProperty("alertedForNewVersion"); if (alreadyAlerted == null){ try{ - var thisVersion = 5.0; + var thisVersion = 5.1; var html = UrlFetchApp.fetch("https://github.com/derekantrican/GAS-ICS-Sync/releases"); var regex = RegExp("","g"); var latestRelease = regex.exec(html)[0]; @@ -790,4 +786,4 @@ function checkForUpdate(){ } catch(e){} } -} \ No newline at end of file +}