diff --git a/packages/features/webhooks/lib/sendPayload.ts b/packages/features/webhooks/lib/sendPayload.ts index dc6e76f1d2..cad89ca7c9 100644 --- a/packages/features/webhooks/lib/sendPayload.ts +++ b/packages/features/webhooks/lib/sendPayload.ts @@ -3,7 +3,8 @@ import { createHmac } from "crypto"; import { compile } from "handlebars"; import { getHumanReadableLocationValue } from "@calcom/app-store/locations"; -import type { CalendarEvent } from "@calcom/types/Calendar"; +import { getUTCOffsetByTimezone } from "@calcom/lib/date-fns"; +import type { CalendarEvent, Person } from "@calcom/types/Calendar"; type ContentType = "application/json" | "application/x-www-form-urlencoded"; @@ -16,6 +17,18 @@ export type EventTypeInfo = { length?: number | null; }; +export type UTCOffset = { + utcOffset?: number | null; +}; + +export type WithUTCOffsetType = T & { + user?: Person & UTCOffset; +} & { + organizer?: Person & UTCOffset; +} & { + attendees?: (Person & UTCOffset)[]; +}; + export type WebhookDataType = CalendarEvent & EventTypeInfo & { metadata?: { [key: string]: string | number | boolean | null }; @@ -32,14 +45,34 @@ export type WebhookDataType = CalendarEvent & paymentId?: number; }; +function addUTCOffset( + data: Omit +): WithUTCOffsetType { + if (data.organizer?.timeZone) { + (data.organizer as Person & UTCOffset).utcOffset = getUTCOffsetByTimezone( + data.organizer.timeZone, + data.startTime + ); + } + + if (data?.attendees?.length) { + (data.attendees as (Person & UTCOffset)[]).forEach((attendee) => { + attendee.utcOffset = getUTCOffsetByTimezone(attendee.timeZone, data.startTime); + }); + } + + return data as WithUTCOffsetType; +} + function getZapierPayload( - data: CalendarEvent & EventTypeInfo & { status?: string; createdAt: string } + data: WithUTCOffsetType ): string { - const attendees = data.attendees.map((attendee) => { + const attendees = (data.attendees as (Person & UTCOffset)[]).map((attendee) => { return { name: attendee.name, email: attendee.email, timeZone: attendee.timeZone, + utcOffset: attendee.utcOffset, }; }); @@ -62,6 +95,7 @@ function getZapierPayload( name: data.organizer.name, email: data.organizer.email, timeZone: data.organizer.timeZone, + utcOffset: data.organizer.utcOffset, locale: data.organizer.locale, }, eventType: { @@ -109,6 +143,8 @@ const sendPayload = async ( !template || jsonParse(template) ? "application/json" : "application/x-www-form-urlencoded"; data.description = data.description || data.additionalNotes; + data = addUTCOffset(data); + let body; /* Zapier id is hardcoded in the DB, we send the raw data for this case */ diff --git a/packages/lib/date-fns/index.ts b/packages/lib/date-fns/index.ts index 947c731f18..23832b0e20 100644 --- a/packages/lib/date-fns/index.ts +++ b/packages/lib/date-fns/index.ts @@ -226,3 +226,15 @@ export const isInDST = (date: Dayjs) => { return timeZoneWithDST(timeZone) && date.utcOffset() === getUTCOffsetInDST(timeZone); }; + +/** + * Get UTC offset of given time zone + * @param timeZone Time Zone Name (Ex. America/Mazatlan) + * @param date + * @returns + */ +export function getUTCOffsetByTimezone(timeZone: string, date?: string | Date | Dayjs) { + if (!timeZone) return null; + + return dayjs(date).tz(timeZone).utcOffset(); +}