Skip to content
Open
70 changes: 59 additions & 11 deletions src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
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';
Expand Down Expand Up @@ -436,7 +437,7 @@
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,

Check failure on line 440 in src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

View workflow job for this annotation

GitHub Actions / check-lint-and-build

Insert `Β·Β·`
),
);

Expand Down Expand Up @@ -1049,16 +1050,16 @@

const messagesRepository: Set<string> = 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 };
(

Check failure on line 1053 in src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

View workflow job for this annotation

GitHub Actions / check-lint-and-build

Insert `Β·Β·`
await this.prismaRepository.message.findMany({

Check failure on line 1054 in src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

View workflow job for this annotation

GitHub Actions / check-lint-and-build

Insert `Β·Β·`
select: { key: true },

Check failure on line 1055 in src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

View workflow job for this annotation

GitHub Actions / check-lint-and-build

Replace `Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·` with `Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·`
where: { instanceId: this.instanceId },

Check failure on line 1056 in src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

View workflow job for this annotation

GitHub Actions / check-lint-and-build

Insert `Β·Β·`
})

Check failure on line 1057 in src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

View workflow job for this annotation

GitHub Actions / check-lint-and-build

Replace `Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·` with `Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·`
).map((message) => {

Check failure on line 1058 in src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

View workflow job for this annotation

GitHub Actions / check-lint-and-build

Insert `Β·Β·`
const key = message.key as { id: string };

Check failure on line 1059 in src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

View workflow job for this annotation

GitHub Actions / check-lint-and-build

Insert `Β·Β·`

return key.id;
}),
return key.id;

Check failure on line 1061 in src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

View workflow job for this annotation

GitHub Actions / check-lint-and-build

Insert `Β·Β·`
}),

Check failure on line 1062 in src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

View workflow job for this annotation

GitHub Actions / check-lint-and-build

Insert `Β·Β·`
);

if (chatwootImport.getRepositoryMessagesCache(instance) === null) {
Expand Down Expand Up @@ -2221,6 +2222,46 @@
}
}

private async generateLinkPreview(text: string) {
try {
const linkRegex = /https?:\/\/[^\s]+/;
const match = text.match(linkRegex);

if (!match) return undefined;

// 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: {
'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 // Removed to prevent "Sent via ad" label
}
};
} catch (error) {
this.logger.error(`Error generating link preview: ${error}`);
return undefined;
}
}

private async sendMessage(
sender: string,
message: any,
Expand Down Expand Up @@ -2432,7 +2473,12 @@
}
}

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;

Expand Down Expand Up @@ -2486,6 +2532,7 @@
quoted,
null,
group?.ephemeralDuration,
previewContext,
// group?.participants,
);
} else {
Expand All @@ -2499,6 +2546,7 @@
unsigned: false,
},
disappearingMode: { initiator: 0 },
...previewContext,
};
messageSent = await this.sendMessage(
sender,
Expand Down
54 changes: 54 additions & 0 deletions src/api/integrations/chatbot/typebot/services/typebot.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,60 @@ export class TypebotService extends BaseChatbotService<TypebotModel, any> {
sendTelemetry('/message/sendWhatsAppAudio');
}

if (message.type === 'file' || message.type === 'embed') {
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(
{
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,
},
null,
false,
);
}
sendTelemetry('/message/sendMedia');
}

const wait = findItemAndGetSecondsToWait(clientSideActions, message.id);

if (wait) {
Expand Down
Loading