2
0

(whatsapp) Improve whatsApp management and media collection

Closes #796
This commit is contained in:
Baptiste Arnaud
2023-09-22 11:08:41 +02:00
parent 8f4e5b5d63
commit 9e0109f561
22 changed files with 505 additions and 452 deletions

View File

@ -6,7 +6,6 @@ import {
import { env } from '@typebot.io/env'
import { sendChatReplyToWhatsApp } from './sendChatReplyToWhatsApp'
import { startWhatsAppSession } from './startWhatsAppSession'
import { downloadMedia } from './downloadMedia'
import { getSession } from '../queries/getSession'
import { continueBotFlow } from '../continueBotFlow'
import { decrypt } from '@typebot.io/lib/api'
@ -17,12 +16,12 @@ export const resumeWhatsAppFlow = async ({
receivedMessage,
sessionId,
workspaceId,
phoneNumberId,
credentialsId,
contact,
}: {
receivedMessage: WhatsAppIncomingMessage
sessionId: string
phoneNumberId: string
credentialsId?: string
workspaceId?: string
contact: NonNullable<SessionState['whatsApp']>['contact']
}) => {
@ -38,22 +37,14 @@ export const resumeWhatsAppFlow = async ({
const session = await getSession(sessionId)
const initialCredentials = session
? await getCredentials(phoneNumberId)(session.state)
: undefined
const isPreview = workspaceId === undefined || credentialsId === undefined
const { typebot, resultId } = session?.state.typebotsQueue[0] ?? {}
const { typebot } = session?.state.typebotsQueue[0] ?? {}
const messageContent = await getIncomingMessageContent({
message: receivedMessage,
systemUserToken: initialCredentials?.systemUserAccessToken,
downloadPath:
typebot && resultId
? `typebots/${typebot.id}/results/${resultId}`
: undefined,
typebotId: typebot?.id,
})
const isPreview = workspaceId === undefined
const sessionState =
isPreview && session?.state
? ({
@ -64,6 +55,15 @@ export const resumeWhatsAppFlow = async ({
} satisfies SessionState)
: session?.state
const credentials = await getCredentials({ credentialsId, isPreview })
if (!credentials) {
console.error('Could not find credentials')
return {
message: 'Message received',
}
}
const resumeResponse = sessionState
? await continueBotFlow(sessionState)(messageContent)
: workspaceId
@ -71,7 +71,7 @@ export const resumeWhatsAppFlow = async ({
message: receivedMessage,
sessionId,
workspaceId,
phoneNumberId,
credentials: { ...credentials, id: credentialsId as string },
contact,
})
: undefined
@ -83,17 +83,6 @@ export const resumeWhatsAppFlow = async ({
}
}
const credentials =
initialCredentials ??
(await getCredentials(phoneNumberId)(resumeResponse.newSessionState))
if (!credentials) {
console.error('Could not find credentials')
return {
message: 'Message received',
}
}
const { input, logs, newSessionState, messages, clientSideActions } =
resumeResponse
@ -127,12 +116,10 @@ export const resumeWhatsAppFlow = async ({
const getIncomingMessageContent = async ({
message,
systemUserToken,
downloadPath,
typebotId,
}: {
message: WhatsAppIncomingMessage
systemUserToken: string | undefined
downloadPath?: string
typebotId?: string
}): Promise<string | undefined> => {
switch (message.type) {
case 'text':
@ -147,46 +134,52 @@ const getIncomingMessageContent = async ({
return
case 'video':
case 'image':
if (!systemUserToken || !downloadPath) return ''
return downloadMedia({
mediaId: 'video' in message ? message.video.id : message.image.id,
systemUserToken,
downloadPath,
})
if (!typebotId) return
const mediaId = 'video' in message ? message.video.id : message.image.id
return (
env.NEXTAUTH_URL +
`/api/typebots/${typebotId}/whatsapp/media/${mediaId}`
)
}
}
const getCredentials =
(phoneNumberId: string) =>
async (
state: SessionState
): Promise<WhatsAppCredentials['data'] | undefined> => {
const isPreview = !state.typebotsQueue[0].resultId
if (isPreview) {
if (!env.META_SYSTEM_USER_TOKEN) return
return {
systemUserAccessToken: env.META_SYSTEM_USER_TOKEN,
phoneNumberId,
}
}
if (!state.whatsApp) return
const credentials = await prisma.credentials.findUnique({
where: {
id: state.whatsApp.credentialsId,
},
select: {
data: true,
iv: true,
},
})
if (!credentials) return
const data = (await decrypt(
credentials.data,
credentials.iv
)) as WhatsAppCredentials['data']
const getCredentials = async ({
credentialsId,
isPreview,
}: {
credentialsId?: string
isPreview: boolean
}): Promise<WhatsAppCredentials['data'] | undefined> => {
if (isPreview) {
if (
!env.META_SYSTEM_USER_TOKEN ||
!env.WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID
)
return
return {
systemUserAccessToken: data.systemUserAccessToken,
phoneNumberId,
systemUserAccessToken: env.META_SYSTEM_USER_TOKEN,
phoneNumberId: env.WHATSAPP_PREVIEW_FROM_PHONE_NUMBER_ID,
}
}
if (!credentialsId) return
const credentials = await prisma.credentials.findUnique({
where: {
id: credentialsId,
},
select: {
data: true,
iv: true,
},
})
if (!credentials) return
const data = (await decrypt(
credentials.data,
credentials.iv
)) as WhatsAppCredentials['data']
return {
systemUserAccessToken: data.systemUserAccessToken,
phoneNumberId: data.phoneNumberId,
}
}