From 7b1b920104f60ae1cfa7ebec4a9fc0a4703b2845 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 6 Feb 2026 01:35:19 +0000 Subject: [PATCH] fix: Disable biz node injection for list messages to fix Web/iOS delivery After testing, messages with list-specific biz node structure were not being delivered. Analysis of the issue revealed that list messages with nativeFlowMessage should NOT have biz node injection, similar to product lists. Changes: - Modified getButtonType() to detect list buttons (single_select/multi_select) - Return undefined for list buttons to skip biz node injection - Applied to both direct interactiveMessage and viewOnceMessage wrapped messages - Simplified biz node injection logic since lists now skip it This approach aligns with how product lists are handled (no biz node) and should allow list messages to be delivered successfully on all platforms. Previous attempt used custom biz node structure which caused delivery failures. This conservative approach avoids biz node entirely for lists. https://claude.ai/code/session_01Vgu4xrsj8aUVCHWb4pmQPF --- src/Socket/messages-send.ts | 90 ++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/src/Socket/messages-send.ts b/src/Socket/messages-send.ts index 7069ba8b..5f675de9 100644 --- a/src/Socket/messages-send.ts +++ b/src/Socket/messages-send.ts @@ -643,6 +643,15 @@ export const makeMessagesSocket = (config: SocketConfig) => { } else if (message.interactiveMessage) { // Check if it has nativeFlowMessage (modern format) if (message.interactiveMessage.nativeFlowMessage) { + // Check if it's a list (single_select or multi_select) + // Lists don't need biz node injection, similar to product lists + const buttons = message.interactiveMessage.nativeFlowMessage.buttons || [] + const isListButton = buttons.some( + (btn: any) => btn?.name === 'single_select' || btn?.name === 'multi_select' + ) + if (isListButton) { + return undefined // No biz node for list messages + } return 'native_flow' } // Check if it's a carousel with nativeFlowMessage buttons in cards @@ -689,6 +698,15 @@ export const makeMessagesSocket = (config: SocketConfig) => { } else if (innerMessage.interactiveMessage) { // Check if it has nativeFlowMessage (modern format) if (innerMessage.interactiveMessage.nativeFlowMessage) { + // Check if it's a list (single_select or multi_select) + // Lists don't need biz node injection, similar to product lists + const buttons = innerMessage.interactiveMessage.nativeFlowMessage.buttons || [] + const isListButton = buttons.some( + (btn: any) => btn?.name === 'single_select' || btn?.name === 'multi_select' + ) + if (isListButton) { + return undefined // No biz node for list messages + } return 'native_flow' } // Check if it's a carousel with nativeFlowMessage buttons in cards @@ -1215,54 +1233,32 @@ export const makeMessagesSocket = (config: SocketConfig) => { metrics.interactiveMessagesSent.inc({ type: buttonType }) try { - // Check if this is a list message to use the correct biz node structure - if (isListDetected) { - // For list messages, use direct tag in biz node - // This structure works on Web, iOS, and Android - ;(stanza.content as BinaryNode[]).push({ - tag: 'biz', - attrs: {}, - content: [ - { - tag: 'list', - attrs: { - type: 'single_select', - v: '2' - } - } - ] - }) - logger.info( - { msgId, to: destinationJid }, - '[EXPERIMENTAL] Injected list-specific biz node for Web/iOS/Android compatibility' - ) - } else { - // Use nested structure: biz > interactive > native_flow - // For buttons, carousels, and other interactive messages - const interactiveType = 'native_flow' - ;(stanza.content as BinaryNode[]).push({ - tag: 'biz', - attrs: {}, - content: [ - { - tag: 'interactive', - attrs: { - type: interactiveType, - v: '1' - }, - content: [ - { - tag: interactiveType, - attrs: { - v: '9', - name: 'mixed' - } + // Use nested structure: biz > interactive > native_flow + // For buttons, carousels, and other interactive messages + // NOTE: Lists now skip biz node injection (handled in getButtonType) + const interactiveType = 'native_flow' + ;(stanza.content as BinaryNode[]).push({ + tag: 'biz', + attrs: {}, + content: [ + { + tag: 'interactive', + attrs: { + type: interactiveType, + v: '1' + }, + content: [ + { + tag: interactiveType, + attrs: { + v: '9', + name: 'mixed' } - ] - } - ] - }) - } + } + ] + } + ] + }) // For private 1:1 chats, add bot node (required for some interactive messages to render) // Only inject for actual user JIDs, not broadcasts, newsletters, or Meta AI bots