2
0

🐛 (chat) Make sure objects are deeply parsed with variables value

This commit is contained in:
Baptiste Arnaud
2022-12-24 10:42:38 +01:00
parent 449080b0ad
commit 431ad7c78c
5 changed files with 42 additions and 56 deletions

View File

@@ -1,5 +1,5 @@
import { ExecuteIntegrationResponse } from '@/features/chat' import { ExecuteIntegrationResponse } from '@/features/chat'
import { parseVariablesInObject } from '@/features/variables' import { deepParseVariable } from '@/features/variables'
import { GoogleAnalyticsBlock, SessionState } from 'models' import { GoogleAnalyticsBlock, SessionState } from 'models'
export const executeGoogleAnalyticsBlock = ( export const executeGoogleAnalyticsBlock = (
@@ -8,6 +8,6 @@ export const executeGoogleAnalyticsBlock = (
): ExecuteIntegrationResponse => ({ ): ExecuteIntegrationResponse => ({
outgoingEdgeId: block.outgoingEdgeId, outgoingEdgeId: block.outgoingEdgeId,
integrations: { integrations: {
googleAnalytics: parseVariablesInObject(block.options, variables), googleAnalytics: deepParseVariable(variables)(block.options),
}, },
}) })

View File

@@ -1,10 +1,14 @@
import { checkChatsUsage } from '@/features/usage' import { checkChatsUsage } from '@/features/usage'
import { parsePrefilledVariables } from '@/features/variables' import {
parsePrefilledVariables,
deepParseVariable,
} from '@/features/variables'
import prisma from '@/lib/prisma' import prisma from '@/lib/prisma'
import { publicProcedure } from '@/utils/server/trpc' import { publicProcedure } from '@/utils/server/trpc'
import { TRPCError } from '@trpc/server' import { TRPCError } from '@trpc/server'
import { Prisma } from 'db' import { Prisma } from 'db'
import { import {
ChatReply,
chatReplySchema, chatReplySchema,
ChatSession, ChatSession,
PublicTypebot, PublicTypebot,
@@ -192,13 +196,13 @@ const startSession = async (startParams?: StartParams) => {
resultId: result?.id, resultId: result?.id,
sessionId: session.id, sessionId: session.id,
typebot: { typebot: {
theme: typebot.theme, settings: deepParseVariable(typebot.variables)(typebot.settings),
settings: typebot.settings, theme: deepParseVariable(typebot.variables)(typebot.theme),
}, },
messages, messages,
input, input,
logic, logic,
} } satisfies ChatReply
} }
const getResult = async ({ const getResult = async ({

View File

@@ -1,8 +1,5 @@
import { parseVariables } from '@/features/variables' import { deepParseVariable } from '@/features/variables'
import { import {
BubbleBlock,
BubbleBlockType,
ChatMessage,
ChatReply, ChatReply,
Group, Group,
InputBlock, InputBlock,
@@ -38,20 +35,22 @@ export const executeGroup =
nextEdgeId = block.outgoingEdgeId nextEdgeId = block.outgoingEdgeId
if (isBubbleBlock(block)) { if (isBubbleBlock(block)) {
messages.push(parseBubbleBlockContent(newSessionState)(block)) messages.push(
deepParseVariable(newSessionState.typebot.variables)(block)
)
continue continue
} }
if (isInputBlock(block)) if (isInputBlock(block))
return { return {
messages, messages,
input: { input: deepParseVariable(newSessionState.typebot.variables)({
...block, ...block,
runtimeOptions: await computeRuntimeOptions(newSessionState)(block), runtimeOptions: await computeRuntimeOptions(newSessionState)(block),
prefilledValue: getPrefilledInputValue( prefilledValue: getPrefilledInputValue(
newSessionState.typebot.variables newSessionState.typebot.variables
)(block), )(block),
}, }),
newSessionState: { newSessionState: {
...newSessionState, ...newSessionState,
currentBlock: { currentBlock: {
@@ -102,34 +101,6 @@ const computeRuntimeOptions =
} }
} }
const parseBubbleBlockContent =
({ typebot: { variables } }: SessionState) =>
(block: BubbleBlock): ChatMessage => {
switch (block.type) {
case BubbleBlockType.TEXT: {
const plainText = parseVariables(variables)(block.content.plainText)
const html = parseVariables(variables)(block.content.html)
return { type: block.type, content: { plainText, html } }
}
case BubbleBlockType.IMAGE: {
const url = parseVariables(variables)(block.content.url)
return { type: block.type, content: { ...block.content, url } }
}
case BubbleBlockType.VIDEO: {
const url = parseVariables(variables)(block.content.url)
return { type: block.type, content: { ...block.content, url } }
}
case BubbleBlockType.AUDIO: {
const url = parseVariables(variables)(block.content.url)
return { type: block.type, content: { ...block.content, url } }
}
case BubbleBlockType.EMBED: {
const url = parseVariables(variables)(block.content.url)
return { type: block.type, content: { ...block.content, url } }
}
}
}
const getPrefilledInputValue = const getPrefilledInputValue =
(variables: SessionState['typebot']['variables']) => (block: InputBlock) => { (variables: SessionState['typebot']['variables']) => (block: InputBlock) => {
return ( return (

View File

@@ -86,20 +86,31 @@ const jsonParse = (str: string) =>
.replace(/"/g, `\\"`) .replace(/"/g, `\\"`)
.replace(/\\[^n"]/g, `\\\\ `) .replace(/\\[^n"]/g, `\\\\ `)
export const parseVariablesInObject = ( export const deepParseVariable =
object: { [key: string]: string | number }, (variables: Variable[]) =>
variables: Variable[] <T extends Record<string, unknown>>(object: T): T =>
) => Object.keys(object).reduce<T>((newObj, key) => {
Object.keys(object).reduce((newObj, key) => {
const currentValue = object[key] const currentValue = object[key]
if (typeof currentValue === 'string')
return { ...newObj, [key]: parseVariables(variables)(currentValue) }
if (currentValue instanceof Object && currentValue.constructor === Object)
return { return {
...newObj, ...newObj,
[key]: [key]: deepParseVariable(variables)(
typeof currentValue === 'string' currentValue as Record<string, unknown>
? parseVariables(variables)(currentValue) ),
: currentValue,
} }
}, {})
if (currentValue instanceof Array)
return {
...newObj,
[key]: currentValue.map(deepParseVariable(variables)),
}
return { ...newObj, [key]: currentValue }
}, {} as T)
export const parsePrefilledVariables = ( export const parsePrefilledVariables = (
variables: Typebot['variables'], variables: Typebot['variables'],

View File

@@ -61,7 +61,7 @@ export const ChoiceForm = (props: Props) => {
> >
{item.content} {item.content}
</button> </button>
{props.inputIndex === 0 && ( {props.inputIndex === 0 && props.block.items.length === 1 && (
<span class="flex h-3 w-3 absolute top-0 right-0 -mt-1 -mr-1 ping"> <span class="flex h-3 w-3 absolute top-0 right-0 -mt-1 -mr-1 ping">
<span class="animate-ping absolute inline-flex h-full w-full rounded-full brightness-225 opacity-75" /> <span class="animate-ping absolute inline-flex h-full w-full rounded-full brightness-225 opacity-75" />
<span class="relative inline-flex rounded-full h-3 w-3 brightness-200" /> <span class="relative inline-flex rounded-full h-3 w-3 brightness-200" />