👷 Add vercel function to benefit from waitUntil method for WA webhook
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -39,3 +39,5 @@ snapshots
|
|||||||
|
|
||||||
.env
|
.env
|
||||||
.typebot-build
|
.typebot-build
|
||||||
|
.vercel
|
||||||
|
.env*.local
|
||||||
|
|||||||
41
apps/builder/api/v1/whatsapp/preview/webhook.ts
Normal file
41
apps/builder/api/v1/whatsapp/preview/webhook.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
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 type { RequestContext } from '@vercel/edge'
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: Request, context: RequestContext) {
|
||||||
|
if (!env.WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID)
|
||||||
|
return new Response(
|
||||||
|
'WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID is not defined',
|
||||||
|
{
|
||||||
|
status: 500,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const body = await request.json()
|
||||||
|
const { entry } = whatsAppWebhookRequestBodySchema.parse(body)
|
||||||
|
context.waitUntil(processWhatsAppReply(entry))
|
||||||
|
return new Response('Message is being processed.', { status: 200 })
|
||||||
|
}
|
||||||
@@ -67,9 +67,9 @@
|
|||||||
"framer-motion": "10.3.0",
|
"framer-motion": "10.3.0",
|
||||||
"google-auth-library": "8.9.0",
|
"google-auth-library": "8.9.0",
|
||||||
"google-spreadsheet": "4.1.1",
|
"google-spreadsheet": "4.1.1",
|
||||||
"ky": "1.2.3",
|
|
||||||
"immer": "10.0.2",
|
"immer": "10.0.2",
|
||||||
"jsonwebtoken": "9.0.1",
|
"jsonwebtoken": "9.0.1",
|
||||||
|
"ky": "1.2.3",
|
||||||
"libphonenumber-js": "1.10.37",
|
"libphonenumber-js": "1.10.37",
|
||||||
"micro": "10.0.1",
|
"micro": "10.0.1",
|
||||||
"micro-cors": "0.1.1",
|
"micro-cors": "0.1.1",
|
||||||
@@ -122,6 +122,7 @@
|
|||||||
"@types/qs": "6.9.7",
|
"@types/qs": "6.9.7",
|
||||||
"@types/react": "18.2.15",
|
"@types/react": "18.2.15",
|
||||||
"@types/tinycolor2": "1.4.3",
|
"@types/tinycolor2": "1.4.3",
|
||||||
|
"@vercel/edge": "1.1.1",
|
||||||
"dotenv-cli": "7.2.1",
|
"dotenv-cli": "7.2.1",
|
||||||
"eslint": "8.44.0",
|
"eslint": "8.44.0",
|
||||||
"eslint-config-custom": "workspace:*",
|
"eslint-config-custom": "workspace:*",
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
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 type { RequestContext } from '@vercel/edge'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
entry: WhatsAppWebhookRequestBody['entry']
|
||||||
|
workspaceId: string
|
||||||
|
credentialsId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(request: Request, context: RequestContext) {
|
||||||
|
const workspaceId = request.url.match(/\/workspaces\/([^/]+)\//)?.[1]
|
||||||
|
const credentialsId = request.url.match(/\/whatsapp\/([^/]+)\//)?.[1]
|
||||||
|
if (!workspaceId || !credentialsId) {
|
||||||
|
console.error('No workspace or credentials id found')
|
||||||
|
return { message: 'No workspace or credentials id found' }
|
||||||
|
}
|
||||||
|
const body = await request.json()
|
||||||
|
const { entry } = whatsAppWebhookRequestBodySchema.parse(body)
|
||||||
|
context.waitUntil(processWhatsAppReply({ entry, workspaceId, credentialsId }))
|
||||||
|
return new Response('Message is being processed.', { status: 200 })
|
||||||
|
}
|
||||||
@@ -37,7 +37,6 @@
|
|||||||
"stripe": "12.13.0"
|
"stripe": "12.13.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"dotenv": "16.4.5",
|
|
||||||
"@faire/mjml-react": "3.3.0",
|
"@faire/mjml-react": "3.3.0",
|
||||||
"@paralleldrive/cuid2": "2.2.1",
|
"@paralleldrive/cuid2": "2.2.1",
|
||||||
"@playwright/test": "1.36.0",
|
"@playwright/test": "1.36.0",
|
||||||
@@ -46,6 +45,8 @@
|
|||||||
"@typebot.io/forge": "workspace:*",
|
"@typebot.io/forge": "workspace:*",
|
||||||
"@typebot.io/forge-repository": "workspace:*",
|
"@typebot.io/forge-repository": "workspace:*",
|
||||||
"@typebot.io/lib": "workspace:*",
|
"@typebot.io/lib": "workspace:*",
|
||||||
|
"@typebot.io/playwright": "workspace:*",
|
||||||
|
"@typebot.io/results": "workspace:*",
|
||||||
"@typebot.io/schemas": "workspace:*",
|
"@typebot.io/schemas": "workspace:*",
|
||||||
"@typebot.io/tsconfig": "workspace:*",
|
"@typebot.io/tsconfig": "workspace:*",
|
||||||
"@typebot.io/variables": "workspace:*",
|
"@typebot.io/variables": "workspace:*",
|
||||||
@@ -55,6 +56,8 @@
|
|||||||
"@types/papaparse": "5.3.7",
|
"@types/papaparse": "5.3.7",
|
||||||
"@types/qs": "6.9.7",
|
"@types/qs": "6.9.7",
|
||||||
"@types/react": "18.2.15",
|
"@types/react": "18.2.15",
|
||||||
|
"@vercel/edge": "1.1.1",
|
||||||
|
"dotenv": "16.4.5",
|
||||||
"dotenv-cli": "7.2.1",
|
"dotenv-cli": "7.2.1",
|
||||||
"eslint": "8.44.0",
|
"eslint": "8.44.0",
|
||||||
"eslint-config-custom": "workspace:*",
|
"eslint-config-custom": "workspace:*",
|
||||||
@@ -63,8 +66,6 @@
|
|||||||
"papaparse": "5.4.1",
|
"papaparse": "5.4.1",
|
||||||
"superjson": "1.12.4",
|
"superjson": "1.12.4",
|
||||||
"typescript": "5.3.2",
|
"typescript": "5.3.2",
|
||||||
"zod": "3.22.4",
|
"zod": "3.22.4"
|
||||||
"@typebot.io/playwright": "workspace:*",
|
|
||||||
"@typebot.io/results": "workspace:*"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -351,6 +351,9 @@ importers:
|
|||||||
'@types/tinycolor2':
|
'@types/tinycolor2':
|
||||||
specifier: 1.4.3
|
specifier: 1.4.3
|
||||||
version: 1.4.3
|
version: 1.4.3
|
||||||
|
'@vercel/edge':
|
||||||
|
specifier: 1.1.1
|
||||||
|
version: 1.1.1
|
||||||
dotenv-cli:
|
dotenv-cli:
|
||||||
specifier: 7.2.1
|
specifier: 7.2.1
|
||||||
version: 7.2.1
|
version: 7.2.1
|
||||||
@@ -678,6 +681,9 @@ importers:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: 18.2.15
|
specifier: 18.2.15
|
||||||
version: 18.2.15
|
version: 18.2.15
|
||||||
|
'@vercel/edge':
|
||||||
|
specifier: 1.1.1
|
||||||
|
version: 1.1.1
|
||||||
dotenv:
|
dotenv:
|
||||||
specifier: 16.4.5
|
specifier: 16.4.5
|
||||||
version: 16.4.5
|
version: 16.4.5
|
||||||
@@ -10670,6 +10676,10 @@ packages:
|
|||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@vercel/edge@1.1.1:
|
||||||
|
resolution: {integrity: sha512-NtKiIbn9Cq6HWGy+qRudz28mz5nxfOJWls5Pnckjw1yCfSX8rhXdvY/il3Sy3Zd5n/sKCM2h7VSCCpJF/oaDrQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@vitejs/plugin-react@3.1.0(vite@4.5.2):
|
/@vitejs/plugin-react@3.1.0(vite@4.5.2):
|
||||||
resolution: {integrity: sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==}
|
resolution: {integrity: sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==}
|
||||||
engines: {node: ^14.18.0 || >=16.0.0}
|
engines: {node: ^14.18.0 || >=16.0.0}
|
||||||
|
|||||||
Reference in New Issue
Block a user