♻️ Add whatsapp api endpoints with waituntil
This commit is contained in:
@ -6,6 +6,7 @@ import { isNotDefined } from '@typebot.io/lib'
|
|||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
import { env } from '@typebot.io/env'
|
import { env } from '@typebot.io/env'
|
||||||
|
|
||||||
|
// TODO: Delete file, replaced by /api/v1/whatsapp/preview/webhook.ts
|
||||||
export const receiveMessagePreview = publicProcedure
|
export const receiveMessagePreview = publicProcedure
|
||||||
.meta({
|
.meta({
|
||||||
openapi: {
|
openapi: {
|
||||||
|
49
apps/builder/src/pages/api/v1/whatsapp/preview/webhook.ts
Normal file
49
apps/builder/src/pages/api/v1/whatsapp/preview/webhook.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import {
|
||||||
|
WhatsAppWebhookRequestBody,
|
||||||
|
whatsAppWebhookRequestBodySchema,
|
||||||
|
} from '@typebot.io/schemas/features/whatsapp'
|
||||||
|
import { resumeWhatsAppFlow } from '@typebot.io/bot-engine/whatsapp/resumeWhatsAppFlow'
|
||||||
|
import { isNotDefined } from '@typebot.io/lib'
|
||||||
|
import { env } from '@typebot.io/env'
|
||||||
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
|
||||||
|
export default async function handler(
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse
|
||||||
|
) {
|
||||||
|
if (!env.WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID)
|
||||||
|
return res
|
||||||
|
.status(500)
|
||||||
|
.send('WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID is not defined')
|
||||||
|
const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body
|
||||||
|
const { entry } = whatsAppWebhookRequestBodySchema.parse(body)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
const ctx = globalThis[Symbol.for('@vercel/request-context')]
|
||||||
|
if (ctx?.get?.().waitUntil) {
|
||||||
|
ctx.get().waitUntil(() => processWhatsAppReply(entry))
|
||||||
|
return res.status(200).json({ message: 'Message is being processed.' })
|
||||||
|
}
|
||||||
|
console.log('Processing message')
|
||||||
|
const { message } = await processWhatsAppReply(entry)
|
||||||
|
return res.status(200).json({ message })
|
||||||
|
}
|
||||||
|
|
||||||
|
const processWhatsAppReply = async (
|
||||||
|
entry: WhatsAppWebhookRequestBody['entry']
|
||||||
|
) => {
|
||||||
|
const receivedMessage = entry.at(0)?.changes.at(0)?.value.messages?.at(0)
|
||||||
|
if (isNotDefined(receivedMessage)) return { message: 'No message found' }
|
||||||
|
const contactName =
|
||||||
|
entry.at(0)?.changes.at(0)?.value?.contacts?.at(0)?.profile?.name ?? ''
|
||||||
|
const contactPhoneNumber =
|
||||||
|
entry.at(0)?.changes.at(0)?.value?.messages?.at(0)?.from ?? ''
|
||||||
|
return resumeWhatsAppFlow({
|
||||||
|
receivedMessage,
|
||||||
|
sessionId: `wa-preview-${receivedMessage.from}`,
|
||||||
|
contact: {
|
||||||
|
name: contactName,
|
||||||
|
phoneNumber: contactPhoneNumber,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
@ -4,6 +4,7 @@ import { z } from 'zod'
|
|||||||
import { isNotDefined } from '@typebot.io/lib'
|
import { isNotDefined } from '@typebot.io/lib'
|
||||||
import { resumeWhatsAppFlow } from '@typebot.io/bot-engine/whatsapp/resumeWhatsAppFlow'
|
import { resumeWhatsAppFlow } from '@typebot.io/bot-engine/whatsapp/resumeWhatsAppFlow'
|
||||||
|
|
||||||
|
// TODO: Delete file, replaced by /api/v1/workspaces/[workspaceId]/whatsapp/[credentialsId]/webhook.ts
|
||||||
export const receiveMessage = publicProcedure
|
export const receiveMessage = publicProcedure
|
||||||
.meta({
|
.meta({
|
||||||
openapi: {
|
openapi: {
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
import {
|
||||||
|
WhatsAppWebhookRequestBody,
|
||||||
|
whatsAppWebhookRequestBodySchema,
|
||||||
|
} from '@typebot.io/schemas/features/whatsapp'
|
||||||
|
import { resumeWhatsAppFlow } from '@typebot.io/bot-engine/whatsapp/resumeWhatsAppFlow'
|
||||||
|
import { isNotDefined } from '@typebot.io/lib'
|
||||||
|
import { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
entry: WhatsAppWebhookRequestBody['entry']
|
||||||
|
workspaceId: string
|
||||||
|
credentialsId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
supportsResponseStreaming: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function handler(
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse
|
||||||
|
) {
|
||||||
|
const workspaceId = req.query.workspaceId as string
|
||||||
|
const credentialsId = req.query.credentialsId as string
|
||||||
|
const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body
|
||||||
|
const { entry } = whatsAppWebhookRequestBodySchema.parse(body)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
const ctx = globalThis[Symbol.for('@vercel/request-context')]
|
||||||
|
if (ctx?.get?.().waitUntil) {
|
||||||
|
ctx
|
||||||
|
.get()
|
||||||
|
.waitUntil(() =>
|
||||||
|
processWhatsAppReply({ entry, workspaceId, credentialsId })
|
||||||
|
)
|
||||||
|
return res.status(200).json({ message: 'Message is being processed.' })
|
||||||
|
}
|
||||||
|
const { message } = await processWhatsAppReply({
|
||||||
|
entry,
|
||||||
|
workspaceId,
|
||||||
|
credentialsId,
|
||||||
|
})
|
||||||
|
return res.status(200).json({ message })
|
||||||
|
}
|
||||||
|
|
||||||
|
const processWhatsAppReply = async ({
|
||||||
|
entry,
|
||||||
|
workspaceId,
|
||||||
|
credentialsId,
|
||||||
|
}: Props) => {
|
||||||
|
const receivedMessage = entry.at(0)?.changes.at(0)?.value.messages?.at(0)
|
||||||
|
if (isNotDefined(receivedMessage)) return { message: 'No message found' }
|
||||||
|
const contactName =
|
||||||
|
entry.at(0)?.changes.at(0)?.value?.contacts?.at(0)?.profile?.name ?? ''
|
||||||
|
const contactPhoneNumber =
|
||||||
|
entry.at(0)?.changes.at(0)?.value?.messages?.at(0)?.from ?? ''
|
||||||
|
const phoneNumberId = entry.at(0)?.changes.at(0)?.value
|
||||||
|
.metadata.phone_number_id
|
||||||
|
if (!phoneNumberId) return { message: 'No phone number id found' }
|
||||||
|
return resumeWhatsAppFlow({
|
||||||
|
receivedMessage,
|
||||||
|
sessionId: `wa-${phoneNumberId}-${receivedMessage.from}`,
|
||||||
|
phoneNumberId,
|
||||||
|
credentialsId,
|
||||||
|
workspaceId,
|
||||||
|
contact: {
|
||||||
|
name: contactName,
|
||||||
|
phoneNumber: contactPhoneNumber,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
Reference in New Issue
Block a user