@@ -44,7 +44,7 @@ function formatDate(date) {
4444
4545 const time = date . slice ( 11 , 16 )
4646 const timeZone = date . slice ( 19 )
47-
47+
4848 return formattedDate + " at " + time + " (UTC" + ( timeZone == "Z" ? "" : timeZone ) + ")"
4949}
5050
@@ -132,39 +132,45 @@ function fetchSourceCalendars(sourceCalendarURLs){
132132 for ( var source of sourceCalendarURLs ) {
133133 var url = source [ 0 ] . replace ( "webcal://" , "https://" ) ;
134134 var colorId = source [ 1 ] ;
135-
136- callWithBackoff ( function ( ) {
137- var urlResponse = UrlFetchApp . fetch ( url , { 'validateHttpsCertificates' : false , 'muteHttpExceptions' : true } ) ;
138- if ( urlResponse . getResponseCode ( ) == 200 ) {
139- var icsContent = urlResponse . getContentText ( )
140- const icsRegex = RegExp ( "(BEGIN:VCALENDAR.*?END:VCALENDAR)" , "s" )
141- var urlContent = icsRegex . exec ( icsContent ) ;
142- if ( urlContent == null ) {
143- // Microsoft Outlook has a bug that sometimes results in incorrectly formatted ics files. This tries to fix that problem.
144- // Add END:VEVENT for every BEGIN:VEVENT that's missing it
145- const veventRegex = / B E G I N : V E V E N T (?: (? ! E N D : V E V E N T ) .) * ?(? = .B E G I N | .E N D : V C A L E N D A R | $ ) / sg;
146- icsContent = icsContent . replace ( veventRegex , ( match ) => match + "\nEND:VEVENT" ) ;
147-
148- // Add END:VCALENDAR if missing
149- if ( ! icsContent . endsWith ( "END:VCALENDAR" ) ) {
150- icsContent += "\nEND:VCALENDAR" ;
151- }
152- urlContent = icsRegex . exec ( icsContent )
135+
136+ try {
137+ callWithBackoff ( function ( ) {
138+ var urlResponse = UrlFetchApp . fetch ( url , { 'validateHttpsCertificates' : false , 'muteHttpExceptions' : true } ) ;
139+ if ( urlResponse . getResponseCode ( ) == 200 ) {
140+ var icsContent = urlResponse . getContentText ( )
141+ const icsRegex = RegExp ( "(BEGIN:VCALENDAR.*?END:VCALENDAR)" , "s" )
142+ var urlContent = icsRegex . exec ( icsContent ) ;
153143 if ( urlContent == null ) {
154- Logger . log ( "[ERROR] Incorrect ics/ical URL: " + url )
155- return
144+ // Microsoft Outlook has a bug that sometimes results in incorrectly formatted ics files. This tries to fix that problem.
145+ // Add END:VEVENT for every BEGIN:VEVENT that's missing it
146+ const veventRegex = / B E G I N : V E V E N T (?: (? ! E N D : V E V E N T ) .) * ?(? = .B E G I N | .E N D : V C A L E N D A R | $ ) / sg;
147+ icsContent = icsContent . replace ( veventRegex , ( match ) => match + "\nEND:VEVENT" ) ;
148+
149+ // Add END:VCALENDAR if missing
150+ if ( ! icsContent . endsWith ( "END:VCALENDAR" ) ) {
151+ icsContent += "\nEND:VCALENDAR" ;
152+ }
153+ urlContent = icsRegex . exec ( icsContent )
154+ if ( urlContent == null ) {
155+ Logger . log ( "[ERROR] Incorrect ics/ical URL: " + url )
156+ reportOverallFailure = true ;
157+ return
158+ }
159+ Logger . log ( "[WARNING] Microsoft is incorrectly formatting ics/ical at: " + url )
156160 }
157- Logger . log ( "[WARNING] Microsoft is incorrectly formatting ics/ical at: " + url )
161+ result . push ( [ urlContent [ 0 ] , colorId ] ) ;
162+ return ;
158163 }
159- result . push ( [ urlContent [ 0 ] , colorId ] ) ;
160- return ;
161- }
162- else { //Throw here to make callWithBackoff run again
163- throw "Error: Encountered HTTP error " + urlResponse . getResponseCode ( ) + " when accessing " + url ;
164- }
165- } , defaultMaxRetries ) ;
164+ else { //Throw here to make callWithBackoff run again
165+ throw "Error: Encountered HTTP error " + urlResponse . getResponseCode ( ) + " when accessing " + url ;
166+ }
167+ } , defaultMaxRetries ) ;
168+ }
169+ catch ( e ) {
170+ reportOverallFailure = true ;
171+ }
166172 }
167-
173+
168174 return result ;
169175}
170176
@@ -242,7 +248,7 @@ function parseResponses(responses){
242248 } ) ;
243249 }
244250
245- //No need to process calcelled events as they will be added to gcal's trash anyway
251+ //No need to process cancelled events as they will be added to gcal's trash anyway
246252 result = result . filter ( function ( event ) {
247253 try {
248254 return ( event . getFirstPropertyValue ( 'status' ) . toString ( ) . toLowerCase ( ) != "cancelled" ) ;
@@ -436,7 +442,7 @@ function createEvent(event, calendarTz){
436442 if ( organizerMail )
437443 newEvent . organizer . email = organizerMail . toString ( ) ;
438444
439- if ( addOrganizerToTitle && organizerName ) {
445+ if ( addOrganizerToTitle && organizerName ) {
440446 newEvent . summary = organizerName + ": " + newEvent . summary ;
441447 }
442448 }
@@ -1090,7 +1096,14 @@ function sendSummary() {
10901096var backoffRecoverableErrors = [
10911097 "service invoked too many times in a short time" ,
10921098 "rate limit exceeded" ,
1093- "internal error" ] ;
1099+ "internal error" ,
1100+ "http error 403" , // forbidden
1101+ "http error 408" , // request timeout
1102+ "http error 423" , // locked
1103+ "http error 500" , // internal server error
1104+ "http error 503" , // service unavailable
1105+ "http error 504" // gateway timeout
1106+ ] ;
10941107function callWithBackoff ( func , maxRetries ) {
10951108 var tries = 0 ;
10961109 var result ;
@@ -1102,10 +1115,7 @@ function callWithBackoff(func, maxRetries) {
11021115 }
11031116 catch ( err ) {
11041117 err = err . message || err ;
1105- if ( err . includes ( "HTTP error" ) ) {
1106- Logger . log ( err ) ;
1107- return null ;
1108- } else if ( err . includes ( "is not a function" ) || ! backoffRecoverableErrors . some ( function ( e ) {
1118+ if ( err . includes ( "is not a function" ) || ! backoffRecoverableErrors . some ( function ( e ) {
11091119 return err . toLowerCase ( ) . includes ( e ) ;
11101120 } ) ) {
11111121 throw err ;
0 commit comments