diff --git a/src/whatsapp/controllers/chat.controller.ts b/src/whatsapp/controllers/chat.controller.ts index 1c16260d..10c2c8e7 100644 --- a/src/whatsapp/controllers/chat.controller.ts +++ b/src/whatsapp/controllers/chat.controller.ts @@ -4,6 +4,7 @@ import { BlockUserDto, DeleteMessage, getBase64FromMediaMessageDto, + downloadMediaMessageDto, NumberDto, PrivacySettingDto, ProfileNameDto, @@ -65,6 +66,11 @@ export class ChatController { return await this.waMonitor.waInstances[instanceName].getBase64FromMediaMessage(data); } + public async downloadMediaMessage({ instanceName }: InstanceDto, data: downloadMediaMessageDto) { + logger.verbose('requested getBase64FromMediaMessage from ' + instanceName + ' instance'); + return await this.waMonitor.waInstances[instanceName].downloadMediaMessage(data); + } + public async fetchMessages({ instanceName }: InstanceDto, query: MessageQuery) { logger.verbose('requested fetchMessages from ' + instanceName + ' instance'); return await this.waMonitor.waInstances[instanceName].fetchMessages(query); diff --git a/src/whatsapp/dto/chat.dto.ts b/src/whatsapp/dto/chat.dto.ts index 24f04847..0719446c 100644 --- a/src/whatsapp/dto/chat.dto.ts +++ b/src/whatsapp/dto/chat.dto.ts @@ -14,6 +14,28 @@ export class getBase64FromMediaMessageDto { convertToMp4?: boolean; } +export class downloadMediaMessageDto { + message: message; + key: Key; + id: string; +} + +export type MediaType = 'image' | 'document' | 'video' | 'audio'; +export class message { + mediatype: MediaType; + mimetype?: string; + caption?: string; + fileName?: string; + media: string; +} + +export class key { + fromMe: boolean; + id: string; + key: string; +} + + export class WhatsAppNumberDto { numbers: string[]; } diff --git a/src/whatsapp/routers/chat.router.ts b/src/whatsapp/routers/chat.router.ts index d8096c79..b3950049 100644 --- a/src/whatsapp/routers/chat.router.ts +++ b/src/whatsapp/routers/chat.router.ts @@ -25,6 +25,7 @@ import { BlockUserDto, DeleteMessage, getBase64FromMediaMessageDto, + downloadMediaMessageDto, NumberDto, PrivacySettingDto, ProfileNameDto, @@ -184,6 +185,20 @@ export class ChatRouter extends RouterBroker { return res.status(HttpStatus.CREATED).json(response); }) + .post(this.routerPath('downloadMediaMessage'), ...guards, async (req, res) => { + logger.verbose('request received in downloadMediaMessage'); + logger.verbose('request body: '); + logger.verbose(req.body); + const response = await this.dataValidate({ + request: req, + schema: null, + ClassRef: downloadMediaMessageDto, + execute: (instance, data) => chatController.downloadMediaMessage(instance, data), + }); + return res.status(HttpStatus.CREATED).writeHead(200, + { 'Content-Type': response?.headers["content-type"] }).end(response.data); + + }) .post(this.routerPath('findMessages'), ...guards, async (req, res) => { logger.verbose('request received in findMessages'); logger.verbose('request body: '); diff --git a/src/whatsapp/services/whatsapp.baileys.service.ts b/src/whatsapp/services/whatsapp.baileys.service.ts index f99e074d..beadddb5 100644 --- a/src/whatsapp/services/whatsapp.baileys.service.ts +++ b/src/whatsapp/services/whatsapp.baileys.service.ts @@ -35,6 +35,7 @@ import makeWASocket, { WAPresence, WASocket, } from '@whiskeysockets/baileys'; +import { downloadMediaMessageDto } from '../dto/chat.dto'; import { Label } from '@whiskeysockets/baileys/lib/Types/Label'; import { LabelAssociation } from '@whiskeysockets/baileys/lib/Types/LabelAssociation'; import axios from 'axios'; @@ -2032,6 +2033,7 @@ export class BaileysStartupService extends WAStartupService { const prepareMedia = await prepareWAMessageMedia( { [mediaMessage.mediatype]: isURL(mediaMessage.media) + || fs.existsSync(mediaMessage.media) ? { url: mediaMessage.media } : Buffer.from(mediaMessage.media, 'base64'), } as any, @@ -3239,6 +3241,21 @@ export class BaileysStartupService extends WAStartupService { throw new BadRequestException('Unable to leave the group', error.toString()); } } + + public async downloadMediaMessage(msg: downloadMediaMessageDto) { + const buffer = await downloadMediaMessage( + { key: msg?.key, message: msg?.message } as any, + 'buffer', + {}, + { + logger: P({ level: 'error' }) as any, + reuploadRequest: this.client.updateMediaMessage, + }, + ); + const message = msg?.message; + const headers = { "content-type": message[Object.keys(message)[0]]?.mimetype }; + return { data: buffer, headers }; + } public async templateMessage() { throw new Error('Method not available in the Baileys service'); } diff --git a/src/whatsapp/services/whatsapp.business.service.ts b/src/whatsapp/services/whatsapp.business.service.ts index 2b4a32cf..0855106a 100644 --- a/src/whatsapp/services/whatsapp.business.service.ts +++ b/src/whatsapp/services/whatsapp.business.service.ts @@ -23,6 +23,7 @@ import { SendTemplateDto, SendTextDto, } from '../dto/sendMessage.dto'; +import {downloadMediaMessageDto} from '../dto/chat.dto'; import { ContactRaw, MessageRaw, MessageUpdateRaw, SettingsRaw } from '../models'; import { RepositoryBroker } from '../repository/repository.manager'; import { Events, wa } from '../types/wa.types'; @@ -162,18 +163,15 @@ export class BusinessStartupService extends WAStartupService { } } - private async downloadMediaMessage(message: any) { + public async downloadMediaMessage(message: downloadMediaMessageDto) { try { const integration = await this.findIntegration(); - - const id = message[message.type].id; let urlServer = this.configService.get('WA_BUSINESS').URL; const version = this.configService.get('WA_BUSINESS').VERSION; - urlServer = `${urlServer}/${version}/${id}`; + urlServer = `${urlServer}/${version}/${message.id}`; const headers = { 'Content-Type': 'application/json', Authorization: `Bearer ${integration.token}` }; let result = await axios.get(urlServer, { headers }); - result = await axios.get(result.data.url, { headers, responseType: 'arraybuffer' }); - return result.data; + return await axios.get(result.data.url, { headers, responseType: 'arraybuffer' }); } catch (e) { this.logger.error(e); } @@ -333,13 +331,14 @@ export class BusinessStartupService extends WAStartupService { received?.messages[0].audio || received?.messages[0].video ) { - const buffer = await this.downloadMediaMessage(received?.messages[0]); + const content = received?.messages[0]; + const buffer = await this.downloadMediaMessage(content[content.type].id); messageRaw = { key, pushName, message: { ...this.messageMediaJson(received), - base64: buffer ? buffer.toString('base64') : undefined, + base64: buffer ? buffer.data.toString('base64') : undefined, }, messageType: this.renderMessageType(received.messages[0].type), messageTimestamp: received.messages[0].timestamp as number, @@ -680,6 +679,7 @@ export class BusinessStartupService extends WAStartupService { message_id: message['reactionMessage']['key']['id'], emoji: message['reactionMessage']['text'], }, + context: { message_id: quoted.id }, }; quoted ? (content.context = { message_id: quoted.id }) : content; return await this.post(content, 'messages');