Skip to content

Commit bd797c1

Browse files
alannncbobharper208
authored andcommitted
fix: handle collective multiple host on destinationCalendar (#10967)
1 parent 500bfb4 commit bd797c1

File tree

22 files changed

+368
-216
lines changed

22 files changed

+368
-216
lines changed

apps/web/pages/api/cron/bookingReminder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
104104
});
105105

106106
const attendeesList = await Promise.all(attendeesListPromises);
107-
107+
const selectedDestinationCalendar = booking.destinationCalendar || user.destinationCalendar;
108108
const evt: CalendarEvent = {
109109
type: booking.title,
110110
title: booking.title,
@@ -127,7 +127,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
127127
attendees: attendeesList,
128128
uid: booking.uid,
129129
recurringEvent: parseRecurringEvent(booking.eventType?.recurringEvent),
130-
destinationCalendar: booking.destinationCalendar || user.destinationCalendar,
130+
destinationCalendar: selectedDestinationCalendar ? [selectedDestinationCalendar] : [],
131131
};
132132

133133
await sendOrganizerRequestReminderEmail(evt);

apps/web/playwright/webhook.e2e.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ test.describe("BOOKING_REJECTED", async () => {
246246
},
247247
],
248248
location: "[redacted/dynamic]",
249-
destinationCalendar: null,
249+
destinationCalendar: [],
250250
// hideCalendarNotes: false,
251251
requiresConfirmation: "[redacted/dynamic]",
252252
eventTypeId: "[redacted/dynamic]",

packages/app-store/googlecalendar/lib/CalendarService.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export default class GoogleCalendarService implements Calendar {
8484
};
8585
};
8686

87-
async createEvent(calEventRaw: CalendarEvent): Promise<NewCalendarEventType> {
87+
async createEvent(calEventRaw: CalendarEvent, credentialId: number): Promise<NewCalendarEventType> {
8888
const eventAttendees = calEventRaw.attendees.map(({ id: _id, ...rest }) => ({
8989
...rest,
9090
responseStatus: "accepted",
@@ -97,6 +97,10 @@ export default class GoogleCalendarService implements Calendar {
9797
responseStatus: "accepted",
9898
})) || [];
9999
return new Promise(async (resolve, reject) => {
100+
const [mainHostDestinationCalendar] =
101+
calEventRaw?.destinationCalendar && calEventRaw?.destinationCalendar.length > 0
102+
? calEventRaw.destinationCalendar
103+
: [];
100104
const myGoogleAuth = await this.auth.getToken();
101105
const payload: calendar_v3.Schema$Event = {
102106
summary: calEventRaw.title,
@@ -115,8 +119,8 @@ export default class GoogleCalendarService implements Calendar {
115119
id: String(calEventRaw.organizer.id),
116120
responseStatus: "accepted",
117121
organizer: true,
118-
email: calEventRaw.destinationCalendar?.externalId
119-
? calEventRaw.destinationCalendar.externalId
122+
email: mainHostDestinationCalendar?.externalId
123+
? mainHostDestinationCalendar.externalId
120124
: calEventRaw.organizer.email,
121125
},
122126
...eventAttendees,
@@ -138,13 +142,16 @@ export default class GoogleCalendarService implements Calendar {
138142
const calendar = google.calendar({
139143
version: "v3",
140144
});
141-
const selectedCalendar = calEventRaw.destinationCalendar?.externalId
142-
? calEventRaw.destinationCalendar.externalId
143-
: "primary";
145+
// Find in calEventRaw.destinationCalendar the one with the same credentialId
146+
147+
const selectedCalendar = calEventRaw.destinationCalendar?.find(
148+
(cal) => cal.credentialId === credentialId
149+
)?.externalId;
150+
144151
calendar.events.insert(
145152
{
146153
auth: myGoogleAuth,
147-
calendarId: selectedCalendar,
154+
calendarId: selectedCalendar || "primary",
148155
requestBody: payload,
149156
conferenceDataVersion: 1,
150157
sendUpdates: "none",
@@ -188,6 +195,8 @@ export default class GoogleCalendarService implements Calendar {
188195

189196
async updateEvent(uid: string, event: CalendarEvent, externalCalendarId: string): Promise<any> {
190197
return new Promise(async (resolve, reject) => {
198+
const [mainHostDestinationCalendar] =
199+
event?.destinationCalendar && event?.destinationCalendar.length > 0 ? event.destinationCalendar : [];
191200
const myGoogleAuth = await this.auth.getToken();
192201
const eventAttendees = event.attendees.map(({ ...rest }) => ({
193202
...rest,
@@ -216,8 +225,8 @@ export default class GoogleCalendarService implements Calendar {
216225
id: String(event.organizer.id),
217226
organizer: true,
218227
responseStatus: "accepted",
219-
email: event.destinationCalendar?.externalId
220-
? event.destinationCalendar.externalId
228+
email: mainHostDestinationCalendar?.externalId
229+
? mainHostDestinationCalendar.externalId
221230
: event.organizer.email,
222231
},
223232
...(eventAttendees as any),
@@ -244,7 +253,7 @@ export default class GoogleCalendarService implements Calendar {
244253

245254
const selectedCalendar = externalCalendarId
246255
? externalCalendarId
247-
: event.destinationCalendar?.externalId;
256+
: event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
248257

249258
calendar.events.update(
250259
{
@@ -303,7 +312,9 @@ export default class GoogleCalendarService implements Calendar {
303312
});
304313

305314
const defaultCalendarId = "primary";
306-
const calendarId = externalCalendarId ? externalCalendarId : event.destinationCalendar?.externalId;
315+
const calendarId = externalCalendarId
316+
? externalCalendarId
317+
: event.destinationCalendar?.find((cal) => cal.externalId === externalCalendarId)?.externalId;
307318

308319
calendar.events.delete(
309320
{

packages/app-store/larkcalendar/lib/CalendarService.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ export default class LarkCalendarService implements Calendar {
125125
async createEvent(event: CalendarEvent): Promise<NewCalendarEventType> {
126126
let eventId = "";
127127
let eventRespData;
128-
const calendarId = event.destinationCalendar?.externalId;
128+
const [mainHostDestinationCalendar] = event.destinationCalendar ?? [];
129+
const calendarId = mainHostDestinationCalendar?.externalId;
129130
if (!calendarId) {
130131
throw new Error("no calendar id");
131132
}
@@ -160,7 +161,8 @@ export default class LarkCalendarService implements Calendar {
160161
}
161162

162163
private createAttendees = async (event: CalendarEvent, eventId: string) => {
163-
const calendarId = event.destinationCalendar?.externalId;
164+
const [mainHostDestinationCalendar] = event.destinationCalendar ?? [];
165+
const calendarId = mainHostDestinationCalendar?.externalId;
164166
if (!calendarId) {
165167
this.log.error("no calendar id provided in createAttendees");
166168
throw new Error("no calendar id provided in createAttendees");
@@ -187,7 +189,8 @@ export default class LarkCalendarService implements Calendar {
187189
async updateEvent(uid: string, event: CalendarEvent, externalCalendarId?: string) {
188190
const eventId = uid;
189191
let eventRespData;
190-
const calendarId = externalCalendarId || event.destinationCalendar?.externalId;
192+
const [mainHostDestinationCalendar] = event.destinationCalendar ?? [];
193+
const calendarId = externalCalendarId || mainHostDestinationCalendar?.externalId;
191194
if (!calendarId) {
192195
this.log.error("no calendar id provided in updateEvent");
193196
throw new Error("no calendar id provided in updateEvent");
@@ -231,7 +234,8 @@ export default class LarkCalendarService implements Calendar {
231234
* @returns
232235
*/
233236
async deleteEvent(uid: string, event: CalendarEvent, externalCalendarId?: string) {
234-
const calendarId = externalCalendarId || event.destinationCalendar?.externalId;
237+
const [mainHostDestinationCalendar] = event.destinationCalendar ?? [];
238+
const calendarId = externalCalendarId || mainHostDestinationCalendar?.externalId;
235239
if (!calendarId) {
236240
this.log.error("no calendar id provided in deleteEvent");
237241
throw new Error("no calendar id provided in deleteEvent");

packages/app-store/office365calendar/lib/CalendarService.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,10 @@ export default class Office365CalendarService implements Calendar {
7070
}
7171

7272
async createEvent(event: CalendarEvent): Promise<NewCalendarEventType> {
73+
const [mainHostDestinationCalendar] = event.destinationCalendar ?? [];
7374
try {
74-
const eventsUrl = event.destinationCalendar?.externalId
75-
? `/me/calendars/${event.destinationCalendar?.externalId}/events`
75+
const eventsUrl = mainHostDestinationCalendar?.externalId
76+
? `/me/calendars/${mainHostDestinationCalendar?.externalId}/events`
7677
: "/me/calendar/events";
7778

7879
const response = await this.fetcher(eventsUrl, {

packages/core/CalendarManager.ts

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,8 @@ export const getBusyCalendarTimes = async (
217217

218218
export const createEvent = async (
219219
credential: CredentialWithAppName,
220-
calEvent: CalendarEvent
220+
calEvent: CalendarEvent,
221+
externalId?: string
221222
): Promise<EventResult<NewCalendarEventType>> => {
222223
const uid: string = getUid(calEvent);
223224
const calendar = await getCalendar(credential);
@@ -226,29 +227,31 @@ export const createEvent = async (
226227

227228
// Check if the disabledNotes flag is set to true
228229
if (calEvent.hideCalendarNotes) {
229-
calEvent.additionalNotes = "Notes have been hidden by the organiser"; // TODO: i18n this string?
230+
calEvent.additionalNotes = "Notes have been hidden by the organizer"; // TODO: i18n this string?
230231
}
231232

232233
// TODO: Surface success/error messages coming from apps to improve end user visibility
233234
const creationResult = calendar
234-
? await calendar.createEvent(calEvent).catch(async (error: { code: number; calError: string }) => {
235-
success = false;
236-
/**
237-
* There is a time when selectedCalendar externalId doesn't match witch certain credential
238-
* so google returns 404.
239-
* */
240-
if (error?.code === 404) {
235+
? await calendar
236+
.createEvent(calEvent, credential.id)
237+
.catch(async (error: { code: number; calError: string }) => {
238+
success = false;
239+
/**
240+
* There is a time when selectedCalendar externalId doesn't match witch certain credential
241+
* so google returns 404.
242+
* */
243+
if (error?.code === 404) {
244+
return undefined;
245+
}
246+
if (error?.calError) {
247+
calError = error.calError;
248+
}
249+
log.error("createEvent failed", JSON.stringify(error), calEvent);
250+
// @TODO: This code will be off till we can investigate an error with it
251+
//https://github.com/calcom/cal.com/issues/3949
252+
// await sendBrokenIntegrationEmail(calEvent, "calendar");
241253
return undefined;
242-
}
243-
if (error?.calError) {
244-
calError = error.calError;
245-
}
246-
log.error("createEvent failed", JSON.stringify(error), calEvent);
247-
// @TODO: This code will be off till we can investigate an error with it
248-
//https://github.com/calcom/cal.com/issues/3949
249-
// await sendBrokenIntegrationEmail(calEvent, "calendar");
250-
return undefined;
251-
})
254+
})
252255
: undefined;
253256

254257
return {
@@ -261,6 +264,8 @@ export const createEvent = async (
261264
originalEvent: calEvent,
262265
calError,
263266
calWarnings: creationResult?.additionalInfo?.calWarnings || [],
267+
externalId,
268+
credentialId: credential.id,
264269
};
265270
};
266271

0 commit comments

Comments
 (0)