hotfix: zoom location on emails (#1153)
* fix: zoom location on emails * test: fix Co-authored-by: Peer Richelsen <peeroke@gmail.com>
This commit is contained in:
parent
43fa4f6497
commit
559ccb8ca7
5 changed files with 80 additions and 58 deletions
|
@ -642,6 +642,15 @@ const createEvent = async (
|
|||
})
|
||||
: undefined;
|
||||
|
||||
if (!creationResult) {
|
||||
return {
|
||||
type: credential.type,
|
||||
success,
|
||||
uid,
|
||||
originalEvent: calEvent,
|
||||
};
|
||||
}
|
||||
|
||||
const metadata: AdditionInformation = {};
|
||||
if (creationResult) {
|
||||
// TODO: Handle created event metadata more elegantly
|
||||
|
@ -650,10 +659,10 @@ const createEvent = async (
|
|||
metadata.entryPoints = creationResult.entryPoints;
|
||||
}
|
||||
|
||||
const emailEvent = { ...calEvent, additionInformation: metadata };
|
||||
calEvent.additionInformation = metadata;
|
||||
|
||||
if (!noMail) {
|
||||
const organizerMail = new EventOrganizerMail(emailEvent);
|
||||
const organizerMail = new EventOrganizerMail(calEvent);
|
||||
|
||||
try {
|
||||
await organizerMail.sendEmail();
|
||||
|
@ -674,27 +683,37 @@ const createEvent = async (
|
|||
const updateEvent = async (
|
||||
credential: Credential,
|
||||
calEvent: CalendarEvent,
|
||||
noMail: boolean | null = false
|
||||
noMail: boolean | null = false,
|
||||
bookingRefUid: string | null
|
||||
): Promise<EventResult> => {
|
||||
const parser: CalEventParser = new CalEventParser(calEvent);
|
||||
const newUid: string = parser.getUid();
|
||||
const uid = parser.getUid();
|
||||
const richEvent: CalendarEvent = parser.asRichEventPlain();
|
||||
|
||||
let success = true;
|
||||
|
||||
const updateResult =
|
||||
credential && calEvent.uid
|
||||
const updatedResult =
|
||||
credential && bookingRefUid
|
||||
? await calendars([credential])[0]
|
||||
.updateEvent(calEvent.uid, richEvent)
|
||||
.updateEvent(bookingRefUid, richEvent)
|
||||
.catch((e) => {
|
||||
log.error("updateEvent failed", e, calEvent);
|
||||
success = false;
|
||||
return undefined;
|
||||
})
|
||||
: null;
|
||||
|
||||
if (!updatedResult) {
|
||||
return {
|
||||
type: credential.type,
|
||||
success,
|
||||
uid,
|
||||
originalEvent: calEvent,
|
||||
};
|
||||
}
|
||||
|
||||
if (!noMail) {
|
||||
const emailEvent = { ...calEvent, uid: newUid };
|
||||
const organizerMail = new EventOrganizerRescheduledMail(emailEvent);
|
||||
const organizerMail = new EventOrganizerRescheduledMail(calEvent);
|
||||
try {
|
||||
await organizerMail.sendEmail();
|
||||
} catch (e) {
|
||||
|
@ -705,8 +724,8 @@ const updateEvent = async (
|
|||
return {
|
||||
type: credential.type,
|
||||
success,
|
||||
uid: newUid,
|
||||
updatedEvent: updateResult,
|
||||
uid,
|
||||
updatedEvent: updatedResult,
|
||||
originalEvent: calEvent,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -79,7 +79,7 @@ export default class EventManager {
|
|||
* @param event
|
||||
*/
|
||||
public async create(event: Ensure<CalendarEvent, "language">): Promise<CreateUpdateResult> {
|
||||
let evt = EventManager.processLocation(event);
|
||||
const evt = EventManager.processLocation(event);
|
||||
const isDedicated = evt.location ? EventManager.isDedicatedIntegration(evt.location) : null;
|
||||
|
||||
// First, create all calendar events. If this is a dedicated integration event, don't send a mail right here.
|
||||
|
@ -88,7 +88,7 @@ export default class EventManager {
|
|||
if (isDedicated) {
|
||||
const result = await this.createVideoEvent(evt);
|
||||
if (result.videoCallData) {
|
||||
evt = { ...evt, videoCallData: result.videoCallData };
|
||||
evt.videoCallData = result.videoCallData;
|
||||
}
|
||||
results.push(result);
|
||||
} else {
|
||||
|
@ -126,17 +126,20 @@ export default class EventManager {
|
|||
*
|
||||
* @param event
|
||||
*/
|
||||
public async update(event: Ensure<CalendarEvent, "uid">): Promise<CreateUpdateResult> {
|
||||
let evt = EventManager.processLocation(event);
|
||||
public async update(
|
||||
event: Ensure<CalendarEvent, "language">,
|
||||
rescheduleUid: string
|
||||
): Promise<CreateUpdateResult> {
|
||||
const evt = EventManager.processLocation(event);
|
||||
|
||||
if (!evt.uid) {
|
||||
throw new Error("You called eventManager.update without an `uid`. This should never happen.");
|
||||
if (!rescheduleUid) {
|
||||
throw new Error("You called eventManager.update without an `rescheduleUid`. This should never happen.");
|
||||
}
|
||||
|
||||
// Get details of existing booking.
|
||||
const booking = await prisma.booking.findFirst({
|
||||
where: {
|
||||
uid: evt.uid,
|
||||
uid: rescheduleUid,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
|
@ -164,7 +167,7 @@ export default class EventManager {
|
|||
if (isDedicated) {
|
||||
const result = await this.updateVideoEvent(evt, booking);
|
||||
if (result.videoCallData) {
|
||||
evt = { ...evt, videoCallData: result.videoCallData };
|
||||
evt.videoCallData = result.videoCallData;
|
||||
}
|
||||
results.push(result);
|
||||
} else {
|
||||
|
@ -182,15 +185,11 @@ export default class EventManager {
|
|||
},
|
||||
});
|
||||
|
||||
let bookingDeletes = null;
|
||||
|
||||
if (evt.uid) {
|
||||
bookingDeletes = prisma.booking.delete({
|
||||
const bookingDeletes = prisma.booking.delete({
|
||||
where: {
|
||||
uid: evt.uid,
|
||||
id: booking.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Wait for all deletions to be applied.
|
||||
await Promise.all([bookingReferenceDeletes, attendeeDeletes, bookingDeletes]);
|
||||
|
@ -275,8 +274,7 @@ export default class EventManager {
|
|||
const bookingRefUid = booking
|
||||
? booking.references.filter((ref) => ref.type === credential.type)[0]?.uid
|
||||
: null;
|
||||
const evt = { ...event, uid: bookingRefUid };
|
||||
return updateEvent(credential, evt, noMail);
|
||||
return updateEvent(credential, event, noMail, bookingRefUid);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -292,10 +290,10 @@ export default class EventManager {
|
|||
|
||||
if (credential) {
|
||||
const bookingRef = booking ? booking.references.filter((ref) => ref.type === credential.type)[0] : null;
|
||||
const evt = { ...event, uid: bookingRef?.uid };
|
||||
return updateMeeting(credential, evt).then((returnVal: EventResult) => {
|
||||
const bookingRefUid = bookingRef ? bookingRef.uid : null;
|
||||
return updateMeeting(credential, event, bookingRefUid).then((returnVal: EventResult) => {
|
||||
// Some video integrations, such as Zoom, don't return any data about the booking when updating it.
|
||||
if (returnVal.videoCallData == undefined) {
|
||||
if (returnVal.videoCallData === undefined) {
|
||||
returnVal.videoCallData = EventManager.bookingReferenceToVideoCallData(bookingRef);
|
||||
}
|
||||
return returnVal;
|
||||
|
@ -441,15 +439,16 @@ export default class EventManager {
|
|||
metadata.conferenceData = results[0].createdEvent?.conferenceData;
|
||||
metadata.entryPoints = results[0].createdEvent?.entryPoints;
|
||||
}
|
||||
const emailEvent = { ...event, additionInformation: metadata };
|
||||
|
||||
event.additionInformation = metadata;
|
||||
|
||||
let attendeeMail;
|
||||
switch (type) {
|
||||
case "reschedule":
|
||||
attendeeMail = new EventAttendeeRescheduledMail(emailEvent);
|
||||
attendeeMail = new EventAttendeeRescheduledMail(event);
|
||||
break;
|
||||
case "new":
|
||||
attendeeMail = new EventAttendeeMail(emailEvent);
|
||||
attendeeMail = new EventAttendeeMail(event);
|
||||
break;
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -116,10 +116,11 @@ const createMeeting = async (
|
|||
entryPoints: [entryPoint],
|
||||
};
|
||||
|
||||
const emailEvent = { ...calEvent, uid, additionInformation, videoCallData };
|
||||
calEvent.additionInformation = additionInformation;
|
||||
calEvent.videoCallData = videoCallData;
|
||||
|
||||
try {
|
||||
const organizerMail = new VideoEventOrganizerMail(emailEvent);
|
||||
const organizerMail = new VideoEventOrganizerMail(calEvent);
|
||||
await organizerMail.sendEmail();
|
||||
} catch (e) {
|
||||
console.error("organizerMail.sendEmail failed", e);
|
||||
|
@ -127,7 +128,7 @@ const createMeeting = async (
|
|||
|
||||
if (!createdMeeting || !createdMeeting.disableConfirmationEmail) {
|
||||
try {
|
||||
const attendeeMail = new VideoEventAttendeeMail(emailEvent);
|
||||
const attendeeMail = new VideoEventAttendeeMail(calEvent);
|
||||
await attendeeMail.sendEmail();
|
||||
} catch (e) {
|
||||
console.error("attendeeMail.sendEmail failed", e);
|
||||
|
@ -144,8 +145,12 @@ const createMeeting = async (
|
|||
};
|
||||
};
|
||||
|
||||
const updateMeeting = async (credential: Credential, calEvent: CalendarEvent): Promise<EventResult> => {
|
||||
const newUid: string = translator.fromUUID(uuidv5(JSON.stringify(calEvent), uuidv5.URL));
|
||||
const updateMeeting = async (
|
||||
credential: Credential,
|
||||
calEvent: CalendarEvent,
|
||||
bookingRefUid: string | null
|
||||
): Promise<EventResult> => {
|
||||
const uid: string = translator.fromUUID(uuidv5(JSON.stringify(calEvent), uuidv5.URL));
|
||||
|
||||
if (!credential) {
|
||||
throw new Error(
|
||||
|
@ -153,31 +158,29 @@ const updateMeeting = async (credential: Credential, calEvent: CalendarEvent): P
|
|||
);
|
||||
}
|
||||
|
||||
if (!calEvent.uid) {
|
||||
throw new Error("You can't update an meeting without it's UID.");
|
||||
}
|
||||
|
||||
let success = true;
|
||||
|
||||
const [firstVideoAdapter] = getVideoAdapters([credential]);
|
||||
const updatedMeeting = await firstVideoAdapter.updateMeeting(calEvent.uid, calEvent).catch((e) => {
|
||||
const updatedMeeting =
|
||||
credential && bookingRefUid
|
||||
? await firstVideoAdapter.updateMeeting(bookingRefUid, calEvent).catch((e) => {
|
||||
log.error("updateMeeting failed", e, calEvent);
|
||||
success = false;
|
||||
});
|
||||
return undefined;
|
||||
})
|
||||
: undefined;
|
||||
|
||||
if (!updatedMeeting) {
|
||||
return {
|
||||
type: credential.type,
|
||||
success,
|
||||
uid: calEvent.uid,
|
||||
uid,
|
||||
originalEvent: calEvent,
|
||||
};
|
||||
}
|
||||
|
||||
const emailEvent = { ...calEvent, uid: newUid };
|
||||
|
||||
try {
|
||||
const organizerMail = new EventOrganizerRescheduledMail(emailEvent);
|
||||
const organizerMail = new EventOrganizerRescheduledMail(calEvent);
|
||||
await organizerMail.sendEmail();
|
||||
} catch (e) {
|
||||
console.error("organizerMail.sendEmail failed", e);
|
||||
|
@ -185,7 +188,7 @@ const updateMeeting = async (credential: Credential, calEvent: CalendarEvent): P
|
|||
|
||||
if (!updatedMeeting.disableConfirmationEmail) {
|
||||
try {
|
||||
const attendeeMail = new EventAttendeeRescheduledMail(emailEvent);
|
||||
const attendeeMail = new EventAttendeeRescheduledMail(calEvent);
|
||||
await attendeeMail.sendEmail();
|
||||
} catch (e) {
|
||||
console.error("attendeeMail.sendEmail failed", e);
|
||||
|
@ -195,7 +198,7 @@ const updateMeeting = async (credential: Credential, calEvent: CalendarEvent): P
|
|||
return {
|
||||
type: credential.type,
|
||||
success,
|
||||
uid: newUid,
|
||||
uid,
|
||||
updatedEvent: updatedMeeting,
|
||||
originalEvent: calEvent,
|
||||
};
|
||||
|
|
|
@ -439,8 +439,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||
|
||||
if (rescheduleUid) {
|
||||
// Use EventManager to conditionally use all needed integrations.
|
||||
const eventManagerCalendarEvent = { ...evt, uid: rescheduleUid };
|
||||
const updateResults = await eventManager.update(eventManagerCalendarEvent);
|
||||
const updateResults = await eventManager.update(evt, rescheduleUid);
|
||||
|
||||
results = updateResults.results;
|
||||
referencesToCreate = updateResults.referencesToCreate;
|
||||
|
@ -473,7 +472,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||
}
|
||||
|
||||
if (eventType.requiresConfirmation && !rescheduleUid) {
|
||||
await new EventOrganizerRequestMail({ ...evt, uid }).sendEmail();
|
||||
await new EventOrganizerRequestMail(evt).sendEmail();
|
||||
}
|
||||
|
||||
if (typeof eventType.price === "number" && eventType.price > 0) {
|
||||
|
|
|
@ -67,6 +67,7 @@ describe("webhooks", () => {
|
|||
}
|
||||
body.payload.organizer.timeZone = dynamic;
|
||||
body.payload.uid = dynamic;
|
||||
body.payload.additionInformation = dynamic;
|
||||
|
||||
// if we change the shape of our webhooks, we can simply update this by clicking `u`
|
||||
// console.log("BODY", body);
|
||||
|
@ -74,6 +75,7 @@ describe("webhooks", () => {
|
|||
Object {
|
||||
"createdAt": "[redacted/dynamic]",
|
||||
"payload": Object {
|
||||
"additionInformation": "[redacted/dynamic]",
|
||||
"attendees": Array [
|
||||
Object {
|
||||
"email": "test@example.com",
|
||||
|
|
Loading…
Reference in a new issue