♻️ (bot) Change to features-centric folder structure
This commit is contained in:
committed by
Baptiste Arnaud
parent
a5c8a8a95c
commit
972094425a
32
packages/bot-engine/src/utils/chat.ts
Normal file
32
packages/bot-engine/src/utils/chat.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import {
|
||||
BubbleBlock,
|
||||
BubbleBlockType,
|
||||
InputBlock,
|
||||
InputBlockType,
|
||||
Block,
|
||||
} from 'models'
|
||||
import { isBubbleBlock, isInputBlock } from 'utils'
|
||||
import type { TypebotPostMessageData } from 'typebot-js'
|
||||
|
||||
export const getLastChatBlockType = (
|
||||
blocks: Block[]
|
||||
): BubbleBlockType | InputBlockType | undefined => {
|
||||
const displayedBlocks = blocks.filter(
|
||||
(s) => isBubbleBlock(s) || isInputBlock(s)
|
||||
) as (BubbleBlock | InputBlock)[]
|
||||
return displayedBlocks.pop()?.type
|
||||
}
|
||||
|
||||
export const sendEventToParent = (data: TypebotPostMessageData) => {
|
||||
try {
|
||||
window.top?.postMessage(
|
||||
{
|
||||
from: 'typebot',
|
||||
...data,
|
||||
},
|
||||
'*'
|
||||
)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
31
packages/bot-engine/src/utils/executeIntegration.ts
Normal file
31
packages/bot-engine/src/utils/executeIntegration.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { executeChatwootBlock } from '@/features/blocks/integrations/chatwoot'
|
||||
import { executeGoogleAnalyticsBlock } from '@/features/blocks/integrations/googleAnalytics'
|
||||
import { executeGoogleSheetBlock } from '@/features/blocks/integrations/googleSheets'
|
||||
import { executeSendEmailBlock } from '@/features/blocks/integrations/sendEmail'
|
||||
import { executeWebhook } from '@/features/blocks/integrations/webhook'
|
||||
import { IntegrationState } from '@/types'
|
||||
import { IntegrationBlock, IntegrationBlockType } from 'models'
|
||||
|
||||
export const executeIntegration = ({
|
||||
block,
|
||||
context,
|
||||
}: {
|
||||
block: IntegrationBlock
|
||||
context: IntegrationState
|
||||
}): Promise<string | undefined> => {
|
||||
switch (block.type) {
|
||||
case IntegrationBlockType.GOOGLE_SHEETS:
|
||||
return executeGoogleSheetBlock(block, context)
|
||||
case IntegrationBlockType.GOOGLE_ANALYTICS:
|
||||
return executeGoogleAnalyticsBlock(block, context)
|
||||
case IntegrationBlockType.ZAPIER:
|
||||
case IntegrationBlockType.MAKE_COM:
|
||||
case IntegrationBlockType.PABBLY_CONNECT:
|
||||
case IntegrationBlockType.WEBHOOK:
|
||||
return executeWebhook(block, context)
|
||||
case IntegrationBlockType.EMAIL:
|
||||
return executeSendEmailBlock(block, context)
|
||||
case IntegrationBlockType.CHATWOOT:
|
||||
return executeChatwootBlock(block, context)
|
||||
}
|
||||
}
|
||||
30
packages/bot-engine/src/utils/executeLogic.ts
Normal file
30
packages/bot-engine/src/utils/executeLogic.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { TypebotViewerProps } from '@/components/TypebotViewer'
|
||||
import { executeCode } from '@/features/blocks/logic/code'
|
||||
import { executeCondition } from '@/features/blocks/logic/condition'
|
||||
import { executeRedirect } from '@/features/blocks/logic/redirect'
|
||||
import { executeSetVariable } from '@/features/blocks/logic/setVariable'
|
||||
import { executeTypebotLink } from '@/features/blocks/logic/typebotLink'
|
||||
import { LinkedTypebot } from '@/providers/TypebotProvider'
|
||||
import { EdgeId, LogicState } from '@/types'
|
||||
import { LogicBlock, LogicBlockType } from 'models'
|
||||
|
||||
export const executeLogic = async (
|
||||
block: LogicBlock,
|
||||
context: LogicState
|
||||
): Promise<{
|
||||
nextEdgeId?: EdgeId
|
||||
linkedTypebot?: TypebotViewerProps['typebot'] | LinkedTypebot
|
||||
}> => {
|
||||
switch (block.type) {
|
||||
case LogicBlockType.SET_VARIABLE:
|
||||
return { nextEdgeId: executeSetVariable(block, context) }
|
||||
case LogicBlockType.CONDITION:
|
||||
return { nextEdgeId: executeCondition(block, context) }
|
||||
case LogicBlockType.REDIRECT:
|
||||
return { nextEdgeId: executeRedirect(block, context) }
|
||||
case LogicBlockType.CODE:
|
||||
return { nextEdgeId: await executeCode(block, context) }
|
||||
case LogicBlockType.TYPEBOT_LINK:
|
||||
return await executeTypebotLink(block, context)
|
||||
}
|
||||
}
|
||||
28
packages/bot-engine/src/utils/helpers.ts
Normal file
28
packages/bot-engine/src/utils/helpers.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Log } from 'db'
|
||||
|
||||
export const sanitizeUrl = (url: string): string =>
|
||||
url.startsWith('http') ||
|
||||
url.startsWith('mailto:') ||
|
||||
url.startsWith('tel:') ||
|
||||
url.startsWith('sms:')
|
||||
? url
|
||||
: `https://${url}`
|
||||
|
||||
export const isMobile =
|
||||
typeof window !== 'undefined' &&
|
||||
window.matchMedia('only screen and (max-width: 760px)').matches
|
||||
|
||||
export const isEmbedded =
|
||||
typeof window !== 'undefined' &&
|
||||
window.parent &&
|
||||
window.location !== window.top?.location
|
||||
|
||||
export const parseLog = (
|
||||
error: Error | undefined,
|
||||
successMessage: string,
|
||||
errorMessage: string
|
||||
): Omit<Log, 'id' | 'createdAt' | 'resultId'> => ({
|
||||
status: error ? 'error' : 'success',
|
||||
description: error ? errorMessage : successMessage,
|
||||
details: (error && JSON.stringify(error, null, 2).substring(0, 1000)) ?? null,
|
||||
})
|
||||
62
packages/bot-engine/src/utils/inputs.ts
Normal file
62
packages/bot-engine/src/utils/inputs.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { validateEmail } from '@/features/blocks/inputs/email'
|
||||
import { validatePhoneNumber } from '@/features/blocks/inputs/phone'
|
||||
import { validateUrl } from '@/features/blocks/inputs/url'
|
||||
import { parseVariables } from '@/features/variables'
|
||||
import {
|
||||
BubbleBlock,
|
||||
BubbleBlockType,
|
||||
Edge,
|
||||
EmailInputBlock,
|
||||
InputBlockType,
|
||||
PhoneNumberInputBlock,
|
||||
Block,
|
||||
UrlInputBlock,
|
||||
Variable,
|
||||
} from 'models'
|
||||
import { isInputBlock } from 'utils'
|
||||
|
||||
export const isInputValid = (
|
||||
inputValue: string,
|
||||
type: InputBlockType
|
||||
): boolean => {
|
||||
switch (type) {
|
||||
case InputBlockType.EMAIL:
|
||||
return validateEmail(inputValue)
|
||||
case InputBlockType.PHONE:
|
||||
return validatePhoneNumber(inputValue)
|
||||
case InputBlockType.URL:
|
||||
return validateUrl(inputValue)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export const blockCanBeRetried = (
|
||||
block: Block
|
||||
): block is EmailInputBlock | UrlInputBlock | PhoneNumberInputBlock =>
|
||||
isInputBlock(block) && 'retryMessageContent' in block.options
|
||||
|
||||
export const parseRetryBlock = (
|
||||
block: EmailInputBlock | UrlInputBlock | PhoneNumberInputBlock,
|
||||
variables: Variable[],
|
||||
createEdge: (edge: Edge) => void
|
||||
): BubbleBlock => {
|
||||
const content = parseVariables(variables)(block.options.retryMessageContent)
|
||||
const newBlockId = block.id + Math.random() * 1000
|
||||
const newEdge: Edge = {
|
||||
id: (Math.random() * 1000).toString(),
|
||||
from: { blockId: newBlockId, groupId: block.groupId },
|
||||
to: { groupId: block.groupId, blockId: block.id },
|
||||
}
|
||||
createEdge(newEdge)
|
||||
return {
|
||||
groupId: block.groupId,
|
||||
id: newBlockId,
|
||||
type: BubbleBlockType.TEXT,
|
||||
content: {
|
||||
html: `<div>${content}</div>`,
|
||||
richText: [],
|
||||
plainText: content,
|
||||
},
|
||||
outgoingEdgeId: newEdge.id,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user