fix(carousel): usar fromObject + viewOnceMessage para compatibilidade…

fix(carousel): usar fromObject + viewOnceMessage para compatibilidade…
This commit is contained in:
Renato Alcara
2026-02-06 17:32:43 -03:00
committed by GitHub
+19 -12
View File
@@ -640,8 +640,9 @@ export const generateCarouselMessage = async (
} }
})) }))
// Build the interactive message with carousel (matching Pastorini structure exactly) // Build the interactive message with carousel
const interactiveMessage: proto.Message.IInteractiveMessage = { const interactiveMessage: proto.Message.IInteractiveMessage = {
header: text ? { title: text } : undefined,
body: { text: text || '' }, body: { text: text || '' },
footer: footer ? { text: footer } : undefined, footer: footer ? { text: footer } : undefined,
carouselMessage: { carouselMessage: {
@@ -650,11 +651,14 @@ export const generateCarouselMessage = async (
} }
} }
// Return as direct interactiveMessage (matching Pastorini exactly) // Wrap in viewOnceMessage for MD (multi-device) compatibility
// Pastorini sends interactiveMessage without viewOnceMessage wrapper // This ensures Web/Desktop clients can render the carousel
// and it renders on Web. Biz node is injected separately in messages-send.ts
return { return {
interactiveMessage viewOnceMessage: {
message: {
interactiveMessage
}
}
} }
} }
@@ -1151,8 +1155,13 @@ export const generateWAMessageContent = async (
} }
// Pass options for media processing if cards have images/videos // Pass options for media processing if cards have images/videos
const generated = await generateCarouselMessage(carouselOptions, options) const generated = await generateCarouselMessage(carouselOptions, options)
m.interactiveMessage = generated.interactiveMessage m.viewOnceMessage = generated.viewOnceMessage
options.logger?.info('Sending carouselMessage as direct interactiveMessage (matching Pastorini)') options.logger?.info('Sending carousel with viewOnceMessage wrapper + fromObject encoding')
// Return early with fromObject for proper deep conversion of nested carousel structure
// fromObject recursively converts nested plain objects to protobuf message instances
// whereas create() does shallow property copy which may not properly encode deep structures
// This matches the working implementation's encoding approach
return WAProto.Message.fromObject(m)
} }
// Check for nativeList // Check for nativeList
else if (hasNonNullishProperty(message, 'nativeList')) { else if (hasNonNullishProperty(message, 'nativeList')) {
@@ -1642,11 +1651,9 @@ export const generateWAMessageContent = async (
} }
} }
// Skip messageContextInfo for carousel messages // Add messageContextInfo with reporting token for non-carousel messages
// Carousel sent as direct interactiveMessage doesn't need reporting token // Carousel messages return early with fromObject encoding and don't need this
// and messageContextInfo alongside interactiveMessage causes error 479 on linked devices if (shouldIncludeReportingToken(m)) {
const isCarouselMsg = !!m.interactiveMessage?.carouselMessage
if (shouldIncludeReportingToken(m) && !isCarouselMsg) {
m.messageContextInfo = m.messageContextInfo || {} m.messageContextInfo = m.messageContextInfo || {}
if (!m.messageContextInfo.messageSecret) { if (!m.messageContextInfo.messageSecret) {
m.messageContextInfo.messageSecret = randomBytes(32) m.messageContextInfo.messageSecret = randomBytes(32)