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
This commit is contained in:
Claude
2026-02-06 01:35:19 +00:00
parent 932f1b17bf
commit 7b1b920104
+43 -47
View File
@@ -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 <list> 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