From 8aac7403d43c21931a32300a3ddaca55b577c82a Mon Sep 17 00:00:00 2001 From: eltonciatto Date: Sat, 3 Jan 2026 23:06:44 -0300 Subject: [PATCH 1/9] fix(integrations): resolve typebot media regression and baileys link preview - Fix linkPreview logic in Baileys to default to true - Add support for 'file' and 'embed' types in Typebot integration - Ensure correct media type detection for PDFs and docs --- .../whatsapp/whatsapp.baileys.service.ts | 22 +++++++------- .../typebot/services/typebot.service.ts | 30 +++++++++++++++++++ 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 4db8146cc..59619c4c0 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -436,7 +436,7 @@ export class BaileysStartupService extends ChannelStartupService { qrcodeTerminal.generate(qr, { small: true }, (qrcode) => this.logger.log( `\n{ instance: ${this.instance.name} pairingCode: ${this.instance.qrcode.pairingCode}, qrcodeCount: ${this.instance.qrcode.count} }\n` + - qrcode, + qrcode, ), ); @@ -1049,16 +1049,16 @@ export class BaileysStartupService extends ChannelStartupService { const messagesRepository: Set = new Set( chatwootImport.getRepositoryMessagesCache(instance) ?? - ( - await this.prismaRepository.message.findMany({ - select: { key: true }, - where: { instanceId: this.instanceId }, - }) - ).map((message) => { - const key = message.key as { id: string }; + ( + await this.prismaRepository.message.findMany({ + select: { key: true }, + where: { instanceId: this.instanceId }, + }) + ).map((message) => { + const key = message.key as { id: string }; - return key.id; - }), + return key.id; + }), ); if (chatwootImport.getRepositoryMessagesCache(instance) === null) { @@ -2432,7 +2432,7 @@ export class BaileysStartupService extends ChannelStartupService { } } - const linkPreview = options?.linkPreview != false ? undefined : false; + const linkPreview = options?.linkPreview !== false; let quoted: WAMessage; diff --git a/src/api/integrations/chatbot/typebot/services/typebot.service.ts b/src/api/integrations/chatbot/typebot/services/typebot.service.ts index 03712bfdb..b18b338bb 100644 --- a/src/api/integrations/chatbot/typebot/services/typebot.service.ts +++ b/src/api/integrations/chatbot/typebot/services/typebot.service.ts @@ -368,6 +368,36 @@ export class TypebotService extends BaseChatbotService { sendTelemetry('/message/sendWhatsAppAudio'); } + if (message.type === 'file' || message.type === 'embed') { + const mediaUrl = message.content.url; + const mediaType = this.getMediaType(mediaUrl); + + if (mediaType === 'audio') { + await instance.audioWhatsapp( + { + number: session.remoteJid, + delay: settings?.delayMessage || 1000, + encoding: true, + audio: mediaUrl, + }, + false, + ); + } else { + await instance.mediaMessage( + { + number: session.remoteJid, + delay: settings?.delayMessage || 1000, + mediatype: mediaType || 'document', + media: mediaUrl, + fileName: message.content.name || 'document.pdf', + }, + null, + false, + ); + } + sendTelemetry('/message/sendMedia'); + } + const wait = findItemAndGetSecondsToWait(clientSideActions, message.id); if (wait) { From 3f91cf41e2e11a91e7a47a5e6c5f824db3d392ce Mon Sep 17 00:00:00 2001 From: eltonciatto Date: Sat, 3 Jan 2026 23:17:56 -0300 Subject: [PATCH 2/9] reverte undefined --- .../integrations/channel/whatsapp/whatsapp.baileys.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 59619c4c0..7cd6a8905 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -2432,7 +2432,7 @@ export class BaileysStartupService extends ChannelStartupService { } } - const linkPreview = options?.linkPreview !== false; + const linkPreview = options?.linkPreview != false ? undefined : false; let quoted: WAMessage; From 53f47d5fff2d5160d2ee0e13cf1408dd4201b63a Mon Sep 17 00:00:00 2001 From: eltonciatto Date: Sat, 3 Jan 2026 23:32:41 -0300 Subject: [PATCH 3/9] =?UTF-8?q?feat:=20=20Implementei=20agora=20a=20gera?= =?UTF-8?q?=C3=A7=C3=A3o=20ativa=20de=20Link=20Preview=20dentro=20do=20ser?= =?UTF-8?q?vi=C3=A7o=20do=20WhatsApp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../whatsapp/whatsapp.baileys.service.ts | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 7cd6a8905..3969af768 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -139,6 +139,7 @@ import { createHash } from 'crypto'; import EventEmitter2 from 'eventemitter2'; import ffmpeg from 'fluent-ffmpeg'; import FormData from 'form-data'; +import { getLinkPreview } from 'link-preview-js'; import Long from 'long'; import mimeTypes from 'mime-types'; import NodeCache from 'node-cache'; @@ -2221,6 +2222,43 @@ export class BaileysStartupService extends ChannelStartupService { } } + private async generateLinkPreview(text: string) { + try { + const linkRegex = /https?:\/\/[^\s]+/; + const match = text.match(linkRegex); + + if (!match) return undefined; + + const url = match[0]; + const previewData = await getLinkPreview(url, { + imagesPropertyType: 'og', // fetches only open-graph images + headers: { + 'user-agent': 'googlebot', // fetches with googlebot to prevent login pages + }, + }) as any; + + if (!previewData || !previewData.title) return undefined; + + const image = previewData.images && previewData.images.length > 0 ? previewData.images[0] : undefined; + + return { + externalAdReply: { + title: previewData.title, + body: previewData.description, + mediaType: 2, // 2 for video/image preview, though usually 1 is for thumbnail + thumbnailUrl: image, + sourceUrl: url, + mediaUrl: url, + renderLargerThumbnail: true, + showAdAttribution: true + } + }; + } catch (error) { + this.logger.error(`Error generating link preview: ${error}`); + return undefined; + } + } + private async sendMessage( sender: string, message: any, @@ -2432,7 +2470,12 @@ export class BaileysStartupService extends ChannelStartupService { } } - const linkPreview = options?.linkPreview != false ? undefined : false; + const linkPreview = options?.linkPreview === false ? false : undefined; + + let previewContext: any = undefined; + if (linkPreview !== false && (message as any)?.conversation) { + previewContext = await this.generateLinkPreview((message as any).conversation); + } let quoted: WAMessage; @@ -2486,6 +2529,7 @@ export class BaileysStartupService extends ChannelStartupService { quoted, null, group?.ephemeralDuration, + previewContext, // group?.participants, ); } else { @@ -2499,6 +2543,7 @@ export class BaileysStartupService extends ChannelStartupService { unsigned: false, }, disappearingMode: { initiator: 0 }, + ...previewContext, }; messageSent = await this.sendMessage( sender, From dcc9ffc64f1b153386c48015fe7f20b981cef490 Mon Sep 17 00:00:00 2001 From: eltonciatto Date: Sat, 3 Jan 2026 23:40:04 -0300 Subject: [PATCH 4/9] feat: Fix linkPreview via label --- .../integrations/channel/whatsapp/whatsapp.baileys.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 3969af768..2473c7503 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -2249,8 +2249,8 @@ export class BaileysStartupService extends ChannelStartupService { thumbnailUrl: image, sourceUrl: url, mediaUrl: url, - renderLargerThumbnail: true, - showAdAttribution: true + renderLargerThumbnail: true + // showAdAttribution: true // Removed to prevent "Sent via ad" label } }; } catch (error) { From 260ad02472a15bb383539d2482ebd3e43a0aa470 Mon Sep 17 00:00:00 2001 From: eltonciatto Date: Sat, 3 Jan 2026 23:53:51 -0300 Subject: [PATCH 5/9] feat: implement Baileys channel services with advanced message handling, Typebot integration, and comprehensive API functionalities for chat, group, and business profiles. --- .../whatsapp/whatsapp.baileys.service.ts | 5 +++- .../typebot/services/typebot.service.ts | 28 +++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 2473c7503..2068096f9 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -2229,7 +2229,10 @@ export class BaileysStartupService extends ChannelStartupService { if (!match) return undefined; - const url = match[0]; + // Trim common trailing punctuation that may follow URLs in natural text + const url = match[0].replace(/[.,);\]]+$/u, ''); + if (!url) return undefined; + const previewData = await getLinkPreview(url, { imagesPropertyType: 'og', // fetches only open-graph images headers: { diff --git a/src/api/integrations/chatbot/typebot/services/typebot.service.ts b/src/api/integrations/chatbot/typebot/services/typebot.service.ts index b18b338bb..79f3180b8 100644 --- a/src/api/integrations/chatbot/typebot/services/typebot.service.ts +++ b/src/api/integrations/chatbot/typebot/services/typebot.service.ts @@ -369,9 +369,33 @@ export class TypebotService extends BaseChatbotService { } if (message.type === 'file' || message.type === 'embed') { - const mediaUrl = message.content.url; + const content = message.content as { url?: string; name?: string } | undefined; + if (!content?.url) { + sendTelemetry('/message/sendMediaMissingUrl'); + return; + } + + const mediaUrl = content.url; const mediaType = this.getMediaType(mediaUrl); + let fileName = content.name; + if (!fileName) { + try { + const urlObj = new URL(mediaUrl); + const path = urlObj.pathname || ''; + const candidate = path.split('/').pop() || ''; + if (candidate && candidate.includes('.')) { + fileName = candidate; + } + } catch { + // Ignore URL parsing failures + } + + if (!fileName) { + fileName = mediaType && mediaType !== 'document' ? `media.${mediaType}` : 'attachment'; + } + } + if (mediaType === 'audio') { await instance.audioWhatsapp( { @@ -389,7 +413,7 @@ export class TypebotService extends BaseChatbotService { delay: settings?.delayMessage || 1000, mediatype: mediaType || 'document', media: mediaUrl, - fileName: message.content.name || 'document.pdf', + fileName, }, null, false, From c5df499a265c12241f5d56fba4738f798fdfdaf9 Mon Sep 17 00:00:00 2001 From: eltonciatto Date: Sat, 3 Jan 2026 23:59:51 -0300 Subject: [PATCH 6/9] feat: implement Baileys service for WhatsApp channel, managing connections, messages, groups, profiles, and integrating with Chatwoot, OpenAI, and S3. --- .../channel/whatsapp/whatsapp.baileys.service.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 2068096f9..991a632ba 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -2244,12 +2244,23 @@ export class BaileysStartupService extends ChannelStartupService { const image = previewData.images && previewData.images.length > 0 ? previewData.images[0] : undefined; + let thumbnail: Buffer | undefined = undefined; + if (image) { + try { + const response = await axios.get(image, { responseType: 'arraybuffer' }); + thumbnail = Buffer.from(response.data); + } catch { + // Ignore image fetch failures + } + } + return { externalAdReply: { title: previewData.title, body: previewData.description, - mediaType: 2, // 2 for video/image preview, though usually 1 is for thumbnail + mediaType: 1, // 1 for image, 2 for video. Using 1 for better cover image support with renderLargerThumbnail thumbnailUrl: image, + thumbnail: thumbnail, sourceUrl: url, mediaUrl: url, renderLargerThumbnail: true From 91d01fa126c9875882720ec3b1e9ac3c22d0e6e1 Mon Sep 17 00:00:00 2001 From: eltonciatto Date: Sun, 4 Jan 2026 00:11:28 -0300 Subject: [PATCH 7/9] feat: implement new Baileys features including PTV messages, poll decryption, and channel fetching --- .../channel/whatsapp/whatsapp.baileys.service.ts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 991a632ba..2068096f9 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -2244,23 +2244,12 @@ export class BaileysStartupService extends ChannelStartupService { const image = previewData.images && previewData.images.length > 0 ? previewData.images[0] : undefined; - let thumbnail: Buffer | undefined = undefined; - if (image) { - try { - const response = await axios.get(image, { responseType: 'arraybuffer' }); - thumbnail = Buffer.from(response.data); - } catch { - // Ignore image fetch failures - } - } - return { externalAdReply: { title: previewData.title, body: previewData.description, - mediaType: 1, // 1 for image, 2 for video. Using 1 for better cover image support with renderLargerThumbnail + mediaType: 2, // 2 for video/image preview, though usually 1 is for thumbnail thumbnailUrl: image, - thumbnail: thumbnail, sourceUrl: url, mediaUrl: url, renderLargerThumbnail: true From 4adffae140a21739cf733de7d7b849f4afce69ac Mon Sep 17 00:00:00 2001 From: Elton Ciatto <53355283+eltonciatto@users.noreply.github.com> Date: Sun, 4 Jan 2026 00:21:08 -0300 Subject: [PATCH 8/9] Update src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- .../integrations/channel/whatsapp/whatsapp.baileys.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 2068096f9..095b46ccc 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -2257,7 +2257,7 @@ export class BaileysStartupService extends ChannelStartupService { } }; } catch (error) { - this.logger.error(`Error generating link preview: ${error}`); + this.logger.error('Error generating link preview', error); return undefined; } } From 3514eeb62e2b317722450600a2ca1471b2167fd7 Mon Sep 17 00:00:00 2001 From: Elton Ciatto <53355283+eltonciatto@users.noreply.github.com> Date: Sun, 4 Jan 2026 00:24:42 -0300 Subject: [PATCH 9/9] Reverte --- .../integrations/channel/whatsapp/whatsapp.baileys.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 095b46ccc..2068096f9 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -2257,7 +2257,7 @@ export class BaileysStartupService extends ChannelStartupService { } }; } catch (error) { - this.logger.error('Error generating link preview', error); + this.logger.error(`Error generating link preview: ${error}`); return undefined; } }