@@ -49,10 +49,13 @@ function eventsFromIcal(calendar) {
4949 return { events, groupName } ;
5050}
5151
52- function date ( value , field , url ) {
53- const match = value ?. match ( / ^ ( \d { 4 } ) ( \d { 2 } ) ( \d { 2 } ) / ) ;
54- if ( ! match ) throw new Error ( `Meetup event ${ url } has no valid ${ field } .` ) ;
55- return `${ match [ 1 ] } -${ match [ 2 ] } -${ match [ 3 ] } ` ;
52+ function eventTime ( value , field , url ) {
53+ if ( typeof value !== 'string' ) throw new Error ( `Meetup event ${ url } has no valid ${ field } .` ) ;
54+ if ( / ^ \d { 4 } - \d { 2 } - \d { 2 } $ / . test ( value ) ) return value ;
55+
56+ const time = new Date ( value ) ;
57+ if ( Number . isNaN ( time . valueOf ( ) ) ) throw new Error ( `Meetup event ${ url } has no valid ${ field } .` ) ;
58+ return time . toISOString ( ) ;
5659}
5760
5861function eventId ( event , url ) {
@@ -104,12 +107,16 @@ function eventSchema(html, url) {
104107 throw new Error ( `Meetup event page has no Event structured data: ${ url } ` ) ;
105108}
106109
107- function eventMetadata ( event ) {
110+ export function eventMetadata ( event , url ) {
108111 const virtual = / (?: O n l i n e | M i x e d ) E v e n t A t t e n d a n c e M o d e $ / . test ( event . eventAttendanceMode ?? '' ) ;
109112 const locations = Array . isArray ( event . location ) ? event . location : [ event . location ] . filter ( Boolean ) ;
110113 const place = locations . find ( ( { '@type' : type } ) => type === 'Place' ) ;
114+ const times = {
115+ startDate : eventTime ( event . startDate , 'start date' , url ) ,
116+ endDate : event . endDate ? eventTime ( event . endDate , 'end date' , url ) : undefined ,
117+ } ;
111118
112- if ( ! place ) return { virtual, where : virtual ? 'Online' : '' } ;
119+ if ( ! place ) return { ... times , virtual, where : virtual ? 'Online' : '' } ;
113120
114121 const address = place . address ;
115122 const addressParts = typeof address === 'string'
@@ -119,19 +126,17 @@ function eventMetadata(event) {
119126 ( parts , part ) => parts . some ( ( existing ) => existing . toLowerCase ( ) . includes ( part . toLowerCase ( ) ) ) ? parts : [ ...parts , part ] ,
120127 [ ] ,
121128 ) . join ( ', ' ) ;
122- return { virtual, where } ;
129+ return { ... times , virtual, where } ;
123130}
124131
125132function eventFile ( event , metadata , groupName ) {
126133 const url = event . URL ;
127134 if ( ! url ) throw new Error ( 'Meetup calendar event has no URL.' ) ;
128135
129- const startDate = date ( event . DTSTART , 'start date' , url ) ;
130- const endDate = event . DTEND ? date ( event . DTEND , 'end date' , url ) : undefined ;
131- const endDateField = endDate && endDate !== startDate ? `endDate: ${ yaml ( endDate ) } \n` : '' ;
136+ const endDateField = metadata . endDate ? `endDate: ${ yaml ( metadata . endDate ) } \n` : '' ;
132137 const description = unescapeIcal ( event . DESCRIPTION ) . trim ( ) ;
133138
134- return `---\nmeetupEventId: ${ yaml ( eventId ( event , url ) ) } \nmeetupSource: meetup\nstartDate: ${ yaml ( startDate ) } \n${ endDateField } title: ${ yaml ( unescapeIcal ( event . SUMMARY ) ) } \nexternalUrl: ${ yaml ( url ) } \nvirtual: ${ metadata . virtual } \nwhere: ${ yaml ( metadata . where || groupName ) } \n---\n${ description } \n` ;
139+ return `---\nmeetupEventId: ${ yaml ( eventId ( event , url ) ) } \nmeetupSource: meetup\nstartDate: ${ yaml ( metadata . startDate ) } \n${ endDateField } title: ${ yaml ( unescapeIcal ( event . SUMMARY ) ) } \nexternalUrl: ${ yaml ( url ) } \nvirtual: ${ metadata . virtual } \nwhere: ${ yaml ( metadata . where || groupName ) } \n---\n${ description } \n` ;
135140}
136141
137142async function groups ( ) {
@@ -167,7 +172,7 @@ async function fetchGroupEvents(urlname) {
167172
168173 const page = await fetch ( event . URL ) ;
169174 if ( ! page . ok ) throw new Error ( `Meetup event page returned ${ page . status } : ${ event . URL } ` ) ;
170- return { event, metadata : eventMetadata ( eventSchema ( await page . text ( ) , event . URL ) ) } ;
175+ return { event, metadata : eventMetadata ( eventSchema ( await page . text ( ) , event . URL ) , event . URL ) } ;
171176 } ) ) ;
172177
173178 return { events, groupName : calendar . groupName || urlname } ;
0 commit comments