diff --git a/package.json b/package.json index f26bae6c..96c408a2 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,6 @@ "dayjs": "^1.11.7", "dotenv": "^16.4.5", "eventemitter2": "^6.4.9", - "evolution-manager-v2": "^0.0.2", "exiftool-vendored": "^22.0.0", "express": "^4.18.2", "express-async-errors": "^3.1.1", diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 5e4b91e9..13eea7b5 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -739,19 +739,24 @@ export class BaileysStartupService extends ChannelStartupService { }, }); - const instance = { instanceName: this.instance.name, instanceId: this.instance.id }; + if (this.configService.get('CHATWOOT').ENABLED && this.localChatwoot?.enabled) { + const instance = { instanceName: this.instance.name, instanceId: this.instance.id }; - const findParticipant = await this.chatwootService.findContact(instance, contact.remoteJid.split('@')[0]); + const findParticipant = await this.chatwootService.findContact( + instance, + contact.remoteJid.split('@')[0], + ); - if (!findParticipant) { - return; + if (!findParticipant) { + return; + } + + this.chatwootService.updateContact(instance, findParticipant.id, { + name: contact.pushName, + avatar_url: contact.profilePicUrl, + }); } - this.chatwootService.updateContact(instance, findParticipant.id, { - name: contact.pushName, - avatar_url: contact.profilePicUrl, - }); - return update; }), ); diff --git a/src/api/integrations/chatbot/dify/services/dify.service.ts b/src/api/integrations/chatbot/dify/services/dify.service.ts index eff4133c..66c55ab2 100644 --- a/src/api/integrations/chatbot/dify/services/dify.service.ts +++ b/src/api/integrations/chatbot/dify/services/dify.service.ts @@ -14,7 +14,7 @@ export class DifyService { private readonly waMonitor: WAMonitoringService, private readonly configService: ConfigService, private readonly prismaRepository: PrismaRepository, - ) {} + ) { } private readonly logger = new Logger('DifyService'); @@ -349,51 +349,99 @@ export class DifyService { } } - private async sendMessageWhatsApp(instance: any, remoteJid: string, message: string, settings: DifySetting) { - const regex = /!?\[(.*?)\]\((.*?)\)/g; + private async sendMessageWhatsApp( + instance: any, + remoteJid: string, + message: string, + settings: DifySetting + ) { + const linkRegex = /(!?)\[(.*?)\]\((.*?)\)/g; - const result = []; + let textBuffer = ''; let lastIndex = 0; - let match; - while ((match = regex.exec(message)) !== null) { - if (match.index > lastIndex) { - result.push({ text: message.slice(lastIndex, match.index).trim() }); + let match: RegExpExecArray | null; + + const getMediaType = (url: string): string | null => { + const extension = url.split('.').pop()?.toLowerCase(); + const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']; + const audioExtensions = ['mp3', 'wav', 'aac', 'ogg']; + const videoExtensions = ['mp4', 'avi', 'mkv', 'mov']; + const documentExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt']; + + if (imageExtensions.includes(extension || '')) return 'image'; + if (audioExtensions.includes(extension || '')) return 'audio'; + if (videoExtensions.includes(extension || '')) return 'video'; + if (documentExtensions.includes(extension || '')) return 'document'; + return null; + }; + + while ((match = linkRegex.exec(message)) !== null) { + const [fullMatch, exclMark, altText, url] = match; + const mediaType = getMediaType(url); + + const beforeText = message.slice(lastIndex, match.index); + if (beforeText) { + textBuffer += beforeText; } - result.push({ caption: match[1], url: match[2] }); + if (mediaType) { + if (textBuffer.trim()) { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false + ); + textBuffer = ''; + } - lastIndex = regex.lastIndex; + if (mediaType === 'audio') { + await instance.audioWhatsapp( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + audio: url, + caption: altText, + } + ); + } else { + await instance.mediaMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + mediatype: mediaType, + media: url, + caption: altText, + }, + false + ); + } + } else { + textBuffer += `[${altText}](${url})`; + } + + lastIndex = linkRegex.lastIndex; } if (lastIndex < message.length) { - result.push({ text: message.slice(lastIndex).trim() }); + const remainingText = message.slice(lastIndex); + if (remainingText.trim()) { + textBuffer += remainingText; + } } - for (const item of result) { - if (item.text) { - await instance.textMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - text: item.text, - }, - false, - ); - } - - if (item.url) { - await instance.mediaMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - mediatype: 'image', - media: item.url, - caption: item.caption, - }, - false, - ); - } + if (textBuffer.trim()) { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false + ); } sendTelemetry('/message/sendText'); diff --git a/src/api/integrations/chatbot/evolutionBot/services/evolutionBot.service.ts b/src/api/integrations/chatbot/evolutionBot/services/evolutionBot.service.ts index a0967007..bb6eb817 100644 --- a/src/api/integrations/chatbot/evolutionBot/services/evolutionBot.service.ts +++ b/src/api/integrations/chatbot/evolutionBot/services/evolutionBot.service.ts @@ -13,7 +13,7 @@ export class EvolutionBotService { private readonly waMonitor: WAMonitoringService, private readonly configService: ConfigService, private readonly prismaRepository: PrismaRepository, - ) {} + ) { } private readonly logger = new Logger('EvolutionBotService'); @@ -112,52 +112,97 @@ export class EvolutionBotService { settings: EvolutionBotSetting, message: string, ) { - const regex = /!?\[(.*?)\]\((.*?)\)/g; + const linkRegex = /(!?)\[(.*?)\]\((.*?)\)/g; - const result = []; + let textBuffer = ''; let lastIndex = 0; - let match; - while ((match = regex.exec(message)) !== null) { - if (match.index > lastIndex) { - result.push({ text: message.slice(lastIndex, match.index).trim() }); + let match: RegExpExecArray | null; + + const getMediaType = (url: string): string | null => { + const extension = url.split('.').pop()?.toLowerCase(); + const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']; + const audioExtensions = ['mp3', 'wav', 'aac', 'ogg']; + const videoExtensions = ['mp4', 'avi', 'mkv', 'mov']; + const documentExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt']; + + if (imageExtensions.includes(extension || '')) return 'image'; + if (audioExtensions.includes(extension || '')) return 'audio'; + if (videoExtensions.includes(extension || '')) return 'video'; + if (documentExtensions.includes(extension || '')) return 'document'; + return null; + }; + + while ((match = linkRegex.exec(message)) !== null) { + const [fullMatch, exclMark, altText, url] = match; + const mediaType = getMediaType(url); + + const beforeText = message.slice(lastIndex, match.index); + if (beforeText) { + textBuffer += beforeText; } - result.push({ caption: match[1], url: match[2] }); + if (mediaType) { + if (textBuffer.trim()) { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false + ); + textBuffer = ''; + } - lastIndex = regex.lastIndex; + if (mediaType === 'audio') { + await instance.audioWhatsapp( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + audio: url, + caption: altText, + } + ); + } else { + await instance.mediaMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + mediatype: mediaType, + media: url, + caption: altText, + }, + false + ); + } + } else { + textBuffer += `[${altText}](${url})`; + } + + lastIndex = linkRegex.lastIndex; } if (lastIndex < message.length) { - result.push({ text: message.slice(lastIndex).trim() }); - } - - for (const item of result) { - if (item.text) { - await instance.textMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - text: item.text, - }, - false, - ); - } - - if (item.url) { - await instance.mediaMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - mediatype: 'image', - media: item.url, - caption: item.caption, - }, - false, - ); + const remainingText = message.slice(lastIndex); + if (remainingText.trim()) { + textBuffer += remainingText; } } + if (textBuffer.trim()) { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false + ); + } + + sendTelemetry('/message/sendText'); + await this.prismaRepository.integrationSession.update({ where: { id: session.id, @@ -167,12 +212,9 @@ export class EvolutionBotService { awaitUser: true, }, }); - - sendTelemetry('/message/sendText'); - - return; } + private async initNewSession( instance: any, remoteJid: string, diff --git a/src/api/integrations/chatbot/flowise/services/flowise.service.ts b/src/api/integrations/chatbot/flowise/services/flowise.service.ts index ff17ab2e..c0b66dd6 100644 --- a/src/api/integrations/chatbot/flowise/services/flowise.service.ts +++ b/src/api/integrations/chatbot/flowise/services/flowise.service.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ import { InstanceDto } from '@api/dto/instance.dto'; import { PrismaRepository } from '@api/repository/repository.service'; import { WAMonitoringService } from '@api/services/monitor.service'; @@ -111,52 +112,95 @@ export class FlowiseService { settings: FlowiseSetting, message: string, ) { - const regex = /!?\[(.*?)\]\((.*?)\)/g; + const linkRegex = /(!?)\[(.*?)\]\((.*?)\)/g; - const result = []; + let textBuffer = ''; let lastIndex = 0; - let match; - while ((match = regex.exec(message)) !== null) { - if (match.index > lastIndex) { - result.push({ text: message.slice(lastIndex, match.index).trim() }); + let match: RegExpExecArray | null; + + const getMediaType = (url: string): string | null => { + const extension = url.split('.').pop()?.toLowerCase(); + const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']; + const audioExtensions = ['mp3', 'wav', 'aac', 'ogg']; + const videoExtensions = ['mp4', 'avi', 'mkv', 'mov']; + const documentExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt']; + + if (imageExtensions.includes(extension || '')) return 'image'; + if (audioExtensions.includes(extension || '')) return 'audio'; + if (videoExtensions.includes(extension || '')) return 'video'; + if (documentExtensions.includes(extension || '')) return 'document'; + return null; + }; + + while ((match = linkRegex.exec(message)) !== null) { + const [fullMatch, exclMark, altText, url] = match; + const mediaType = getMediaType(url); + + const beforeText = message.slice(lastIndex, match.index); + if (beforeText) { + textBuffer += beforeText; } - result.push({ caption: match[1], url: match[2] }); + if (mediaType) { + if (textBuffer.trim()) { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false, + ); + textBuffer = ''; + } - lastIndex = regex.lastIndex; + if (mediaType === 'audio') { + await instance.audioWhatsapp({ + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + audio: url, + caption: altText, + }); + } else { + await instance.mediaMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + mediatype: mediaType, + media: url, + caption: altText, + }, + false, + ); + } + } else { + textBuffer += `[${altText}](${url})`; + } + + lastIndex = linkRegex.lastIndex; } if (lastIndex < message.length) { - result.push({ text: message.slice(lastIndex).trim() }); - } - - for (const item of result) { - if (item.text) { - await instance.textMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - text: item.text, - }, - false, - ); - } - - if (item.url) { - await instance.mediaMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - mediatype: 'image', - media: item.url, - caption: item.caption, - }, - false, - ); + const remainingText = message.slice(lastIndex); + if (remainingText.trim()) { + textBuffer += remainingText; } } + if (textBuffer.trim()) { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false, + ); + } + + sendTelemetry('/message/sendText'); + await this.prismaRepository.integrationSession.update({ where: { id: session.id, @@ -167,8 +211,6 @@ export class FlowiseService { }, }); - sendTelemetry('/message/sendText'); - return; } diff --git a/src/api/integrations/chatbot/openai/services/openai.service.ts b/src/api/integrations/chatbot/openai/services/openai.service.ts index 6db2b334..53f144c4 100644 --- a/src/api/integrations/chatbot/openai/services/openai.service.ts +++ b/src/api/integrations/chatbot/openai/services/openai.service.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ import { InstanceDto } from '@api/dto/instance.dto'; import { PrismaRepository } from '@api/repository/repository.service'; import { WAMonitoringService } from '@api/services/monitor.service'; @@ -156,52 +157,95 @@ export class OpenaiService { settings: OpenaiSetting, message: string, ) { - const regex = /!?\[(.*?)\]\((.*?)\)/g; + const linkRegex = /(!?)\[(.*?)\]\((.*?)\)/g; - const result = []; + let textBuffer = ''; let lastIndex = 0; - let match; - while ((match = regex.exec(message)) !== null) { - if (match.index > lastIndex) { - result.push({ text: message.slice(lastIndex, match.index).trim() }); + let match: RegExpExecArray | null; + + const getMediaType = (url: string): string | null => { + const extension = url.split('.').pop()?.toLowerCase(); + const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']; + const audioExtensions = ['mp3', 'wav', 'aac', 'ogg']; + const videoExtensions = ['mp4', 'avi', 'mkv', 'mov']; + const documentExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt']; + + if (imageExtensions.includes(extension || '')) return 'image'; + if (audioExtensions.includes(extension || '')) return 'audio'; + if (videoExtensions.includes(extension || '')) return 'video'; + if (documentExtensions.includes(extension || '')) return 'document'; + return null; + }; + + while ((match = linkRegex.exec(message)) !== null) { + const [fullMatch, exclMark, altText, url] = match; + const mediaType = getMediaType(url); + + const beforeText = message.slice(lastIndex, match.index); + if (beforeText) { + textBuffer += beforeText; } - result.push({ caption: match[1], url: match[2] }); + if (mediaType) { + if (textBuffer.trim()) { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false, + ); + textBuffer = ''; + } - lastIndex = regex.lastIndex; + if (mediaType === 'audio') { + await instance.audioWhatsapp({ + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + audio: url, + caption: altText, + }); + } else { + await instance.mediaMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + mediatype: mediaType, + media: url, + caption: altText, + }, + false, + ); + } + } else { + textBuffer += `[${altText}](${url})`; + } + + lastIndex = linkRegex.lastIndex; } if (lastIndex < message.length) { - result.push({ text: message.slice(lastIndex).trim() }); - } - - for (const item of result) { - if (item.text) { - await instance.textMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - text: item.text, - }, - false, - ); - } - - if (item.url) { - await instance.mediaMessage( - { - number: remoteJid.split('@')[0], - delay: settings?.delayMessage || 1000, - mediatype: 'image', - media: item.url, - caption: item.caption, - }, - false, - ); + const remainingText = message.slice(lastIndex); + if (remainingText.trim()) { + textBuffer += remainingText; } } + if (textBuffer.trim()) { + await instance.textMessage( + { + number: remoteJid.split('@')[0], + delay: settings?.delayMessage || 1000, + text: textBuffer.trim(), + }, + false, + ); + } + + sendTelemetry('/message/sendText'); + await this.prismaRepository.integrationSession.update({ where: { id: session.id, @@ -211,8 +255,6 @@ export class OpenaiService { awaitUser: true, }, }); - - sendTelemetry('/message/sendText'); } public async createAssistantNewSession(instance: InstanceDto, data: any) {