From c16f962d2b1110eadeffc9cc9fe0a3f94fb513f1 Mon Sep 17 00:00:00 2001 From: AdsonCicilioti Date: Tue, 12 Sep 2023 13:39:40 -0300 Subject: [PATCH 1/3] chore: compreensive var name for `conversation` term --- src/whatsapp/services/chatwoot.service.ts | 26 +++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/whatsapp/services/chatwoot.service.ts b/src/whatsapp/services/chatwoot.service.ts index 485e408d..1ab7d7f7 100644 --- a/src/whatsapp/services/chatwoot.service.ts +++ b/src/whatsapp/services/chatwoot.service.ts @@ -949,7 +949,7 @@ export class ChatwootService { public async receiveWebhook(instance: InstanceDto, body: any) { try { - // espera 500ms para evitar duplicidade de mensagens +// espera 500ms para evitar duplicidade de mensagens await new Promise((resolve) => setTimeout(resolve, 500)); this.logger.verbose('receive webhook to chatwoot instance: ' + instance.instanceName); @@ -1284,9 +1284,9 @@ export class ChatwootService { } this.logger.verbose('get conversation in chatwoot'); - const getConversion = await this.createConversation(instance, body); + const getConversation = await this.createConversation(instance, body); - if (!getConversion) { + if (!getConversation) { this.logger.warn('conversation not found'); return; } @@ -1337,7 +1337,7 @@ export class ChatwootService { } this.logger.verbose('send data to chatwoot'); - const send = await this.sendData(getConversion, fileName, messageType, content); + const send = await this.sendData(getConversation, fileName, messageType, content); if (!send) { this.logger.warn('message not sent'); @@ -1358,7 +1358,7 @@ export class ChatwootService { this.logger.verbose('message is not group'); this.logger.verbose('send data to chatwoot'); - const send = await this.sendData(getConversion, fileName, messageType, bodyMessage); + const send = await this.sendData(getConversation, fileName, messageType, bodyMessage); if (!send) { this.logger.warn('message not sent'); @@ -1394,7 +1394,7 @@ export class ChatwootService { } this.logger.verbose('send data to chatwoot'); - const send = await this.createMessage(instance, getConversion, content, messageType); + const send = await this.createMessage(instance, getConversation, content, messageType); if (!send) { this.logger.warn('message not sent'); @@ -1415,7 +1415,7 @@ export class ChatwootService { this.logger.verbose('message is not group'); this.logger.verbose('send data to chatwoot'); - const send = await this.createMessage(instance, getConversion, bodyMessage, messageType); + const send = await this.createMessage(instance, getConversation, bodyMessage, messageType); if (!send) { this.logger.warn('message not sent'); @@ -1452,14 +1452,14 @@ export class ChatwootService { } // if (event === 'connection.update') { - // this.logger.verbose('event connection.update'); + // this.logger.verbose('event connection.update'); - // if (body.status === 'open') { - // const msgConnection = `🚀 Connection successfully established!`; + // if (body.status === 'open') { + // const msgConnection = `🚀 Connection successfully established!`; - // this.logger.verbose('send message to chatwoot'); - // await this.createBotMessage(instance, msgConnection, 'incoming'); - // } + // this.logger.verbose('send message to chatwoot'); + // await this.createBotMessage(instance, msgConnection, 'incoming'); + // } // } if (event === 'qrcode.updated') { From ccd90a69eea9e98914ba0f230846638f0b7f3719 Mon Sep 17 00:00:00 2001 From: AdsonCicilioti Date: Tue, 12 Sep 2023 13:43:17 -0300 Subject: [PATCH 2/3] add: initial support for preview and reference from messages with Ads metadata --- src/whatsapp/services/chatwoot.service.ts | 74 +++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/whatsapp/services/chatwoot.service.ts b/src/whatsapp/services/chatwoot.service.ts index 1ab7d7f7..0ef8f324 100644 --- a/src/whatsapp/services/chatwoot.service.ts +++ b/src/whatsapp/services/chatwoot.service.ts @@ -1125,6 +1125,20 @@ export class ChatwootService { return result; } + private getAdsMessage(msg: any) { + interface AdsMessage { + title: string; + body: string; + thumbnailUrl: string; + sourceUrl: string; + } + let adsMessage: AdsMessage | undefined = msg.extendedTextMessage?.contextInfo.externalAdReply; + + this.logger.verbose('Get ads message if it exist'); + adsMessage && this.logger.verbose('Ads message: ' + adsMessage); + return adsMessage; + } + private getTypeMessage(msg: any) { this.logger.verbose('get type message'); @@ -1278,6 +1292,8 @@ export class ChatwootService { const isMedia = this.isMediaMessage(body.message); + const adsMessage = this.getAdsMessage(body.message); + if (!bodyMessage && !isMedia) { this.logger.warn('no body message found'); return; @@ -1378,6 +1394,64 @@ export class ChatwootService { } } + this.logger.verbose('check if has Ads Message'); + if (adsMessage) { + this.logger.verbose('message is from Ads'); + + this.logger.verbose('get base64 from media ads message'); + const getBase64AdMsg = await axios.get(adsMessage.thumbnailUrl, { responseType: 'arraybuffer' }); + const base64 = getBase64AdMsg.data.toString('base64'); + + const contentType = getBase64AdMsg.headers['content-type']; + const extension = mimeTypes.extension(contentType); + const mimeType = extension && mimeTypes.lookup(extension); + + if (!mimeType) { + this.logger.warn('mimetype of Ads message not found'); + return; + } + + const random = Math.random().toString(36).substring(7); + const nameFile = `${random}.${mimeTypes.extension(mimeType)}`; + const fileData = Buffer.from(base64, 'base64'); + const fileName = `${path.join(waInstance?.storePath, 'temp', `${nameFile}`)}`; + + this.logger.verbose('temp file name: ' + nameFile); + + this.logger.verbose('create temp file'); + writeFileSync(fileName, fileData, 'utf8'); + const truncStr = (str: string, len: number) => { + return str.length > len ? str.substring(0, len) + '...' : str; + }; + + const title = truncStr(adsMessage.title, 40); + const description = truncStr(adsMessage.body, 75); + + this.logger.verbose('send data to chatwoot'); + const send = await this.sendData( + getConversation, + fileName, + messageType, + `${bodyMessage}\n\n\n**${title}**\n${description}\n${adsMessage.sourceUrl}`, + ); + + if (!send) { + this.logger.warn('message not sent'); + return; + } + + this.messageCacheFile = path.join(ROOT_DIR, 'store', 'chatwoot', `${instance.instanceName}_cache.txt`); + + this.messageCache = this.loadMessageCache(); + + this.messageCache.add(send.id.toString()); + + this.logger.verbose('save message cache'); + this.saveMessageCache(); + + return send; + } + this.logger.verbose('check if is group'); if (body.key.remoteJid.includes('@g.us')) { this.logger.verbose('message is group'); From cfdca38d59088163260763981d1773b8b46694c5 Mon Sep 17 00:00:00 2001 From: AdsonCicilioti Date: Wed, 13 Sep 2023 00:04:02 -0300 Subject: [PATCH 3/3] add: fixed crop (cover) ads imge thumbnail with Jimp library --- src/whatsapp/services/chatwoot.service.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/whatsapp/services/chatwoot.service.ts b/src/whatsapp/services/chatwoot.service.ts index 0ef8f324..d1314fe7 100644 --- a/src/whatsapp/services/chatwoot.service.ts +++ b/src/whatsapp/services/chatwoot.service.ts @@ -2,6 +2,7 @@ import ChatwootClient from '@figuro/chatwoot-sdk'; import axios from 'axios'; import FormData from 'form-data'; import { createReadStream, readFileSync, unlinkSync, writeFileSync } from 'fs'; +import Jimp from 'jimp'; import mimeTypes from 'mime-types'; import path from 'path'; @@ -1399,11 +1400,9 @@ export class ChatwootService { this.logger.verbose('message is from Ads'); this.logger.verbose('get base64 from media ads message'); - const getBase64AdMsg = await axios.get(adsMessage.thumbnailUrl, { responseType: 'arraybuffer' }); - const base64 = getBase64AdMsg.data.toString('base64'); + const imgBuffer = await axios.get(adsMessage.thumbnailUrl, { responseType: 'arraybuffer' }); - const contentType = getBase64AdMsg.headers['content-type']; - const extension = mimeTypes.extension(contentType); + const extension = mimeTypes.extension(imgBuffer.headers['content-type']); const mimeType = extension && mimeTypes.lookup(extension); if (!mimeType) { @@ -1413,13 +1412,18 @@ export class ChatwootService { const random = Math.random().toString(36).substring(7); const nameFile = `${random}.${mimeTypes.extension(mimeType)}`; - const fileData = Buffer.from(base64, 'base64'); + const fileData = Buffer.from(imgBuffer.data, 'binary'); const fileName = `${path.join(waInstance?.storePath, 'temp', `${nameFile}`)}`; this.logger.verbose('temp file name: ' + nameFile); - this.logger.verbose('create temp file'); - writeFileSync(fileName, fileData, 'utf8'); + await Jimp.read(fileData) + .then(async (img) => { + await img.cover(320, 180).writeAsync(fileName); + }) + .catch((err) => { + this.logger.error(`image is not write: ${err}`); + }); const truncStr = (str: string, len: number) => { return str.length > len ? str.substring(0, len) + '...' : str; };