From 2d127a5316eba26931c25664a8362719b29f0db4 Mon Sep 17 00:00:00 2001 From: Femi Odugbesan Date: Mon, 23 Aug 2021 11:15:03 -0500 Subject: [PATCH] improve speed of caldav event fetching (#501) * improve speed of caldav event fetching use forked version of tsDav * use dayjs to format timerange * apply calendar timezone to event dates --- .../CalDav/CalDavCalendarAdapter.ts | 59 ++++++++++++------- package.json | 2 +- yarn.lock | 8 +-- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/lib/integrations/CalDav/CalDavCalendarAdapter.ts b/lib/integrations/CalDav/CalDavCalendarAdapter.ts index 1e76c0bf..eeed5db8 100644 --- a/lib/integrations/CalDav/CalDavCalendarAdapter.ts +++ b/lib/integrations/CalDav/CalDavCalendarAdapter.ts @@ -15,6 +15,9 @@ import { createEvent, DurationObject, Attendee, Person } from "ics"; import dayjs from "dayjs"; import { v4 as uuidv4 } from "uuid"; import { stripHtml } from "../../emails/helpers"; +import logger from "@lib/logger"; + +const log = logger.getChildLogger({ prefix: ["[[lib] caldav"] }); type EventBusyDate = Record<"start" | "end", Date>; @@ -74,14 +77,20 @@ export class CalDavCalendar implements CalendarApiAdapter { start: this.convertDate(event.startTime), duration: this.getDuration(event.startTime, event.endTime), title: event.title, - description: stripHtml(event.description), + description: stripHtml(event.description ?? ""), location: event.location, organizer: { email: event.organizer.email, name: event.organizer.name }, attendees: this.getAttendees(event.attendees), }); if (error) { - return null; + log.debug("Error creating iCalString"); + return {}; + } + + if (!iCalString) { + log.debug("Error creating iCalString"); + return {}; } await Promise.all( @@ -107,7 +116,7 @@ export class CalDavCalendar implements CalendarApiAdapter { } } - async updateEvent(uid: string, event: CalendarEvent): Promise> { + async updateEvent(uid: string, event: CalendarEvent): Promise { try { const calendars = await this.listCalendars(); const events = []; @@ -126,19 +135,20 @@ export class CalDavCalendar implements CalendarApiAdapter { start: this.convertDate(event.startTime), duration: this.getDuration(event.startTime, event.endTime), title: event.title, - description: stripHtml(event.description), + description: stripHtml(event.description ?? ""), location: event.location, organizer: { email: event.organizer.email, name: event.organizer.name }, attendees: this.getAttendees(event.attendees), }); if (error) { - return null; + log.debug("Error creating iCalString"); + return {}; } const eventsToUpdate = events.filter((event) => event.uid === uid); - await Promise.all( + return await Promise.all( eventsToUpdate.map((event) => { return updateCalendarObject({ calendarObject: { @@ -150,8 +160,6 @@ export class CalDavCalendar implements CalendarApiAdapter { }); }) ); - - return null; } catch (reason) { console.error(reason); throw reason; @@ -184,8 +192,6 @@ export class CalDavCalendar implements CalendarApiAdapter { }); }) ); - - return null; } catch (reason) { console.error(reason); throw reason; @@ -214,7 +220,7 @@ export class CalDavCalendar implements CalendarApiAdapter { return events; } catch (reason) { - console.error(reason); + log.error(reason); throw reason; } } @@ -229,11 +235,11 @@ export class CalDavCalendar implements CalendarApiAdapter { return calendars .filter((calendar) => { - return calendar.components.includes("VEVENT"); + return calendar.components?.includes("VEVENT"); }) .map((calendar) => ({ externalId: calendar.url, - name: calendar.displayName, + name: calendar.displayName ?? "", primary: false, integration: this.integrationName, })); @@ -243,14 +249,19 @@ export class CalDavCalendar implements CalendarApiAdapter { } } - async getEvents(calId: string, dateFrom: string, dateTo: string): Promise { + async getEvents(calId: string, dateFrom: string | null, dateTo: string | null): Promise { try { - //TODO: Figure out Time range and filters - console.log(dateFrom, dateTo); const objects = await fetchCalendarObjects({ calendar: { url: calId, }, + timeRange: + dateFrom && dateTo + ? { + start: dayjs(dateFrom).utc().format("YYYY-MM-DDTHH:mm:ss[Z]"), + end: dayjs(dateTo).utc().format("YYYY-MM-DDTHH:mm:ss[Z]"), + } + : undefined, headers: this.headers, }); @@ -265,8 +276,16 @@ export class CalDavCalendar implements CalendarApiAdapter { const vevent = vcalendar.getFirstSubcomponent("vevent"); const event = new ICAL.Event(vevent); - const startDate = new Date(event.startDate.toUnixTime() * 1000); - const endDate = new Date(event.endDate.toUnixTime() * 1000); + const calendarTimezone = vcalendar.getFirstSubcomponent("vtimezone") + ? vcalendar.getFirstSubcomponent("vtimezone").getFirstPropertyValue("tzid") + : ""; + + const startDate = calendarTimezone + ? dayjs(event.startDate).tz(calendarTimezone) + : new Date(event.startDate.toUnixTime() * 1000); + const endDate = calendarTimezone + ? dayjs(event.endDate).tz(calendarTimezone) + : new Date(event.endDate.toUnixTime() * 1000); return { uid: event.uid, @@ -289,9 +308,7 @@ export class CalDavCalendar implements CalendarApiAdapter { organizer: event.organizer, attendees: event.attendees.map((a) => a.getValues()), recurrenceId: event.recurrenceId, - timezone: vcalendar.getFirstSubcomponent("vtimezone") - ? vcalendar.getFirstSubcomponent("vtimezone").getFirstPropertyValue("tzid") - : "", + timezone: calendarTimezone, }; } }) diff --git a/package.json b/package.json index 80c540a9..1523bd77 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "react-select": "^4.3.1", "react-timezone-select": "^1.0.7", "short-uuid": "^4.2.0", - "tsdav": "^1.0.3", + "tsdav": "^1.0.6", "tslog": "^3.2.1", "uuid": "^8.3.2" }, diff --git a/yarn.lock b/yarn.lock index 917a3f5e..981636a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6528,10 +6528,10 @@ ts-pnp@^1.1.6: resolved "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== -tsdav@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/tsdav/-/tsdav-1.0.3.tgz#251bfc1d6fa6c931b5a97392162f7831a954dc49" - integrity sha512-2i5YoTIwQ801VbsOgZepydg90AL5pc3RtbqkbcIW0EHah1RaS5ZDSHIzWPyLvLaFWYwwJgcXGlwrVB7DznM6qQ== +tsdav@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tsdav/-/tsdav-1.0.6.tgz#65c22fc77d6516db234c1288ff9c9fed6730fef5" + integrity sha512-xnKE39wZtyLoyW1UClYAb2Eilx6tHzbqhO2v29P1zrmwLAsKNYUHwHb+lrmJHfZZLsbbzKWRg5dPLYRuEXmMJA== dependencies: base-64 "^1.0.0" cross-fetch "^3.1.4"