⚡ (setVariable) Add "Environment name" value in Set variable block (#850)
Closes #848 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ### Summary by CodeRabbit - New Feature: Added "Environment name" as a new value type in the SetVariable function, allowing users to distinguish between 'web' and 'whatsapp' environments. - Refactor: Simplified session state handling in `resumeWhatsAppFlow.ts` for improved code clarity. - Refactor: Updated `startWhatsAppSession.ts` to include an initial session state with WhatsApp contact and expiry timeout, enhancing session management. - Bug Fix: Improved null handling in `executeSetVariable.ts` for 'Contact name' and 'Phone number', preventing potential issues with falsy values. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -62,6 +62,7 @@ const Expression = ({
|
|||||||
case 'Tomorrow':
|
case 'Tomorrow':
|
||||||
case 'User ID':
|
case 'User ID':
|
||||||
case 'Moment of the day':
|
case 'Moment of the day':
|
||||||
|
case 'Environment name':
|
||||||
case 'Yesterday': {
|
case 'Yesterday': {
|
||||||
return (
|
return (
|
||||||
<Text as="span">
|
<Text as="span">
|
||||||
|
|||||||
@@ -158,6 +158,17 @@ const SetVariableValue = ({
|
|||||||
</Alert>
|
</Alert>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
case 'Environment name': {
|
||||||
|
return (
|
||||||
|
<Alert fontSize="sm">
|
||||||
|
<AlertIcon />
|
||||||
|
<Text>
|
||||||
|
Will return either <Tag size="sm">web</Tag> or{' '}
|
||||||
|
<Tag size="sm">whatsapp</Tag>.
|
||||||
|
</Text>
|
||||||
|
</Alert>
|
||||||
|
)
|
||||||
|
}
|
||||||
case 'Contact name':
|
case 'Contact name':
|
||||||
case 'Phone number':
|
case 'Phone number':
|
||||||
case 'Random ID':
|
case 'Random ID':
|
||||||
|
|||||||
@@ -1979,6 +1979,7 @@
|
|||||||
"enum": [
|
"enum": [
|
||||||
"Custom",
|
"Custom",
|
||||||
"Empty",
|
"Empty",
|
||||||
|
"Environment name",
|
||||||
"User ID",
|
"User ID",
|
||||||
"Now",
|
"Now",
|
||||||
"Today",
|
"Today",
|
||||||
@@ -6367,6 +6368,7 @@
|
|||||||
"enum": [
|
"enum": [
|
||||||
"Custom",
|
"Custom",
|
||||||
"Empty",
|
"Empty",
|
||||||
|
"Environment name",
|
||||||
"User ID",
|
"User ID",
|
||||||
"Now",
|
"Now",
|
||||||
"Today",
|
"Today",
|
||||||
@@ -10396,6 +10398,7 @@
|
|||||||
"enum": [
|
"enum": [
|
||||||
"Custom",
|
"Custom",
|
||||||
"Empty",
|
"Empty",
|
||||||
|
"Environment name",
|
||||||
"User ID",
|
"User ID",
|
||||||
"Now",
|
"Now",
|
||||||
"Today",
|
"Today",
|
||||||
@@ -14565,6 +14568,7 @@
|
|||||||
"enum": [
|
"enum": [
|
||||||
"Custom",
|
"Custom",
|
||||||
"Empty",
|
"Empty",
|
||||||
|
"Environment name",
|
||||||
"User ID",
|
"User ID",
|
||||||
"Now",
|
"Now",
|
||||||
"Today",
|
"Today",
|
||||||
@@ -18614,6 +18618,7 @@
|
|||||||
"enum": [
|
"enum": [
|
||||||
"Custom",
|
"Custom",
|
||||||
"Empty",
|
"Empty",
|
||||||
|
"Environment name",
|
||||||
"User ID",
|
"User ID",
|
||||||
"Now",
|
"Now",
|
||||||
"Today",
|
"Today",
|
||||||
@@ -22718,6 +22723,7 @@
|
|||||||
"enum": [
|
"enum": [
|
||||||
"Custom",
|
"Custom",
|
||||||
"Empty",
|
"Empty",
|
||||||
|
"Environment name",
|
||||||
"User ID",
|
"User ID",
|
||||||
"Now",
|
"Now",
|
||||||
"Today",
|
"Today",
|
||||||
@@ -26885,6 +26891,7 @@
|
|||||||
"enum": [
|
"enum": [
|
||||||
"Custom",
|
"Custom",
|
||||||
"Empty",
|
"Empty",
|
||||||
|
"Environment name",
|
||||||
"User ID",
|
"User ID",
|
||||||
"Now",
|
"Now",
|
||||||
"Today",
|
"Today",
|
||||||
|
|||||||
@@ -1574,6 +1574,7 @@
|
|||||||
"enum": [
|
"enum": [
|
||||||
"Custom",
|
"Custom",
|
||||||
"Empty",
|
"Empty",
|
||||||
|
"Environment name",
|
||||||
"User ID",
|
"User ID",
|
||||||
"Now",
|
"Now",
|
||||||
"Today",
|
"Today",
|
||||||
|
|||||||
@@ -77,9 +77,11 @@ const getExpressionToEvaluate =
|
|||||||
(options: SetVariableBlock['options']): string | null => {
|
(options: SetVariableBlock['options']): string | null => {
|
||||||
switch (options.type) {
|
switch (options.type) {
|
||||||
case 'Contact name':
|
case 'Contact name':
|
||||||
return state.whatsApp?.contact.name ?? ''
|
return state.whatsApp?.contact.name ?? null
|
||||||
case 'Phone number':
|
case 'Phone number': {
|
||||||
return `"${state.whatsApp?.contact.phoneNumber}"` ?? ''
|
const phoneNumber = state.whatsApp?.contact.phoneNumber
|
||||||
|
return phoneNumber ? `"${state.whatsApp?.contact.phoneNumber}"` : null
|
||||||
|
}
|
||||||
case 'Now':
|
case 'Now':
|
||||||
case 'Today':
|
case 'Today':
|
||||||
return 'new Date().toISOString()'
|
return 'new Date().toISOString()'
|
||||||
@@ -112,6 +114,9 @@ const getExpressionToEvaluate =
|
|||||||
if(now.getHours() >= 18) return 'evening'
|
if(now.getHours() >= 18) return 'evening'
|
||||||
if(now.getHours() >= 22 || now.getHours() < 6) return 'night'`
|
if(now.getHours() >= 22 || now.getHours() < 6) return 'night'`
|
||||||
}
|
}
|
||||||
|
case 'Environment name': {
|
||||||
|
return state.whatsApp ? 'whatsapp' : 'web'
|
||||||
|
}
|
||||||
case 'Custom':
|
case 'Custom':
|
||||||
case undefined: {
|
case undefined: {
|
||||||
return options.expressionToEvaluate ?? null
|
return options.expressionToEvaluate ?? null
|
||||||
|
|||||||
@@ -30,11 +30,13 @@ import { injectVariablesFromExistingResult } from './variables/injectVariablesFr
|
|||||||
type Props = {
|
type Props = {
|
||||||
startParams: StartParams
|
startParams: StartParams
|
||||||
userId: string | undefined
|
userId: string | undefined
|
||||||
|
initialSessionState?: Pick<SessionState, 'whatsApp' | 'expiryTimeout'>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const startSession = async ({
|
export const startSession = async ({
|
||||||
startParams,
|
startParams,
|
||||||
userId,
|
userId,
|
||||||
|
initialSessionState,
|
||||||
}: Props): Promise<ChatReply & { newSessionState: SessionState }> => {
|
}: Props): Promise<ChatReply & { newSessionState: SessionState }> => {
|
||||||
if (!startParams)
|
if (!startParams)
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@@ -108,6 +110,7 @@ export const startSession = async ({
|
|||||||
dynamicTheme: parseDynamicThemeInState(typebot.theme),
|
dynamicTheme: parseDynamicThemeInState(typebot.theme),
|
||||||
isStreamEnabled: startParams.isStreamEnabled,
|
isStreamEnabled: startParams.isStreamEnabled,
|
||||||
typingEmulation: typebot.settings.typingEmulation,
|
typingEmulation: typebot.settings.typingEmulation,
|
||||||
|
...initialSessionState,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startParams.isOnlyRegistering) {
|
if (startParams.isOnlyRegistering) {
|
||||||
|
|||||||
@@ -46,16 +46,6 @@ export const resumeWhatsAppFlow = async ({
|
|||||||
typebotId: typebot?.id,
|
typebotId: typebot?.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
const sessionState =
|
|
||||||
isPreview && session?.state
|
|
||||||
? ({
|
|
||||||
...session?.state,
|
|
||||||
whatsApp: {
|
|
||||||
contact,
|
|
||||||
},
|
|
||||||
} satisfies SessionState)
|
|
||||||
: session?.state
|
|
||||||
|
|
||||||
const credentials = await getCredentials({ credentialsId, isPreview })
|
const credentials = await getCredentials({ credentialsId, isPreview })
|
||||||
|
|
||||||
if (!credentials) {
|
if (!credentials) {
|
||||||
@@ -71,8 +61,8 @@ export const resumeWhatsAppFlow = async ({
|
|||||||
session?.updatedAt.getTime() + session.state.expiryTimeout < Date.now()
|
session?.updatedAt.getTime() + session.state.expiryTimeout < Date.now()
|
||||||
|
|
||||||
const resumeResponse =
|
const resumeResponse =
|
||||||
sessionState && !isSessionExpired
|
session && !isSessionExpired
|
||||||
? await continueBotFlow(sessionState)(messageContent)
|
? await continueBotFlow(session.state)(messageContent)
|
||||||
: workspaceId
|
: workspaceId
|
||||||
? await startWhatsAppSession({
|
? await startWhatsAppSession({
|
||||||
incomingMessage: messageContent,
|
incomingMessage: messageContent,
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
} from '@typebot.io/schemas'
|
} from '@typebot.io/schemas'
|
||||||
import {
|
import {
|
||||||
WhatsAppCredentials,
|
WhatsAppCredentials,
|
||||||
WhatsAppIncomingMessage,
|
|
||||||
defaultSessionExpiryTimeout,
|
defaultSessionExpiryTimeout,
|
||||||
} from '@typebot.io/schemas/features/whatsapp'
|
} from '@typebot.io/schemas/features/whatsapp'
|
||||||
import { isInputBlock, isNotDefined } from '@typebot.io/lib/utils'
|
import { isInputBlock, isNotDefined } from '@typebot.io/lib/utils'
|
||||||
@@ -73,47 +72,50 @@ export const startWhatsAppSession = async ({
|
|||||||
|
|
||||||
if (isNotDefined(publicTypebot)) return
|
if (isNotDefined(publicTypebot)) return
|
||||||
|
|
||||||
let session = await startSession({
|
|
||||||
startParams: {
|
|
||||||
typebot: publicTypebot.typebot.publicId as string,
|
|
||||||
},
|
|
||||||
userId: undefined,
|
|
||||||
})
|
|
||||||
|
|
||||||
// If first block is an input block, we can directly continue the bot flow
|
|
||||||
const firstEdgeId =
|
|
||||||
session.newSessionState.typebotsQueue[0].typebot.groups[0].blocks[0]
|
|
||||||
.outgoingEdgeId
|
|
||||||
const nextGroup = await getNextGroup(session.newSessionState)(firstEdgeId)
|
|
||||||
const firstBlock = nextGroup.group?.blocks.at(0)
|
|
||||||
if (firstBlock && isInputBlock(firstBlock)) {
|
|
||||||
const resultId = session.newSessionState.typebotsQueue[0].resultId
|
|
||||||
if (resultId)
|
|
||||||
await upsertResult({
|
|
||||||
hasStarted: true,
|
|
||||||
isCompleted: false,
|
|
||||||
resultId,
|
|
||||||
typebot: session.newSessionState.typebotsQueue[0].typebot,
|
|
||||||
})
|
|
||||||
session = await continueBotFlow({
|
|
||||||
...session.newSessionState,
|
|
||||||
currentBlock: { groupId: firstBlock.groupId, blockId: firstBlock.id },
|
|
||||||
})(incomingMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
const sessionExpiryTimeoutHours =
|
const sessionExpiryTimeoutHours =
|
||||||
publicTypebot.settings.whatsApp?.sessionExpiryTimeout ??
|
publicTypebot.settings.whatsApp?.sessionExpiryTimeout ??
|
||||||
defaultSessionExpiryTimeout
|
defaultSessionExpiryTimeout
|
||||||
|
|
||||||
return {
|
const session = await startSession({
|
||||||
...session,
|
startParams: {
|
||||||
newSessionState: {
|
typebot: publicTypebot.typebot.publicId as string,
|
||||||
...session.newSessionState,
|
},
|
||||||
|
userId: undefined,
|
||||||
|
initialSessionState: {
|
||||||
whatsApp: {
|
whatsApp: {
|
||||||
contact,
|
contact,
|
||||||
},
|
},
|
||||||
expiryTimeout: sessionExpiryTimeoutHours * 60 * 60 * 1000,
|
expiryTimeout: sessionExpiryTimeoutHours * 60 * 60 * 1000,
|
||||||
},
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
let newSessionState: SessionState = session.newSessionState
|
||||||
|
|
||||||
|
// If first block is an input block, we can directly continue the bot flow
|
||||||
|
const firstEdgeId =
|
||||||
|
newSessionState.typebotsQueue[0].typebot.groups[0].blocks[0].outgoingEdgeId
|
||||||
|
const nextGroup = await getNextGroup(newSessionState)(firstEdgeId)
|
||||||
|
const firstBlock = nextGroup.group?.blocks.at(0)
|
||||||
|
if (firstBlock && isInputBlock(firstBlock)) {
|
||||||
|
const resultId = newSessionState.typebotsQueue[0].resultId
|
||||||
|
if (resultId)
|
||||||
|
await upsertResult({
|
||||||
|
hasStarted: true,
|
||||||
|
isCompleted: false,
|
||||||
|
resultId,
|
||||||
|
typebot: newSessionState.typebotsQueue[0].typebot,
|
||||||
|
})
|
||||||
|
newSessionState = (
|
||||||
|
await continueBotFlow({
|
||||||
|
...newSessionState,
|
||||||
|
currentBlock: { groupId: firstBlock.groupId, blockId: firstBlock.id },
|
||||||
|
})(incomingMessage)
|
||||||
|
).newSessionState
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...session,
|
||||||
|
newSessionState,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { LogicBlockType } from './enums'
|
|||||||
export const valueTypes = [
|
export const valueTypes = [
|
||||||
'Custom',
|
'Custom',
|
||||||
'Empty',
|
'Empty',
|
||||||
|
'Environment name',
|
||||||
'User ID',
|
'User ID',
|
||||||
'Now',
|
'Now',
|
||||||
'Today',
|
'Today',
|
||||||
|
|||||||
Reference in New Issue
Block a user