diff --git a/CHANGELOG.md b/CHANGELOG.md index 05f1eec4..c2203bbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ * Fix chatwoot reply quote with Cloud API * Use exchange name from .env on RabbitMQ * Fixed chatwoot screen +* It is now possible to send images via the Evolution Channel # 2.1.0 (2024-08-26 15:33) diff --git a/src/api/integrations/channel/evolution/evolution.channel.service.ts b/src/api/integrations/channel/evolution/evolution.channel.service.ts index 35383ff8..4c278668 100644 --- a/src/api/integrations/channel/evolution/evolution.channel.service.ts +++ b/src/api/integrations/channel/evolution/evolution.channel.service.ts @@ -1,4 +1,4 @@ -import { Options, SendAudioDto, SendMediaDto, SendTextDto } from '@api/dto/sendMessage.dto'; +import { MediaMessage, Options, SendAudioDto, SendMediaDto, SendTextDto } from '@api/dto/sendMessage.dto'; import { ProviderFiles } from '@api/provider/sessions'; import { PrismaRepository } from '@api/repository/repository.service'; import { chatbotController } from '@api/server.module'; @@ -7,7 +7,9 @@ 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 { isURL } from 'class-validator'; import EventEmitter2 from 'eventemitter2'; +import mime from 'mime'; import { v4 } from 'uuid'; export class EvolutionStartupService extends ChannelStartupService { @@ -195,7 +197,7 @@ export class EvolutionStartupService extends ChannelStartupService { } await this.prismaRepository.contact.updateMany({ - where: { remoteJid: contact.remoteJid }, + where: { remoteJid: contact.remoteJid, instanceId: this.instanceId }, data: contactRaw, }); return; @@ -271,18 +273,74 @@ export class EvolutionStartupService extends ChannelStartupService { const messageId = v4(); - const messageRaw: any = { - key: { fromMe: true, id: messageId, remoteJid: number }, - message: { - ...message, - quoted, - }, - messageType: 'conversation', - messageTimestamp: Math.round(new Date().getTime() / 1000), - webhookUrl, - source: 'unknown', - instanceId: this.instanceId, - }; + let messageRaw: any; + + if (message?.mediaType === 'image') { + messageRaw = { + key: { fromMe: true, id: messageId, remoteJid: number }, + 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 }, + 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 }, + 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 }, + 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 }, + message: { + ...message, + quoted, + }, + messageType: 'conversation', + messageTimestamp: Math.round(new Date().getTime() / 1000), + webhookUrl, + source: 'unknown', + instanceId: this.instanceId, + }; + } this.logger.log(messageRaw); @@ -334,9 +392,51 @@ export class EvolutionStartupService extends ChannelStartupService { return res; } - public async mediaMessage(data: SendMediaDto, isIntegration = false) { - const message = data; + protected async prepareMediaMessage(mediaMessage: MediaMessage) { + try { + if (mediaMessage.mediatype === 'document' && !mediaMessage.fileName) { + const regex = new RegExp(/.*\/(.+?)\./); + const arrayMatch = regex.exec(mediaMessage.media); + mediaMessage.fileName = arrayMatch[1]; + } + if (mediaMessage.mediatype === 'image' && !mediaMessage.fileName) { + mediaMessage.fileName = 'image.png'; + } + + if (mediaMessage.mediatype === 'video' && !mediaMessage.fileName) { + mediaMessage.fileName = 'video.mp4'; + } + + let mimetype: string; + + const prepareMedia: any = { + caption: mediaMessage?.caption, + fileName: mediaMessage.fileName, + mediaType: mediaMessage.mediatype, + media: mediaMessage.media, + gifPlayback: false, + }; + + if (isURL(mediaMessage.media)) { + mimetype = mime.getType(mediaMessage.media); + } else { + mimetype = mime.getType(mediaMessage.fileName); + } + + prepareMedia.mimetype = mimetype; + + return prepareMedia; + } catch (error) { + this.logger.error(error); + throw new InternalServerErrorException(error?.toString() || error); + } + } + + public async mediaMessage(data: SendMediaDto, isIntegration = false) { + const message = await this.prepareMediaMessage(data); + + console.log('message', message); return await this.sendMessageWithTyping( data.number, { ...message }, @@ -352,8 +452,31 @@ export class EvolutionStartupService extends ChannelStartupService { ); } + public async processAudio(audio: string, number: string) { + number = number.replace(/\D/g, ''); + const hash = `${number}-${new Date().getTime()}`; + + let mimetype: string; + + const prepareMedia: any = { + fileName: `${hash}.mp4`, + mediaType: 'audio', + media: audio, + }; + + if (isURL(audio)) { + mimetype = mime.getType(audio); + } else { + mimetype = mime.getType(prepareMedia.fileName); + } + + prepareMedia.mimetype = mimetype; + + return prepareMedia; + } + public async audioWhatsapp(data: SendAudioDto, isIntegration = false) { - const message = data; + const message = await this.processAudio(data.audio, data.number); return await this.sendMessageWithTyping( data.number, diff --git a/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts b/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts index 8e20b93c..67e1099b 100644 --- a/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts +++ b/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts @@ -635,7 +635,7 @@ export class ChatwootService { } } } else { - const jid = isGroup ? null : body.key.remoteJid; + const jid = body.key.remoteJid; contact = await this.createContact( instance, chatId,