2
0

♻️ Add whatsapp api endpoints with waituntil

This commit is contained in:
Baptiste Arnaud
2024-04-16 14:25:56 +02:00
parent 87f5d8515a
commit faa8d42b04
4 changed files with 122 additions and 0 deletions

View File

@ -6,6 +6,7 @@ import { isNotDefined } from '@typebot.io/lib'
import { TRPCError } from '@trpc/server'
import { env } from '@typebot.io/env'
// TODO: Delete file, replaced by /api/v1/whatsapp/preview/webhook.ts
export const receiveMessagePreview = publicProcedure
.meta({
openapi: {

View 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,
},
})
}

View File

@ -4,6 +4,7 @@ import { z } from 'zod'
import { isNotDefined } from '@typebot.io/lib'
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
.meta({
openapi: {

View File

@ -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,
},
})
}