"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var IntegrationsWebhookController_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.IntegrationsWebhookController = void 0; const common_1 = require("@nestjs/common"); const config_1 = require("@nestjs/config"); const prisma_service_1 = require("../prisma/prisma.service"); const crypto = __importStar(require("crypto")); const webhook_idempotency_service_1 = require("./webhook-idempotency.service"); const self_hosted_clients_service_1 = require("./clients/self-hosted-clients.service"); const chatwoot_sync_service_1 = require("../support/chatwoot-sync.service"); const events_gateway_1 = require("../websocket/events.gateway"); function timingSafeCompare(provided, expected) { if (!provided || !expected) return false; const bufProvided = Buffer.from(provided); const bufExpected = Buffer.from(expected); if (bufProvided.length !== bufExpected.length) return false; return crypto.timingSafeEqual(bufProvided, bufExpected); } function verifyRawBodyHmac(rawBody, signature, secret, timestamp, allowSha1 = false) { if (!rawBody || !signature || !secret) return false; const provided = signature.replace(/^sha256=/i, "").replace(/^sha1=/i, ""); const messages = [rawBody]; if (timestamp) { messages.push(Buffer.from(`${timestamp}.${rawBody.toString("utf8")}`, "utf8")); } const candidates = []; for (const msg of messages) { candidates.push(crypto.createHmac("sha256", secret).update(msg).digest("hex")); if (allowSha1) { candidates.push(crypto.createHmac("sha1", secret).update(msg).digest("hex")); } } return candidates.some((expected) => timingSafeCompare(provided, expected)); } function verifyStandardWebhooksSignature(rawBody, signatureHeader, idHeader, timestampHeader, secret) { if (!rawBody || !signatureHeader || !idHeader || !timestampHeader || !secret) { return false; } const nowSec = Math.floor(Date.now() / 1000); const ts = Number(timestampHeader); if (!Number.isFinite(ts) || Math.abs(nowSec - ts) > 300) return false; let secretBytes; const stripped = secret.replace(/^whsec_/i, ""); try { const decoded = Buffer.from(stripped, "base64"); if (decoded.toString("base64").replace(/=+$/, "") === stripped.replace(/=+$/, "")) { secretBytes = decoded; } else { secretBytes = Buffer.from(secret, "utf8"); } } catch { secretBytes = Buffer.from(secret, "utf8"); } const signedContent = `${idHeader}.${timestampHeader}.${rawBody.toString("utf8")}`; const expected = crypto .createHmac("sha256", secretBytes) .update(signedContent) .digest("base64"); return signatureHeader.split(/\s+/).some((entry) => { const [version, sig] = entry.split(",", 2); if (version !== "v1" || !sig) return false; return timingSafeCompare(sig, expected); }); } let IntegrationsWebhookController = IntegrationsWebhookController_1 = class IntegrationsWebhookController { configService; prisma; idempotency; selfHostedClients; chatwootSync; eventsGateway; logger = new common_1.Logger(IntegrationsWebhookController_1.name); constructor(configService, prisma, idempotency, selfHostedClients, chatwootSync, eventsGateway) { this.configService = configService; this.prisma = prisma; this.idempotency = idempotency; this.selfHostedClients = selfHostedClients; this.chatwootSync = chatwootSync; this.eventsGateway = eventsGateway; } requireSecret(envName, configured) { if (!configured && process.env.NODE_ENV === "production") { this.logger.error(`${envName} is not configured — rejecting webhook`); throw new common_1.UnauthorizedException(`${envName} is not configured`); } } async checkIdempotency(provider, body) { const eventKey = this.idempotency.generateEventKey(provider, body); const isDuplicate = await this.idempotency.checkAndMark(eventKey); if (isDuplicate) { this.logger.warn(`Duplicate webhook ignored: ${provider}:${eventKey}`); } return isDuplicate; } verifyLiveKitJwt(authorization, apiKey, apiSecret, rawBody) { if (!authorization?.startsWith("Bearer ")) return false; const token = authorization.slice("Bearer ".length).trim(); const parts = token.split("."); if (parts.length !== 3) return false; const [headerB64, payloadB64, signatureB64] = parts; try { const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString("utf8")); if (payload.iss !== apiKey) return false; const nowSec = Math.floor(Date.now() / 1000); if (typeof payload.exp === "number" && payload.exp < nowSec) return false; if (typeof payload.nbf === "number" && payload.nbf > nowSec + 60) return false; const signingInput = `${headerB64}.${payloadB64}`; const expected = crypto .createHmac("sha256", apiSecret) .update(signingInput) .digest("base64url"); if (!timingSafeCompare(expected, signatureB64)) return false; if (typeof payload.sha256 !== "string") return false; if (rawBody === undefined) { return process.env.NODE_ENV !== "production"; } const bodyBuf = typeof rawBody === "string" ? Buffer.from(rawBody, "utf8") : rawBody; const bodyHash = crypto .createHash("sha256") .update(bodyBuf) .digest("base64"); return timingSafeCompare(payload.sha256, bodyHash); } catch { return false; } } async handleCalComWebhook(body, secret) { const expected = this.configService.get("CALCOM_WEBHOOK_SECRET", ""); this.requireSecret("CALCOM_WEBHOOK_SECRET", expected); if (expected && !timingSafeCompare(secret, expected)) { throw new common_1.UnauthorizedException("Invalid Cal.com webhook secret"); } if (await this.checkIdempotency("calcom", body)) { return { received: true, duplicate: true }; } const eventType = String(body?.triggerEvent || body?.event || "unknown"); const payload = (body?.payload || body); this.logger.log(`Cal.com webhook received: ${eventType}`); await this.handleCalComEvent(eventType, payload); return { received: true, event: eventType }; } async handleCalComEvent(eventType, payload) { const uid = String(payload?.uid || payload?.bookingId || ""); if (!uid) return; const booking = await this.prisma.booking.findFirst({ where: { OR: [{ calendarEventId: uid }, { meetLink: { contains: uid } }] }, include: { episode: { include: { podcast: { select: { workspaceId: true }, }, }, }, }, }); if (!booking) { this.logger.warn(`No booking found for Cal.com UID: ${uid}`); return; } switch (eventType) { case "BOOKING_CREATED": case "BOOKING_CONFIRMED": await this.prisma.booking.update({ where: { id: booking.id }, data: { isConfirmed: true, updatedAt: new Date() }, }); this.logger.log(`Booking ${booking.id} confirmed via Cal.com`); if (booking.episode?.podcast?.workspaceId) { this.eventsGateway.notifyCalComBookingCreated(booking.episode.podcast.workspaceId, { id: booking.id, isConfirmed: true }); } break; case "BOOKING_CANCELLED": case "BOOKING_REJECTED": await this.prisma.booking.update({ where: { id: booking.id }, data: { isConfirmed: false, updatedAt: new Date() }, }); this.logger.log(`Booking ${booking.id} cancelled via Cal.com`); if (booking.episode?.podcast?.workspaceId) { this.eventsGateway.notifyCalComBookingCancelled(booking.episode.podcast.workspaceId, booking.id); } break; case "BOOKING_RESCHEDULED": const newStart = String(payload?.startTime || payload?.rescheduledStartTime || ""); const newEnd = String(payload?.endTime || payload?.rescheduledEndTime || ""); if (newStart && newEnd) { await this.prisma.booking.update({ where: { id: booking.id }, data: { startTime: new Date(newStart), endTime: new Date(newEnd), updatedAt: new Date(), }, }); this.logger.log(`Booking ${booking.id} rescheduled to ${newStart}`); if (booking.episode?.podcast?.workspaceId) { this.eventsGateway.notifyCalComBookingRescheduled(booking.episode.podcast.workspaceId, booking.id); } } break; case "BOOKING_NO_SHOW": this.logger.log(`Booking ${booking.id} no-show (no status field available)`); break; case "BOOKING_ATTENDEE_ADDED": case "BOOKING_ATTENDEE_REMOVED": this.logger.log(`Attendee change for booking ${booking.id}: ${eventType}`); break; default: this.logger.debug(`Unhandled Cal.com event type: ${eventType}`); } } async handleChatwootWebhook(accountId, req, body, signature, timestamp) { const expected = this.configService.get("CHATWOOT_WEBHOOK_SECRET", ""); this.requireSecret("CHATWOOT_WEBHOOK_SECRET", expected); if (expected && !verifyRawBodyHmac(req.rawBody, signature, expected, timestamp, true)) { throw new common_1.UnauthorizedException("Invalid Chatwoot webhook signature"); } if (await this.checkIdempotency("chatwoot", body)) { return { received: true, duplicate: true }; } const event = body?.event || "unknown"; this.logger.log(`Chatwoot webhook: ${event} for account ${accountId}`); await this.handleChatwootEvent(event, body, accountId); return { received: true, event, accountId }; } async handleChatwootEvent(event, body, accountId) { switch (event) { case "message_created": if (body?.message_type === "incoming" && body?.content) { const conversationId = body?.conversation?.id; const contactId = body?.conversation?.contact_inbox?.contact_id; const messageId = body?.message?.id; this.logger.log(`Incoming Chatwoot message in conversation ${conversationId} from contact ${contactId}`); if (contactId) { await this.syncChatwootContact(contactId, accountId); } if (conversationId && messageId && body.content) { await this.chatwootSync.syncIncomingMessage(accountId, conversationId, messageId, body.content, "incoming"); } } break; case "conversation_created": this.logger.log(`New Chatwoot conversation: ${body?.conversation?.id}`); break; case "conversation_status_changed": { const newStatus = body?.conversation?.status; const conversationId = body?.conversation?.id; this.logger.log(`Conversation ${conversationId} status changed to ${newStatus}`); if (conversationId && newStatus) { await this.chatwootSync.syncConversationStatus(accountId, conversationId, newStatus); } break; } case "conversation_assigned": { const conversationId = body?.conversation?.id; const assigneeId = body?.conversation?.assignee?.id; this.logger.log(`Conversation ${conversationId} assigned to ${assigneeId}`); if (conversationId) { await this.chatwootSync.syncConversationAssignment(accountId, conversationId, assigneeId); } break; } case "contact_created": case "contact_updated": const contactId = body?.contact?.id; if (contactId) { await this.syncChatwootContact(contactId, accountId); } break; default: this.logger.debug(`Unhandled Chatwoot event: ${event}`); } } async syncChatwootContact(contactId, accountId) { try { const integration = await this.prisma.workspaceIntegration.findFirst({ where: { provider: "chatwoot", status: "connected", metadata: { path: ["accountId"], equals: accountId }, }, }); if (!integration) { this.logger.warn(`No workspace integration found for Chatwoot account ${accountId}`); return; } const apiKey = integration.accessToken; if (!apiKey) { this.logger.warn(`No API key found for Chatwoot integration ${integration.id}`); return; } const contact = await this.selfHostedClients.getChatwootContact(apiKey, contactId); if (!contact?.email) { this.logger.warn(`Chatwoot contact ${contactId} has no email, skipping sync`); return; } const workspace = await this.prisma.workspace.findUnique({ where: { id: integration.workspaceId }, include: { podcasts: { take: 1 } }, }); const podcastId = workspace?.podcasts?.[0]?.id; if (!podcastId) { this.logger.warn(`No podcast found for workspace ${integration.workspaceId}, cannot create guest`); return; } const existingGuest = await this.prisma.guest.findFirst({ where: { podcastId, email: contact.email }, }); if (existingGuest) { const currentCustomFields = existingGuest.customFields || {}; await this.prisma.guest.update({ where: { id: existingGuest.id }, data: { fullName: contact.name || existingGuest.fullName, lastContactAt: new Date(), customFields: { ...currentCustomFields, chatwootContactId: contactId, chatwootAccountId: accountId, chatwootPhone: contact.phone_number, chatwootCustomAttributes: contact.custom_attributes, }, }, }); this.logger.log(`Updated guest ${existingGuest.id} from Chatwoot contact ${contactId}`); } else { await this.prisma.guest.create({ data: { podcastId, email: contact.email, fullName: contact.name || contact.email.split("@")[0], status: "prospect", customFields: { chatwootContactId: contactId, chatwootAccountId: accountId, chatwootPhone: contact.phone_number, chatwootCustomAttributes: contact.custom_attributes, source: "chatwoot", }, }, }); this.logger.log(`Created guest from Chatwoot contact ${contactId} (${contact.email})`); } } catch (error) { const message = error instanceof Error ? error.message : String(error); this.logger.error(`Failed to sync Chatwoot contact ${contactId}: ${message}`); } } async handleDocumensoWebhook(body, secret) { const expected = this.configService.get("DOCUMENSO_WEBHOOK_SECRET", ""); this.requireSecret("DOCUMENSO_WEBHOOK_SECRET", expected); if (expected && !timingSafeCompare(secret, expected)) { throw new common_1.UnauthorizedException("Invalid Documenso webhook secret"); } if (await this.checkIdempotency("documenso", body)) { return { received: true, duplicate: true }; } const event = body?.event || "unknown"; const documentId = body?.documentId || body?.data?.id; this.logger.log(`Documenso webhook: ${event} docId=${documentId ?? ""}`); if (documentId && (event === "document_completed" || event === "document_declined")) { this.logger.log(`Document ${documentId} status: ${event}`); } return { received: true, event, documentId }; } async handleFormbricksWebhook(req, body, signature, webhookId, webhookTimestamp) { const expected = this.configService.get("FORMBRICKS_WEBHOOK_SECRET", ""); this.requireSecret("FORMBRICKS_WEBHOOK_SECRET", expected); if (expected && !verifyStandardWebhooksSignature(req.rawBody, signature, webhookId, webhookTimestamp, expected)) { throw new common_1.UnauthorizedException("Invalid Formbricks webhook signature"); } if (await this.checkIdempotency("formbricks", body)) { return { received: true, duplicate: true }; } const event = body?.event || body?.type || "unknown"; const surveyId = body?.surveyId || body?.data?.surveyId; const responseId = body?.responseId || body?.data?.id; this.logger.log(`Formbricks webhook: ${event} surveyId=${surveyId ?? ""} responseId=${responseId ?? ""}`); if (body?.data?.userId) { const guest = await this.prisma.guest.findFirst({ where: { id: body.data.userId }, }); if (guest) { await this.prisma.guestJourneyEvent.create({ data: { guestId: guest.id, eventType: "follow_up", title: "Completed Survey", details: `Completed survey ${surveyId || ""}`, metadata: JSON.parse(JSON.stringify(body?.data || {})), }, }); this.logger.log(`Recorded survey completion journey event for guest ${guest.id}`); } } return { received: true, event, surveyId, responseId }; } async handleListmonkWebhook(body, secret) { const expected = this.configService.get("LISTMONK_WEBHOOK_SECRET", ""); this.requireSecret("LISTMONK_WEBHOOK_SECRET", expected); if (expected && !timingSafeCompare(secret, expected)) { throw new common_1.UnauthorizedException("Invalid Listmonk webhook secret"); } if (await this.checkIdempotency("listmonk", body)) { return { received: true, duplicate: true }; } const event = body?.event || "unknown"; const subscriberId = body?.data?.subscriber?.id || body?.subscriber_id; this.logger.log(`Listmonk webhook: ${event} subscriberId=${subscriberId ?? ""}`); await this.handleListmonkEvent(event, body); return { received: true, event, subscriberId }; } async handleListmonkEvent(event, body) { const subscriber = body?.data?.subscriber || body?.subscriber; if (!subscriber) return; const email = subscriber.email; const name = subscriber.name || ""; const status = subscriber.status || "enabled"; const lists = subscriber.lists || []; switch (event) { case "subscriber.created": case "subscriber.updated": await this.syncListmonkSubscriber(subscriber); break; case "subscriber.deleted": await this.unsubscribeListmonkSubscriber(email); break; case "subscriber.subscribed": case "subscriber.unsubscribed": await this.handleListmonkSubscriptionChange(email, lists, event); break; default: this.logger.debug(`Unhandled Listmonk event: ${event}`); } } async syncListmonkSubscriber(subscriber) { const email = subscriber.email; if (!email) return; try { const guest = await this.prisma.guest.findFirst({ where: { email }, }); if (guest) { await this.prisma.guest.update({ where: { id: guest.id }, data: { customFields: { listmonkSubscriberId: subscriber.id, listmonkStatus: subscriber.status, listmonkLists: subscriber.lists || [], }, }, }); this.logger.log(`Synced Listmonk subscriber ${subscriber.id} to guest ${guest.id}`); } else { this.logger.log(`Listmonk subscriber ${email} not found in guests, would create contact`); } } catch (error) { const message = error instanceof Error ? error.message : String(error); this.logger.error(`Failed to sync Listmonk subscriber ${subscriber.id}: ${message}`); } } async unsubscribeListmonkSubscriber(email) { try { const guest = await this.prisma.guest.findFirst({ where: { email } }); if (guest) { await this.prisma.guest.update({ where: { id: guest.id }, data: { customFields: { listmonkUnsubscribedAt: new Date().toISOString(), }, }, }); this.logger.log(`Marked guest ${guest.id} as unsubscribed via Listmonk webhook`); } } catch (error) { const message = error instanceof Error ? error.message : String(error); this.logger.error(`Failed to unsubscribe guest for email ${email}: ${message}`); } } async handleListmonkSubscriptionChange(email, lists, event) { this.logger.log(`Listmonk subscription change for ${email}: ${event} on lists ${lists.map(l => l.id).join(", ")}`); } async handleLiveKitWebhook(req, body, authorization) { const apiKey = this.configService.get("LIVEKIT_API_KEY", ""); const apiSecret = this.configService.get("LIVEKIT_API_SECRET", ""); const rawBody = req.rawBody; if (process.env.NODE_ENV === "production") { if (!apiKey || !apiSecret || !this.verifyLiveKitJwt(authorization, apiKey, apiSecret, rawBody)) { throw new common_1.UnauthorizedException("Invalid LiveKit webhook authorization"); } } else if (apiKey && apiSecret && !this.verifyLiveKitJwt(authorization, apiKey, apiSecret, rawBody)) { throw new common_1.UnauthorizedException("Invalid LiveKit webhook authorization"); } else if (!apiKey || !apiSecret) { this.logger.warn("LIVEKIT_API_KEY / LIVEKIT_API_SECRET not configured — LiveKit webhook verification skipped (dev)"); } if (await this.checkIdempotency("livekit", body)) { return { received: true, duplicate: true }; } const event = String(body?.event || "unknown"); const roomName = body?.room?.name || body?.egressInfo?.roomName || String(body?.roomName || ""); this.logger.log(`LiveKit webhook: ${event} room=${roomName ?? ""}`); if (event === "room_finished" && roomName) { const episodeId = this.extractEpisodeIdFromRoom(roomName); if (episodeId) { const session = await this.prisma.recordingSession.findUnique({ where: { episodeId }, }); if (session && session.status === "active") { await this.prisma.recordingSession.update({ where: { id: session.id }, data: { status: "completed", endedAt: new Date() }, }); this.logger.log(`Marked recording session ${session.id} as completed via LiveKit webhook`); } } else { this.logger.warn(`Could not extract episode ID from room name: ${roomName}`); } } if (event === "egress_ended" || event === "egress_completed" || event === "recording.completed" || event === "recording_completed") { await this.handleLiveKitRecordingFinished(body); } if (event === "participant_joined" || event === "participant_left") { const participant = body?.participant; this.logger.log(`Participant ${participant?.identity} ${event} in room ${roomName}`); } return { received: true, event, roomName }; } extractEpisodeIdFromRoom(roomName) { const match = roomName.match(/^episode-(.+)$/); return match ? match[1] : null; } async handleLiveKitRecordingFinished(body) { const egressInfo = body?.recording; const roomName = egressInfo?.name || body?.room?.name; if (!roomName) { this.logger.warn("LiveKit recording/egress event missing room name"); return; } const episodeId = this.extractEpisodeIdFromRoom(roomName); if (!episodeId) { this.logger.warn(`Could not extract episode ID from room name: ${roomName}`); return; } const session = await this.prisma.recordingSession.findUnique({ where: { episodeId }, }); if (!session) { this.logger.warn(`No recording session found for episode ${episodeId}`); return; } if (session.status === "completed" || session.status === "processing") { this.logger.log(`Session ${session.id} already ${session.status}, skipping`); return; } await this.prisma.recordingSession.update({ where: { id: session.id }, data: { status: "processing", endedAt: new Date() }, }); this.logger.log(`Session ${session.id} marked as processing after LiveKit recording finished (${egressInfo?.status ?? "unknown"})`); } }; exports.IntegrationsWebhookController = IntegrationsWebhookController; __decorate([ (0, common_1.Post)("calcom"), (0, common_1.HttpCode)(common_1.HttpStatus.OK), __param(0, (0, common_1.Body)()), __param(1, (0, common_1.Headers)("x-cal-secret-key")), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, String]), __metadata("design:returntype", Promise) ], IntegrationsWebhookController.prototype, "handleCalComWebhook", null); __decorate([ (0, common_1.Post)("chatwoot/:accountId"), (0, common_1.HttpCode)(common_1.HttpStatus.OK), __param(0, (0, common_1.Param)("accountId")), __param(1, (0, common_1.Req)()), __param(2, (0, common_1.Body)()), __param(3, (0, common_1.Headers)("x-chatwoot-signature")), __param(4, (0, common_1.Headers)("x-chatwoot-timestamp")), __metadata("design:type", Function), __metadata("design:paramtypes", [String, Object, Object, String, String]), __metadata("design:returntype", Promise) ], IntegrationsWebhookController.prototype, "handleChatwootWebhook", null); __decorate([ (0, common_1.Post)("documenso"), (0, common_1.HttpCode)(common_1.HttpStatus.OK), __param(0, (0, common_1.Body)()), __param(1, (0, common_1.Headers)("x-documenso-secret")), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, String]), __metadata("design:returntype", Promise) ], IntegrationsWebhookController.prototype, "handleDocumensoWebhook", null); __decorate([ (0, common_1.Post)("formbricks"), (0, common_1.HttpCode)(common_1.HttpStatus.OK), __param(0, (0, common_1.Req)()), __param(1, (0, common_1.Body)()), __param(2, (0, common_1.Headers)("webhook-signature")), __param(3, (0, common_1.Headers)("webhook-id")), __param(4, (0, common_1.Headers)("webhook-timestamp")), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object, String, String, String]), __metadata("design:returntype", Promise) ], IntegrationsWebhookController.prototype, "handleFormbricksWebhook", null); __decorate([ (0, common_1.Post)("listmonk"), (0, common_1.HttpCode)(common_1.HttpStatus.OK), __param(0, (0, common_1.Body)()), __param(1, (0, common_1.Headers)("x-listmonk-secret")), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, String]), __metadata("design:returntype", Promise) ], IntegrationsWebhookController.prototype, "handleListmonkWebhook", null); __decorate([ (0, common_1.Post)("livekit"), (0, common_1.HttpCode)(common_1.HttpStatus.OK), __param(0, (0, common_1.Req)()), __param(1, (0, common_1.Body)()), __param(2, (0, common_1.Headers)("authorization")), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object, String]), __metadata("design:returntype", Promise) ], IntegrationsWebhookController.prototype, "handleLiveKitWebhook", null); exports.IntegrationsWebhookController = IntegrationsWebhookController = IntegrationsWebhookController_1 = __decorate([ (0, common_1.Controller)("integrations/webhooks"), __metadata("design:paramtypes", [config_1.ConfigService, prisma_service_1.PrismaService, webhook_idempotency_service_1.WebhookIdempotencyService, self_hosted_clients_service_1.SelfHostedClientsService, chatwoot_sync_service_1.ChatwootSyncService, events_gateway_1.EventsGateway]) ], IntegrationsWebhookController); //# sourceMappingURL=integrations-webhook.controller.js.map