2
0
Files
bot/packages/bot-engine/blocks/inputs/buttons/parseButtonsReply.ts
2024-04-11 12:16:55 +02:00

82 lines
2.7 KiB
TypeScript

import { ChoiceInputBlock, SessionState } from '@typebot.io/schemas'
import { injectVariableValuesInButtonsInputBlock } from './injectVariableValuesInButtonsInputBlock'
import { ParsedReply } from '../../../types'
export const parseButtonsReply =
(state: SessionState) =>
(inputValue: string, block: ChoiceInputBlock): ParsedReply => {
const displayedItems =
injectVariableValuesInButtonsInputBlock(state)(block).items
if (block.options?.isMultipleChoice) {
const longestItemsFirst = [...displayedItems].sort(
(a, b) => (b.content?.length ?? 0) - (a.content?.length ?? 0)
)
const matchedItemsByContent = longestItemsFirst.reduce<{
strippedInput: string
matchedItemIds: string[]
}>(
(acc, item) => {
if (
item.content &&
acc.strippedInput
.toLowerCase()
.includes(item.content.trim().toLowerCase())
)
return {
strippedInput: acc.strippedInput.replace(item.content ?? '', ''),
matchedItemIds: [...acc.matchedItemIds, item.id],
}
return acc
},
{
strippedInput: inputValue.trim(),
matchedItemIds: [],
}
)
const remainingItems = displayedItems.filter(
(item) => !matchedItemsByContent.matchedItemIds.includes(item.id)
)
const matchedItemsByIndex = remainingItems.reduce<{
strippedInput: string
matchedItemIds: string[]
}>(
(acc, item, idx) => {
if (acc.strippedInput.includes(`${idx + 1}`))
return {
strippedInput: acc.strippedInput.replace(`${idx + 1}`, ''),
matchedItemIds: [...acc.matchedItemIds, item.id],
}
return acc
},
{
strippedInput: matchedItemsByContent.strippedInput,
matchedItemIds: [],
}
)
const matchedItems = displayedItems.filter((item) =>
[
...matchedItemsByContent.matchedItemIds,
...matchedItemsByIndex.matchedItemIds,
].includes(item.id)
)
if (matchedItems.length === 0) return { status: 'fail' }
return {
status: 'success',
reply: matchedItems.map((item) => item.content).join(', '),
}
}
const longestItemsFirst = [...displayedItems].sort(
(a, b) => (b.content?.length ?? 0) - (a.content?.length ?? 0)
)
const matchedItem = longestItemsFirst.find(
(item) =>
item.id === inputValue ||
(item.content && inputValue.trim() === item.content.trim())
)
if (!matchedItem) return { status: 'fail' }
return {
status: 'success',
reply: matchedItem.content ?? '',
}
}