2
0

🐛 Add subscription handler in api folder

This commit is contained in:
Baptiste Arnaud
2024-04-16 15:13:44 +02:00
parent faa8d42b04
commit 5a99493ced
5 changed files with 81 additions and 36 deletions

View File

@@ -15,7 +15,8 @@
"DATABASE_URL": "postgresql://postgres:typebot@127.0.0.1:5432/typebot", "DATABASE_URL": "postgresql://postgres:typebot@127.0.0.1:5432/typebot",
"NEXT_PUBLIC_VIEWER_URL": "http://localhost:3001", "NEXT_PUBLIC_VIEWER_URL": "http://localhost:3001",
"NEXTAUTH_URL": "http://localhost:3000", "NEXTAUTH_URL": "http://localhost:3000",
"ENCRYPTION_SECRET": "H+KbL/OFrqbEuDy/1zX8bsPG+spXri3S" "ENCRYPTION_SECRET": "H+KbL/OFrqbEuDy/1zX8bsPG+spXri3S",
"S3_ENDPOINT": "http://localhost:9000"
}, },
"[prisma]": { "[prisma]": {
"editor.defaultFormatter": "Prisma.prisma" "editor.defaultFormatter": "Prisma.prisma"

View File

@@ -3,6 +3,7 @@ import { TRPCError } from '@trpc/server'
import { env } from '@typebot.io/env' import { env } from '@typebot.io/env'
import { z } from 'zod' import { z } from 'zod'
// TODO: Delete in favor of /api
export const subscribePreviewWebhook = publicProcedure export const subscribePreviewWebhook = publicProcedure
.meta({ .meta({
openapi: { openapi: {

View File

@@ -6,27 +6,40 @@ import { resumeWhatsAppFlow } from '@typebot.io/bot-engine/whatsapp/resumeWhatsA
import { isNotDefined } from '@typebot.io/lib' import { isNotDefined } from '@typebot.io/lib'
import { env } from '@typebot.io/env' import { env } from '@typebot.io/env'
import { NextApiRequest, NextApiResponse } from 'next' import { NextApiRequest, NextApiResponse } from 'next'
import { methodNotAllowed } from '@typebot.io/lib/api'
export default async function handler( export default async function handler(
req: NextApiRequest, req: NextApiRequest,
res: NextApiResponse res: NextApiResponse
) { ) {
if (!env.WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID) if (req.method === 'GET') {
return res const token = req.query['hub.verify_token'] as string | undefined
.status(500) const challenge = req.query['hub.challenge'] as string | undefined
.send('WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID is not defined') if (token !== env.ENCRYPTION_SECRET)
const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body return res.status(401).json({
const { entry } = whatsAppWebhookRequestBodySchema.parse(body) error: 'Unauthorized',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment })
// @ts-ignore return Number(challenge)
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') if (req.method === 'POST') {
const { message } = await processWhatsAppReply(entry) if (!env.WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID)
return res.status(200).json({ message }) 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 })
}
return methodNotAllowed(res)
} }
const processWhatsAppReply = async ( const processWhatsAppReply = async (

View File

@@ -3,6 +3,8 @@ import prisma from '@typebot.io/lib/prisma'
import { TRPCError } from '@trpc/server' import { TRPCError } from '@trpc/server'
import { z } from 'zod' import { z } from 'zod'
// TODO: Delete in favor of /api
export const subscribeWebhook = publicProcedure export const subscribeWebhook = publicProcedure
.meta({ .meta({
openapi: { openapi: {

View File

@@ -5,6 +5,8 @@ import {
import { resumeWhatsAppFlow } from '@typebot.io/bot-engine/whatsapp/resumeWhatsAppFlow' import { resumeWhatsAppFlow } from '@typebot.io/bot-engine/whatsapp/resumeWhatsAppFlow'
import { isNotDefined } from '@typebot.io/lib' import { isNotDefined } from '@typebot.io/lib'
import { NextApiRequest, NextApiResponse } from 'next' import { NextApiRequest, NextApiResponse } from 'next'
import prisma from '@typebot.io/lib/prisma'
import { methodNotAllowed } from '@typebot.io/lib/api/utils'
type Props = { type Props = {
entry: WhatsAppWebhookRequestBody['entry'] entry: WhatsAppWebhookRequestBody['entry']
@@ -20,27 +22,53 @@ export default async function handler(
req: NextApiRequest, req: NextApiRequest,
res: NextApiResponse res: NextApiResponse
) { ) {
const workspaceId = req.query.workspaceId as string if (req.method === 'GET') {
const credentialsId = req.query.credentialsId as string const token = req.query['hub.verify_token'] as string | undefined
const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body const challenge = req.query['hub.challenge'] as string | undefined
const { entry } = whatsAppWebhookRequestBodySchema.parse(body) if (!token || !challenge)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment return res.status(400).json({
// @ts-ignore error: 'hub.verify_token and hub.challenge are required',
const ctx = globalThis[Symbol.for('@vercel/request-context')] })
if (ctx?.get?.().waitUntil) { const verificationToken = await prisma.verificationToken.findUnique({
ctx where: {
.get() token,
.waitUntil(() => },
processWhatsAppReply({ entry, workspaceId, credentialsId }) })
) if (!verificationToken)
return res.status(200).json({ message: 'Message is being processed.' }) return res.status(401).json({
error: 'Unauthorized',
})
await prisma.verificationToken.delete({
where: {
token,
},
})
return Number(challenge)
} }
const { message } = await processWhatsAppReply({ if (req.method === 'POST') {
entry, const workspaceId = req.query.workspaceId as string
workspaceId, const credentialsId = req.query.credentialsId as string
credentialsId, const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body
}) const { entry } = whatsAppWebhookRequestBodySchema.parse(body)
return res.status(200).json({ message }) // 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 })
}
return methodNotAllowed(res)
} }
const processWhatsAppReply = async ({ const processWhatsAppReply = async ({