import { type FrameMetadata } from '../../utils/getFrameMetadata.js' import { type FrameButton } from '../types.js' // https://regexr.com/7rlm0 const buttonRegex = /fc:frame:button:(1|2|3|4)(?::(action|target))?$/ export function parseButtons(metadata: FrameMetadata) { let currentButtonIndex = 0 let buttonsAreMissing = false let buttonsAreOutOfOrder = false const buttonMap = new Map>() const buttonActionMap = new Map() const buttonTargetMap = new Map() const invalidButtons: FrameButton['index'][] = [] for (const meta of metadata) { const { property } = meta if (!buttonRegex.test(property)) continue const matchArray = property.match(buttonRegex) as [ string, string, string | undefined, ] const index = parseInt(matchArray[1], 10) as FrameButton['index'] const type = matchArray[2] const content = meta.content ?? '' if (type === 'action') buttonActionMap.set(index, content as FrameButton['type']) else if (type === 'target') buttonTargetMap.set(index, content as FrameButton['target']) else { if (currentButtonIndex >= index) buttonsAreOutOfOrder = true if (currentButtonIndex + 1 === index) currentButtonIndex = index else buttonsAreMissing = true if (buttonsAreOutOfOrder || buttonsAreMissing) invalidButtons.push(index) const title = content ?? index buttonMap.set(index, { index, title }) } } const buttons: FrameButton[] = [] for (const [index, button] of buttonMap) { const type = buttonActionMap.get(index) ?? 'post' const target = buttonTargetMap.get(index) as FrameButton['target'] buttons.push({ ...button, ...(target ? { target } : {}), type, } as FrameButton) } // Using `sort` over `toSorted` for Node.js < 20 compatibility (ie. Vercel default). buttons.sort((a, b) => a.index - b.index) return buttons }