diff --git a/src/Socket/messages-send.ts b/src/Socket/messages-send.ts index 3a09b9d3..66775fd6 100644 --- a/src/Socket/messages-send.ts +++ b/src/Socket/messages-send.ts @@ -628,8 +628,12 @@ export const makeMessagesSocket = (config: SocketConfig) => { } else if (message.templateMessage) { return 'template' } else if (message.listMessage) { - // All listMessages (SINGLE_SELECT and PRODUCT_LIST) need biz > list node + (SINGLE_SELECT and PRODUCT_LIST) need biz > list node return 'list' + + // listMessage works natively without biz node + return undefined + } else if (message.buttonsResponseMessage) { return 'buttons_response' } else if (message.listResponseMessage) { @@ -671,8 +675,13 @@ export const makeMessagesSocket = (config: SocketConfig) => { } else if (innerMessage.templateMessage) { return 'template' } else if (innerMessage.listMessage) { + // All listMessages (SINGLE_SELECT and PRODUCT_LIST) need biz > list node return 'list' + + // listMessage works natively without biz node + return undefined + } else if (innerMessage.buttonsResponseMessage) { return 'buttons_response' } else if (innerMessage.listResponseMessage) { @@ -1215,6 +1224,7 @@ export const makeMessagesSocket = (config: SocketConfig) => { metrics.interactiveMessagesSent.inc({ type: buttonType }) try { + // Differentiate biz node structure based on message type // isListMessage: true for direct listMessage OR nativeFlowMessage with single_select const isListMessage = buttonType === 'list' || isListNativeFlow(message) @@ -1223,6 +1233,11 @@ export const makeMessagesSocket = (config: SocketConfig) => { // For listMessage: use biz > list (type=product_list, v=2) // This is the format that works on both phone and web WhatsApp // Reference: Pastorini implementation +======= + // For listMessage (legacy format), use direct tag + // This matches pastorini's working implementation + if (buttonType === 'list') { + ;(stanza.content as BinaryNode[]).push({ tag: 'biz', attrs: {}, @@ -1238,11 +1253,18 @@ export const makeMessagesSocket = (config: SocketConfig) => { }) logger.info( { msgId, to: destinationJid }, + '[BIZ NODE] Added list biz node (type=product_list, v=2) for listMessage' ) } else { // For other interactive messages (native_flow, buttons, templates, carousels): // use biz > interactive > native_flow +======= + '[EXPERIMENTAL] Injected biz node for listMessage (legacy format)' + ) + } 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', diff --git a/src/Utils/messages.ts b/src/Utils/messages.ts index 46c6cad4..098f5118 100644 --- a/src/Utils/messages.ts +++ b/src/Utils/messages.ts @@ -1020,7 +1020,7 @@ export const generateListMessageLegacy = ( description, buttonText, footerText: footer, - listType: WAProto.Message.ListMessage.ListType.SINGLE_SELECT, + listType: WAProto.Message.ListMessage.ListType.PRODUCT_LIST, sections: listInfo.sections.map(section => ({ title: section.title, rows: section.rows.map(row => ({ @@ -1076,16 +1076,18 @@ export const generateWAMessageContent = async ( // Check for nativeList else if (hasNonNullishProperty(message, 'nativeList')) { const listMsg = message as any - const listOptions: ListMessageOptions = { - buttonText: listMsg.nativeList.buttonText, - sections: listMsg.nativeList.sections, - text: listMsg.text || '', - title: listMsg.title, - footer: listMsg.footer - } - const generated = generateListMessage(listOptions) - m.viewOnceMessage = generated.viewOnceMessage - options.logger?.info('Sending listMessage with viewOnceMessage wrapper') + // Use LEGACY format to avoid error 479 + // Modern format (interactiveMessage) causes rejection + // Legacy format (listMessage) works on all platforms + const generated = generateListMessageLegacy( + { sections: listMsg.nativeList.sections }, + listMsg.title || listMsg.text || '', + listMsg.text || '', + listMsg.nativeList.buttonText, + listMsg.footer + ) + m.listMessage = generated.listMessage + options.logger?.info('Sending listMessage with LEGACY format (fixes error 479)') } // Check for productList (multi-product message from catalog) else if (hasNonNullishProperty(message, 'productList')) {