166 lines
4.9 KiB
TypeScript
166 lines
4.9 KiB
TypeScript
import { authenticatedProcedure } from '@/helpers/server/trpc'
|
|
import { z } from 'zod'
|
|
import { TRPCError } from '@trpc/server'
|
|
import { startSession } from '@typebot.io/bot-engine/startSession'
|
|
import { env } from '@typebot.io/env'
|
|
import { HTTPError } from 'got'
|
|
import prisma from '@typebot.io/lib/prisma'
|
|
import { saveStateToDatabase } from '@typebot.io/bot-engine/saveStateToDatabase'
|
|
import { restartSession } from '@typebot.io/bot-engine/queries/restartSession'
|
|
import { sendChatReplyToWhatsApp } from '@typebot.io/bot-engine/whatsapp/sendChatReplyToWhatsApp'
|
|
import { sendWhatsAppMessage } from '@typebot.io/bot-engine/whatsapp/sendWhatsAppMessage'
|
|
import { isReadTypebotForbidden } from '../typebot/helpers/isReadTypebotForbidden'
|
|
import { SessionState } from '@typebot.io/schemas'
|
|
|
|
export const startWhatsAppPreview = authenticatedProcedure
|
|
.meta({
|
|
openapi: {
|
|
method: 'POST',
|
|
path: '/typebots/{typebotId}/whatsapp/start-preview',
|
|
summary: 'Start preview',
|
|
tags: ['WhatsApp'],
|
|
protect: true,
|
|
},
|
|
})
|
|
.input(
|
|
z.object({
|
|
to: z
|
|
.string()
|
|
.min(1)
|
|
.transform((value) => value.replace(/\s/g, '').replace(/\+/g, '')),
|
|
typebotId: z.string(),
|
|
startGroupId: z.string().optional(),
|
|
})
|
|
)
|
|
.output(
|
|
z.object({
|
|
message: z.string(),
|
|
})
|
|
)
|
|
.mutation(
|
|
async ({ input: { to, typebotId, startGroupId }, ctx: { user } }) => {
|
|
if (
|
|
!env.WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID ||
|
|
!env.META_SYSTEM_USER_TOKEN ||
|
|
!env.WHATSAPP_PREVIEW_TEMPLATE_NAME
|
|
)
|
|
throw new TRPCError({
|
|
code: 'BAD_REQUEST',
|
|
message:
|
|
'Missing WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID or META_SYSTEM_USER_TOKEN or WHATSAPP_PREVIEW_TEMPLATE_NAME env variables',
|
|
})
|
|
|
|
const existingTypebot = await prisma.typebot.findFirst({
|
|
where: {
|
|
id: typebotId,
|
|
},
|
|
select: {
|
|
id: true,
|
|
workspaceId: true,
|
|
collaborators: {
|
|
select: {
|
|
userId: true,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
if (
|
|
!existingTypebot?.id ||
|
|
(await isReadTypebotForbidden(existingTypebot, user))
|
|
)
|
|
throw new TRPCError({ code: 'NOT_FOUND', message: 'Typebot not found' })
|
|
|
|
const sessionId = `wa-${to}-preview`
|
|
|
|
const existingSession = await prisma.chatSession.findFirst({
|
|
where: {
|
|
id: sessionId,
|
|
},
|
|
select: {
|
|
updatedAt: true,
|
|
state: true,
|
|
},
|
|
})
|
|
|
|
// For users that did not interact with the bot in the last 24 hours, we need to send a template message.
|
|
const canSendDirectMessagesToUser =
|
|
(existingSession?.updatedAt.getTime() ?? 0) >
|
|
Date.now() - 24 * 60 * 60 * 1000
|
|
|
|
const { newSessionState, messages, input, clientSideActions, logs } =
|
|
await startSession({
|
|
startParams: {
|
|
isOnlyRegistering: !canSendDirectMessagesToUser,
|
|
typebot: typebotId,
|
|
isPreview: true,
|
|
startGroupId,
|
|
},
|
|
userId: user.id,
|
|
})
|
|
|
|
if (canSendDirectMessagesToUser) {
|
|
await sendChatReplyToWhatsApp({
|
|
to,
|
|
typingEmulation: newSessionState.typingEmulation,
|
|
messages,
|
|
input,
|
|
clientSideActions,
|
|
credentials: {
|
|
phoneNumberId: env.WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID,
|
|
systemUserAccessToken: env.META_SYSTEM_USER_TOKEN,
|
|
},
|
|
state: newSessionState,
|
|
})
|
|
await saveStateToDatabase({
|
|
clientSideActions: [],
|
|
input,
|
|
logs,
|
|
session: {
|
|
id: sessionId,
|
|
state: {
|
|
...newSessionState,
|
|
currentBlock: !input ? undefined : newSessionState.currentBlock,
|
|
},
|
|
},
|
|
})
|
|
} else {
|
|
await restartSession({
|
|
state: {
|
|
...newSessionState,
|
|
whatsApp: (existingSession?.state as SessionState | undefined)
|
|
?.whatsApp,
|
|
},
|
|
id: `wa-${to}-preview`,
|
|
})
|
|
try {
|
|
await sendWhatsAppMessage({
|
|
to,
|
|
message: {
|
|
type: 'template',
|
|
template: {
|
|
language: {
|
|
code: env.WHATSAPP_PREVIEW_TEMPLATE_LANG,
|
|
},
|
|
name: env.WHATSAPP_PREVIEW_TEMPLATE_NAME,
|
|
},
|
|
},
|
|
credentials: {
|
|
phoneNumberId: env.WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID,
|
|
systemUserAccessToken: env.META_SYSTEM_USER_TOKEN,
|
|
},
|
|
})
|
|
} catch (err) {
|
|
if (err instanceof HTTPError) console.log(err.response.body)
|
|
throw new TRPCError({
|
|
code: 'INTERNAL_SERVER_ERROR',
|
|
message: 'Request to Meta to send preview message failed',
|
|
cause: err,
|
|
})
|
|
}
|
|
}
|
|
return {
|
|
message: 'success',
|
|
}
|
|
}
|
|
)
|