From 83567d64669ac7ca9c0e9a2930511484a49356b3 Mon Sep 17 00:00:00 2001 From: nestordavalos Date: Sat, 5 Oct 2024 22:49:30 -0400 Subject: [PATCH 1/7] fix: Corrected audio file handling in WhatsApp An error in the WhatsApp audio message handler has been fixed. The system now checks if the file has a valid buffer before sending it. Additionally, validation has been added to verify if the audio is a valid URL or Base64. If these conditions are not met, an error message is shown, and a BadRequestException is thrown. --- src/api/controllers/sendMessage.controller.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/api/controllers/sendMessage.controller.ts b/src/api/controllers/sendMessage.controller.ts index 0d6ea33e..6f60ceb9 100644 --- a/src/api/controllers/sendMessage.controller.ts +++ b/src/api/controllers/sendMessage.controller.ts @@ -47,11 +47,14 @@ export class SendMessageController { } public async sendWhatsAppAudio({ instanceName }: InstanceDto, data: SendAudioDto, file?: any) { - if (file || isURL(data.audio) || isBase64(data.audio)) { - return await this.waMonitor.waInstances[instanceName].audioWhatsapp(data, file); + if (file?.buffer || isURL(data.audio) || isBase64(data.audio)) { + // Si file existe y tiene buffer, o si es una URL o Base64, continúa + return await this.waMonitor.waInstances[instanceName].audioWhatsapp(data, file); + } else { + console.error('El archivo no tiene buffer o el audio no es una URL o Base64 válida'); + throw new BadRequestException('Owned media must be a url, base64, or valid file with buffer'); } - throw new BadRequestException('Owned media must be a url or base64'); - } +} public async sendButtons({ instanceName }: InstanceDto, data: SendButtonDto) { return await this.waMonitor.waInstances[instanceName].buttonMessage(data); From 59af93251d6f2759a9bfadbf446a9073d0ab7907 Mon Sep 17 00:00:00 2001 From: nestordavalos Date: Sun, 6 Oct 2024 01:16:08 -0300 Subject: [PATCH 2/7] fix: Corregir manejo de archivo de audio en WhatsApp --- .../evolution/evolution.channel.service.ts | 7 ++- .../channel/meta/whatsapp.business.service.ts | 8 ++- .../whatsapp/whatsapp.baileys.service.ts | 57 ++++++++++--------- 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/api/integrations/channel/evolution/evolution.channel.service.ts b/src/api/integrations/channel/evolution/evolution.channel.service.ts index 28d73d7f..b4020509 100644 --- a/src/api/integrations/channel/evolution/evolution.channel.service.ts +++ b/src/api/integrations/channel/evolution/evolution.channel.service.ts @@ -483,7 +483,12 @@ export class EvolutionStartupService extends ChannelStartupService { public async audioWhatsapp(data: SendAudioDto, file?: any, isIntegration = false) { const mediaData: SendAudioDto = { ...data }; - if (file) mediaData.audio = file.buffer.toString('base64'); + if (file?.buffer) { + mediaData.audio = file.buffer.toString('base64'); + } else { + console.error("El archivo o buffer no está definido correctamente."); + throw new Error("File or buffer is undefined."); + } const message = await this.processAudio(mediaData.audio, data.number); diff --git a/src/api/integrations/channel/meta/whatsapp.business.service.ts b/src/api/integrations/channel/meta/whatsapp.business.service.ts index f3bccdfd..934b59a3 100644 --- a/src/api/integrations/channel/meta/whatsapp.business.service.ts +++ b/src/api/integrations/channel/meta/whatsapp.business.service.ts @@ -1081,7 +1081,13 @@ export class BusinessStartupService extends ChannelStartupService { public async audioWhatsapp(data: SendAudioDto, file?: any, isIntegration = false) { const mediaData: SendAudioDto = { ...data }; - if (file) mediaData.audio = file.buffer.toString('base64'); + if (file?.buffer) { + // Asegurarse de que file y buffer existen antes de usarlos + mediaData.audio = file.buffer.toString('base64'); + } else { + console.error('El archivo no tiene buffer o file es undefined'); + throw new Error('File or buffer is undefined'); + } const message = await this.processAudio(mediaData.audio, data.number); diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 79167858..944a234f 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -2574,42 +2574,47 @@ export class BaileysStartupService extends ChannelStartupService { public async audioWhatsapp(data: SendAudioDto, file?: any, isIntegration = false) { const mediaData: SendAudioDto = { ...data }; - if (file) mediaData.audio = file.buffer.toString('base64'); + if (file?.buffer) { + mediaData.audio = file.buffer.toString('base64'); + } else if (!isURL(data.audio) && !isBase64(data.audio)) { + console.error('Invalid file or audio source'); + throw new BadRequestException('File buffer, URL, or base64 audio is required'); + } if (!data?.encoding && data?.encoding !== false) { - data.encoding = true; + data.encoding = true; } if (data?.encoding) { - const convert = await this.processAudio(mediaData.audio); + const convert = await this.processAudio(mediaData.audio); - if (Buffer.isBuffer(convert)) { - const result = this.sendMessageWithTyping( - data.number, - { - audio: convert, - ptt: true, - mimetype: 'audio/ogg; codecs=opus', - }, - { presence: 'recording', delay: data?.delay }, - isIntegration, - ); + if (Buffer.isBuffer(convert)) { + const result = this.sendMessageWithTyping( + data.number, + { + audio: convert, + ptt: true, + mimetype: 'audio/ogg; codecs=opus', + }, + { presence: 'recording', delay: data?.delay }, + isIntegration, + ); - return result; - } else { - throw new InternalServerErrorException('Failed to convert audio'); - } + return result; + } else { + throw new InternalServerErrorException('Failed to convert audio'); + } } return await this.sendMessageWithTyping( - data.number, - { - audio: isURL(data.audio) ? { url: data.audio } : Buffer.from(data.audio, 'base64'), - ptt: true, - mimetype: 'audio/ogg; codecs=opus', - }, - { presence: 'recording', delay: data?.delay }, - isIntegration, + data.number, + { + audio: isURL(data.audio) ? { url: data.audio } : Buffer.from(data.audio, 'base64'), + ptt: true, + mimetype: 'audio/ogg; codecs=opus', + }, + { presence: 'recording', delay: data?.delay }, + isIntegration, ); } From 1f6473cfd59f2e30b0afdbcec981b2f97571143d Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Sun, 6 Oct 2024 09:47:42 -0300 Subject: [PATCH 3/7] version: 2.1.2 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 296673ec..2ecc2c99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 2.1.2 (develop) +# 2.1.2 (2024-10-06 09:47) ### Features From 0f7c2437bc1939bf4ab07d169088227967d68ad3 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Sun, 6 Oct 2024 09:58:57 -0300 Subject: [PATCH 4/7] fix: status on send message --- CHANGELOG.md | 2 +- .../evolution/evolution.channel.service.ts | 46 +++++-------- .../channel/meta/whatsapp.business.service.ts | 10 +-- .../whatsapp/whatsapp.baileys.service.ts | 68 ++++++++----------- src/utils/renderStatus.ts | 10 +++ 5 files changed, 63 insertions(+), 73 deletions(-) create mode 100644 src/utils/renderStatus.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ecc2c99..296673ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 2.1.2 (2024-10-06 09:47) +# 2.1.2 (develop) ### Features diff --git a/src/api/integrations/channel/evolution/evolution.channel.service.ts b/src/api/integrations/channel/evolution/evolution.channel.service.ts index b4020509..91e232a3 100644 --- a/src/api/integrations/channel/evolution/evolution.channel.service.ts +++ b/src/api/integrations/channel/evolution/evolution.channel.service.ts @@ -7,6 +7,7 @@ import { ChannelStartupService } from '@api/services/channel.service'; import { Events, wa } from '@api/types/wa.types'; import { Chatwoot, ConfigService, Openai } from '@config/env.config'; import { BadRequestException, InternalServerErrorException } from '@exceptions'; +import { status } from '@utils/renderStatus'; import { isURL } from 'class-validator'; import EventEmitter2 from 'eventemitter2'; import mime from 'mime'; @@ -273,72 +274,59 @@ export class EvolutionStartupService extends ChannelStartupService { const messageId = v4(); - let messageRaw: any; + let messageRaw: any = { + key: { fromMe: true, id: messageId, remoteJid: number }, + messageTimestamp: Math.round(new Date().getTime() / 1000), + webhookUrl, + source: 'unknown', + instanceId: this.instanceId, + status: status[1], + }; if (message?.mediaType === 'image') { messageRaw = { - key: { fromMe: true, id: messageId, remoteJid: number }, + ...messageRaw, message: { mediaUrl: message.media, quoted, }, messageType: 'imageMessage', - messageTimestamp: Math.round(new Date().getTime() / 1000), - webhookUrl, - source: 'unknown', - instanceId: this.instanceId, }; } else if (message?.mediaType === 'video') { messageRaw = { - key: { fromMe: true, id: messageId, remoteJid: number }, + ...messageRaw, message: { mediaUrl: message.media, quoted, }, messageType: 'videoMessage', - messageTimestamp: Math.round(new Date().getTime() / 1000), - webhookUrl, - source: 'unknown', - instanceId: this.instanceId, }; } else if (message?.mediaType === 'audio') { messageRaw = { - key: { fromMe: true, id: messageId, remoteJid: number }, + ...messageRaw, message: { mediaUrl: message.media, quoted, }, messageType: 'audioMessage', - messageTimestamp: Math.round(new Date().getTime() / 1000), - webhookUrl, - source: 'unknown', - instanceId: this.instanceId, }; } else if (message?.mediaType === 'document') { messageRaw = { - key: { fromMe: true, id: messageId, remoteJid: number }, + ...messageRaw, message: { mediaUrl: message.media, quoted, }, messageType: 'documentMessage', - messageTimestamp: Math.round(new Date().getTime() / 1000), - webhookUrl, - source: 'unknown', - instanceId: this.instanceId, }; } else { messageRaw = { - key: { fromMe: true, id: messageId, remoteJid: number }, + ...messageRaw, message: { ...message, quoted, }, messageType: 'conversation', - messageTimestamp: Math.round(new Date().getTime() / 1000), - webhookUrl, - source: 'unknown', - instanceId: this.instanceId, }; } @@ -484,10 +472,10 @@ export class EvolutionStartupService extends ChannelStartupService { const mediaData: SendAudioDto = { ...data }; if (file?.buffer) { - mediaData.audio = file.buffer.toString('base64'); + mediaData.audio = file.buffer.toString('base64'); } else { - console.error("El archivo o buffer no está definido correctamente."); - throw new Error("File or buffer is undefined."); + console.error('El archivo o buffer no est� definido correctamente.'); + throw new Error('File or buffer is undefined.'); } const message = await this.processAudio(mediaData.audio, data.number); diff --git a/src/api/integrations/channel/meta/whatsapp.business.service.ts b/src/api/integrations/channel/meta/whatsapp.business.service.ts index 934b59a3..57cc5e4a 100644 --- a/src/api/integrations/channel/meta/whatsapp.business.service.ts +++ b/src/api/integrations/channel/meta/whatsapp.business.service.ts @@ -22,6 +22,7 @@ import { ChannelStartupService } from '@api/services/channel.service'; import { Events, wa } from '@api/types/wa.types'; import { Chatwoot, ConfigService, Database, Openai, S3, WaBusiness } from '@config/env.config'; import { BadRequestException, InternalServerErrorException } from '@exceptions'; +import { status } from '@utils/renderStatus'; import axios from 'axios'; import { arrayUnique, isURL } from 'class-validator'; import EventEmitter2 from 'eventemitter2'; @@ -895,12 +896,12 @@ export class BusinessStartupService extends ChannelStartupService { const messageRaw: any = { key: { fromMe: true, id: messageSent?.messages[0]?.id, remoteJid: this.createJid(number) }, - //pushName: messageSent.pushName, message: this.convertMessageToRaw(message, content), messageType: this.renderMessageType(content.type), messageTimestamp: (messageSent?.messages[0]?.timestamp as number) || Math.round(new Date().getTime() / 1000), instanceId: this.instanceId, webhookUrl, + status: status[1], source: 'unknown', }; @@ -1082,11 +1083,10 @@ export class BusinessStartupService extends ChannelStartupService { const mediaData: SendAudioDto = { ...data }; if (file?.buffer) { - // Asegurarse de que file y buffer existen antes de usarlos - mediaData.audio = file.buffer.toString('base64'); + mediaData.audio = file.buffer.toString('base64'); } else { - console.error('El archivo no tiene buffer o file es undefined'); - throw new Error('File or buffer is undefined'); + console.error('El archivo no tiene buffer o file es undefined'); + throw new Error('File or buffer is undefined'); } const message = await this.processAudio(mediaData.audio, data.number); diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 944a234f..1da37deb 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -72,6 +72,7 @@ import { Boom } from '@hapi/boom'; import { Instance } from '@prisma/client'; import { makeProxyAgent } from '@utils/makeProxyAgent'; import { getOnWhatsappCache, saveOnWhatsappCache } from '@utils/onWhatsappCache'; +import { status } from '@utils/renderStatus'; import useMultiFileAuthStatePrisma from '@utils/use-multi-file-auth-state-prisma'; import { AuthStateProvider } from '@utils/use-multi-file-auth-state-provider-files'; import { useMultiFileAuthStateRedisDb } from '@utils/use-multi-file-auth-state-redis-db'; @@ -569,7 +570,6 @@ export class BaileysStartupService extends ChannelStartupService { const isGroupJid = this.localSettings.groupsIgnore && isJidGroup(jid); const isBroadcast = !this.localSettings.readStatus && isJidBroadcast(jid); const isNewsletter = isJidNewsletter(jid); - // const isNewsletter = jid && jid.includes('newsletter'); return isGroupJid || isBroadcast || isNewsletter; }, @@ -1230,14 +1230,6 @@ export class BaileysStartupService extends ChannelStartupService { }, 'messages.update': async (args: WAMessageUpdate[], settings: any) => { - const status: Record = { - 0: 'ERROR', - 1: 'PENDING', - 2: 'SERVER_ACK', - 3: 'DELIVERY_ACK', - 4: 'READ', - 5: 'PLAYED', - }; for await (const { key, update } of args) { if (settings?.groupsIgnore && key.remoteJid?.includes('@g.us')) { return; @@ -2575,46 +2567,46 @@ export class BaileysStartupService extends ChannelStartupService { const mediaData: SendAudioDto = { ...data }; if (file?.buffer) { - mediaData.audio = file.buffer.toString('base64'); + mediaData.audio = file.buffer.toString('base64'); } else if (!isURL(data.audio) && !isBase64(data.audio)) { - console.error('Invalid file or audio source'); - throw new BadRequestException('File buffer, URL, or base64 audio is required'); + console.error('Invalid file or audio source'); + throw new BadRequestException('File buffer, URL, or base64 audio is required'); } if (!data?.encoding && data?.encoding !== false) { - data.encoding = true; + data.encoding = true; } if (data?.encoding) { - const convert = await this.processAudio(mediaData.audio); + const convert = await this.processAudio(mediaData.audio); - if (Buffer.isBuffer(convert)) { - const result = this.sendMessageWithTyping( - data.number, - { - audio: convert, - ptt: true, - mimetype: 'audio/ogg; codecs=opus', - }, - { presence: 'recording', delay: data?.delay }, - isIntegration, - ); + if (Buffer.isBuffer(convert)) { + const result = this.sendMessageWithTyping( + data.number, + { + audio: convert, + ptt: true, + mimetype: 'audio/ogg; codecs=opus', + }, + { presence: 'recording', delay: data?.delay }, + isIntegration, + ); - return result; - } else { - throw new InternalServerErrorException('Failed to convert audio'); - } + return result; + } else { + throw new InternalServerErrorException('Failed to convert audio'); + } } return await this.sendMessageWithTyping( - data.number, - { - audio: isURL(data.audio) ? { url: data.audio } : Buffer.from(data.audio, 'base64'), - ptt: true, - mimetype: 'audio/ogg; codecs=opus', - }, - { presence: 'recording', delay: data?.delay }, - isIntegration, + data.number, + { + audio: isURL(data.audio) ? { url: data.audio } : Buffer.from(data.audio, 'base64'), + ptt: true, + mimetype: 'audio/ogg; codecs=opus', + }, + { presence: 'recording', delay: data?.delay }, + isIntegration, ); } @@ -3659,7 +3651,7 @@ export class BaileysStartupService extends ChannelStartupService { const messageRaw = { key: message.key, pushName: message.pushName, - status: message.status, + status: status[message.status], message: { ...message.message }, contextInfo: contentMsg?.contextInfo, messageType: contentType || 'unknown', diff --git a/src/utils/renderStatus.ts b/src/utils/renderStatus.ts new file mode 100644 index 00000000..e57b1224 --- /dev/null +++ b/src/utils/renderStatus.ts @@ -0,0 +1,10 @@ +import { wa } from '@api/types/wa.types'; + +export const status: Record = { + 0: 'ERROR', + 1: 'PENDING', + 2: 'SERVER_ACK', + 3: 'DELIVERY_ACK', + 4: 'READ', + 5: 'PLAYED', +}; From c823f84c7029c981487e478f020b6374bd2c334e Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Sun, 6 Oct 2024 10:04:02 -0300 Subject: [PATCH 5/7] fix: status on send message --- prisma/mysql-schema.prisma | 2 +- .../20241006130306_alter_status_on_message_table/migration.sql | 2 ++ prisma/postgresql-schema.prisma | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 prisma/postgresql-migrations/20241006130306_alter_status_on_message_table/migration.sql diff --git a/prisma/mysql-schema.prisma b/prisma/mysql-schema.prisma index 2576b04f..cfa9d735 100644 --- a/prisma/mysql-schema.prisma +++ b/prisma/mysql-schema.prisma @@ -159,7 +159,7 @@ model Message { MessageUpdate MessageUpdate[] Media Media? webhookUrl String? @db.VarChar(500) - status Int? @db.Int + status String? @db.VarChar(30) sessionId String? session IntegrationSession? @relation(fields: [sessionId], references: [id]) diff --git a/prisma/postgresql-migrations/20241006130306_alter_status_on_message_table/migration.sql b/prisma/postgresql-migrations/20241006130306_alter_status_on_message_table/migration.sql new file mode 100644 index 00000000..ac923c98 --- /dev/null +++ b/prisma/postgresql-migrations/20241006130306_alter_status_on_message_table/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Message" ALTER COLUMN "status" SET DATA TYPE VARCHAR(30); diff --git a/prisma/postgresql-schema.prisma b/prisma/postgresql-schema.prisma index 4f061adb..857c4426 100644 --- a/prisma/postgresql-schema.prisma +++ b/prisma/postgresql-schema.prisma @@ -158,7 +158,7 @@ model Message { MessageUpdate MessageUpdate[] Media Media? webhookUrl String? @db.VarChar(500) - status Int? @db.Integer + status String? @db.VarChar(30) sessionId String? session IntegrationSession? @relation(fields: [sessionId], references: [id]) From ebbba7b7e92f7d1e7726b2d0a5517e4a7bff4b5c Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Sun, 6 Oct 2024 10:10:00 -0300 Subject: [PATCH 6/7] version: 2.1.2 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 296673ec..6b780e70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 2.1.2 (develop) +# 2.1.2 (2024-10-06 10:09) ### Features From 29a1d99d05edc6f86dad672edafdb1d42e26bd3b Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Sun, 6 Oct 2024 20:05:14 -0300 Subject: [PATCH 7/7] fix: Fixed prefilledVariables in startTypebot --- CHANGELOG.md | 6 ++++++ .../chatbot/typebot/controllers/typebot.controller.ts | 11 +++-------- .../chatbot/typebot/services/typebot.service.ts | 3 +++ 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b780e70..5976b8f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 2.1.3 (develop) + +### Fixed + +* Fixed prefilledVariables in startTypebot + # 2.1.2 (2024-10-06 10:09) ### Features diff --git a/src/api/integrations/chatbot/typebot/controllers/typebot.controller.ts b/src/api/integrations/chatbot/typebot/controllers/typebot.controller.ts index 1f03197f..e0818a68 100644 --- a/src/api/integrations/chatbot/typebot/controllers/typebot.controller.ts +++ b/src/api/integrations/chatbot/typebot/controllers/typebot.controller.ts @@ -5,7 +5,7 @@ import { TypebotService } from '@api/integrations/chatbot/typebot/services/typeb import { PrismaRepository } from '@api/repository/repository.service'; import { WAMonitoringService } from '@api/services/monitor.service'; import { Events } from '@api/types/wa.types'; -import { Auth, configService, HttpServer, Typebot } from '@config/env.config'; +import { configService, Typebot } from '@config/env.config'; import { Logger } from '@config/logger.config'; import { BadRequestException } from '@exceptions'; import { Typebot as TypebotModel } from '@prisma/client'; @@ -609,13 +609,7 @@ export class TypebotController extends ChatbotController implements ChatbotContr } } - const prefilledVariables = { - remoteJid: remoteJid, - instanceName: instance.instanceName, - serverUrl: configService.get('SERVER').URL, - apiKey: configService.get('AUTHENTICATION').API_KEY.KEY, - ownerJid: instanceData.number, - }; + const prefilledVariables: any = {}; if (variables?.length) { variables.forEach((variable: { name: string | number; value: string }) => { @@ -674,6 +668,7 @@ export class TypebotController extends ChatbotController implements ChatbotContr stopBotFromMe, keepOpen, 'init', + prefilledVariables, ); // const response = await this.typebotService.createNewSession(instanceData, { diff --git a/src/api/integrations/chatbot/typebot/services/typebot.service.ts b/src/api/integrations/chatbot/typebot/services/typebot.service.ts index b6de1b8d..2f30e091 100644 --- a/src/api/integrations/chatbot/typebot/services/typebot.service.ts +++ b/src/api/integrations/chatbot/typebot/services/typebot.service.ts @@ -356,6 +356,7 @@ export class TypebotService { stopBotFromMe: boolean, keepOpen: boolean, content: string, + prefilledVariables?: any, ) { if (session && expire && expire > 0) { const now = Date.now(); @@ -397,6 +398,7 @@ export class TypebotService { remoteJid: remoteJid, pushName: msg.pushName, botId: findTypebot.id, + prefilledVariables: prefilledVariables, }); if (data.session) { @@ -524,6 +526,7 @@ export class TypebotService { remoteJid: remoteJid, pushName: msg?.pushName, botId: findTypebot.id, + prefilledVariables: prefilledVariables, }); if (data?.session) {