From 0bc9f4a34efe4c1a6169c215ce43994b1a7408ba Mon Sep 17 00:00:00 2001 From: Renato Alcara Date: Mon, 16 Mar 2026 22:07:28 -0300 Subject: [PATCH] fix: flatten carousel thumbnail fallback --- src/Utils/messages.ts | 76 +++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/src/Utils/messages.ts b/src/Utils/messages.ts index 490dd16c..468498df 100644 --- a/src/Utils/messages.ts +++ b/src/Utils/messages.ts @@ -475,6 +475,48 @@ export const formatNativeFlowButton = (button: NativeButton): NativeFlowButton = } } +const recoverCarouselImageMetadata = async ( + card: CarouselMessageOptions['cards'][number], + imageMessage: proto.Message.IImageMessage, + mediaOptions: MessageContentGenerationOptions +) => { + if (imageMessage.jpegThumbnail && imageMessage.height && imageMessage.width) { + return + } + + try { + const { stream } = await getStream(card.image!, mediaOptions.options) + const thumb = await extractImageThumb(stream) + + if (!imageMessage.jpegThumbnail) { + imageMessage.jpegThumbnail = thumb.buffer + } + + if (!imageMessage.width && thumb.original.width) { + imageMessage.width = thumb.original.width + } + + if (!imageMessage.height && thumb.original.height) { + imageMessage.height = thumb.original.height + } + + mediaOptions.logger?.info( + { + cardTitle: card.title, + hasJpegThumbnail: !!imageMessage.jpegThumbnail, + width: imageMessage.width, + height: imageMessage.height + }, + '[CAROUSEL] Recovered image thumbnail/dimensions from source media' + ) + } catch (error) { + mediaOptions.logger?.warn( + { cardTitle: card.title, error }, + '[CAROUSEL] Failed to recover image thumbnail/dimensions from source media' + ) + } +} + /** * Generates a button message using Native Flow format wrapped in viewOnceMessage * This is the modern approach for button messages that works on iOS and Android @@ -650,38 +692,8 @@ export const generateCarouselMessage = async ( if (hasMedia && mediaOptions) { if (card.image) { const { imageMessage } = await prepareWAMessageMedia({ image: card.image }, mediaOptions) - if (imageMessage && (!imageMessage.jpegThumbnail || !imageMessage.height || !imageMessage.width)) { - try { - const { stream } = await getStream(card.image, mediaOptions.options) - const thumb = await extractImageThumb(stream) - - if (!imageMessage.jpegThumbnail) { - imageMessage.jpegThumbnail = thumb.buffer - } - - if (!imageMessage.width && thumb.original.width) { - imageMessage.width = thumb.original.width - } - - if (!imageMessage.height && thumb.original.height) { - imageMessage.height = thumb.original.height - } - - mediaOptions.logger?.info( - { - cardTitle: card.title, - hasJpegThumbnail: !!imageMessage.jpegThumbnail, - width: imageMessage.width, - height: imageMessage.height - }, - '[CAROUSEL] Recovered image thumbnail/dimensions from source media' - ) - } catch (error) { - mediaOptions.logger?.warn( - { cardTitle: card.title, error }, - '[CAROUSEL] Failed to recover image thumbnail/dimensions from source media' - ) - } + if (imageMessage) { + await recoverCarouselImageMetadata(card, imageMessage, mediaOptions) } if (imageMessage && !imageMessage.jpegThumbnail) {