Refactor calendar to use new sync statuses and stages (#6141)

- Refactor calendar modules and some messaging modules to better
organize them by business rules and decouple them
- Work toward a common architecture for the different calendar providers
by introducing interfaces for the drivers
- Modify cron job to use the new sync statuses and stages
This commit is contained in:
bosiraphael
2024-07-08 17:01:06 +02:00
committed by GitHub
parent 1c3ea9b106
commit f458322303
69 changed files with 1300 additions and 884 deletions

View File

@ -0,0 +1,40 @@
import { filterOutBlocklistedEvents } from 'src/modules/calendar/calendar-event-import-manager/utils/filter-out-blocklisted-events.util';
import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
import { CalendarEventWithParticipants } from 'src/modules/calendar/common/types/calendar-event';
export const filterEventsAndReturnCancelledEvents = (
calendarChannel: Pick<CalendarChannelWorkspaceEntity, 'handle'>,
events: CalendarEventWithParticipants[],
blocklist: string[],
): {
filteredEvents: CalendarEventWithParticipants[];
cancelledEvents: CalendarEventWithParticipants[];
} => {
const filteredEvents = filterOutBlocklistedEvents(
calendarChannel.handle,
events,
blocklist,
);
return filteredEvents.reduce(
(
acc: {
filteredEvents: CalendarEventWithParticipants[];
cancelledEvents: CalendarEventWithParticipants[];
},
event,
) => {
if (event.status === 'cancelled') {
acc.cancelledEvents.push(event);
} else {
acc.filteredEvents.push(event);
}
return acc;
},
{
filteredEvents: [],
cancelledEvents: [],
},
);
};

View File

@ -1,20 +1,19 @@
import { calendar_v3 as calendarV3 } from 'googleapis';
import { isEmailBlocklisted } from 'src/modules/calendar-messaging-participant/utils/is-email-blocklisted.util';
import { isEmailBlocklisted } from 'src/modules/calendar-messaging-participant-manager/utils/is-email-blocklisted.util';
import { CalendarEventWithParticipants } from 'src/modules/calendar/common/types/calendar-event';
export const filterOutBlocklistedEvents = (
calendarChannelHandle: string,
events: calendarV3.Schema$Event[],
events: CalendarEventWithParticipants[],
blocklist: string[],
) => {
return events.filter((event) => {
if (!event.attendees) {
if (!event.participants) {
return true;
}
return event.attendees.every(
return event.participants.every(
(attendee) =>
!isEmailBlocklisted(calendarChannelHandle, attendee.email, blocklist),
!isEmailBlocklisted(calendarChannelHandle, attendee.handle, blocklist),
);
});
};

View File

@ -1,55 +0,0 @@
import { calendar_v3 as calendarV3 } from 'googleapis';
import { v4 } from 'uuid';
import { CalendarEventWithParticipants } from 'src/modules/calendar/common/types/calendar-event';
import { CalendarEventParticipantResponseStatus } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
export const formatGoogleCalendarEvent = (
event: calendarV3.Schema$Event,
iCalUIDCalendarEventIdMap: Map<string, string>,
): CalendarEventWithParticipants => {
const id =
(event.iCalUID && iCalUIDCalendarEventIdMap.get(event.iCalUID)) ?? v4();
const formatResponseStatus = (status: string | null | undefined) => {
switch (status) {
case 'accepted':
return CalendarEventParticipantResponseStatus.ACCEPTED;
case 'declined':
return CalendarEventParticipantResponseStatus.DECLINED;
case 'tentative':
return CalendarEventParticipantResponseStatus.TENTATIVE;
default:
return CalendarEventParticipantResponseStatus.NEEDS_ACTION;
}
};
return {
id,
title: event.summary ?? '',
isCanceled: event.status === 'cancelled',
isFullDay: event.start?.dateTime == null,
startsAt: event.start?.dateTime ?? event.start?.date ?? null,
endsAt: event.end?.dateTime ?? event.end?.date ?? null,
externalId: event.id ?? '',
externalCreatedAt: event.created ?? null,
externalUpdatedAt: event.updated ?? null,
description: event.description ?? '',
location: event.location ?? '',
iCalUID: event.iCalUID ?? '',
conferenceSolution:
event.conferenceData?.conferenceSolution?.key?.type ?? '',
conferenceLinkLabel: event.conferenceData?.entryPoints?.[0]?.uri ?? '',
conferenceLinkUrl: event.conferenceData?.entryPoints?.[0]?.uri ?? '',
recurringEventExternalId: event.recurringEventId ?? '',
participants:
event.attendees?.map((attendee) => ({
calendarEventId: id,
iCalUID: event.iCalUID ?? '',
handle: attendee.email ?? '',
displayName: attendee.displayName ?? '',
isOrganizer: attendee.organizer === true,
responseStatus: formatResponseStatus(attendee.responseStatus),
})) ?? [],
};
};

View File

@ -0,0 +1,31 @@
import { v4 } from 'uuid';
import {
CalendarEventWithParticipants,
CalendarEventWithParticipantsAndCalendarEventId,
} from 'src/modules/calendar/common/types/calendar-event';
export const injectIdsInCalendarEvents = (
calendarEvents: CalendarEventWithParticipants[],
iCalUIDCalendarEventIdMap: Map<string, string>,
): CalendarEventWithParticipantsAndCalendarEventId[] => {
return calendarEvents.map((calendarEvent) => {
const id = iCalUIDCalendarEventIdMap.get(calendarEvent.iCalUID) ?? v4();
return injectIdInCalendarEvent(calendarEvent, id);
});
};
const injectIdInCalendarEvent = (
calendarEvent: CalendarEventWithParticipants,
id: string,
): CalendarEventWithParticipantsAndCalendarEventId => {
return {
...calendarEvent,
id,
participants: calendarEvent.participants.map((participant) => ({
...participant,
calendarEventId: id,
})),
};
};