From 7289c3d7f9afbd3c563d4120c4f0cc78710942b5 Mon Sep 17 00:00:00 2001 From: raimartinsb Date: Thu, 31 Aug 2023 07:52:36 -0300 Subject: [PATCH 1/7] Add source_id and update message --- package.json | 2 +- src/whatsapp/models/message.model.ts | 2 + src/whatsapp/services/chatwoot.service.ts | 91 +++++++++++++++++++++-- src/whatsapp/services/whatsapp.service.ts | 1 + 4 files changed, 88 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 6f92aaf3..c28271ca 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "dependencies": { "@adiwajshing/keyed-db": "^0.2.4", "@ffmpeg-installer/ffmpeg": "^1.1.0", - "@figuro/chatwoot-sdk": "^1.1.14", + "@figuro/chatwoot-sdk": "github:raimartinsb/chatwoot-sdk", "@hapi/boom": "^10.0.1", "@sentry/node": "^7.59.2", "@whiskeysockets/baileys": "github:EvolutionAPI/Baileys", diff --git a/src/whatsapp/models/message.model.ts b/src/whatsapp/models/message.model.ts index a5790be7..252cd6e4 100644 --- a/src/whatsapp/models/message.model.ts +++ b/src/whatsapp/models/message.model.ts @@ -20,6 +20,8 @@ export class MessageRaw { messageTimestamp?: number | Long.Long; owner: string; source?: 'android' | 'web' | 'ios'; + source_id?: string; + source_reply_id?: string; } const messageSchema = new Schema({ diff --git a/src/whatsapp/services/chatwoot.service.ts b/src/whatsapp/services/chatwoot.service.ts index 4dc9215c..b489a2c6 100644 --- a/src/whatsapp/services/chatwoot.service.ts +++ b/src/whatsapp/services/chatwoot.service.ts @@ -608,6 +608,8 @@ export class ChatwootService { conversationId: number, content: string, messageType: 'incoming' | 'outgoing' | undefined, + source_id?: string, + source_reply_id?: string, privateMessage?: boolean, attachments?: { content: unknown; @@ -633,6 +635,8 @@ export class ChatwootService { message_type: messageType, attachments: attachments, private: privateMessage || false, + source_id: source_id, + source_reply_id: source_reply_id, }, }); @@ -909,10 +913,10 @@ export class ChatwootService { }, }; - await waInstance?.audioWhatsapp(data); + const audioWhatsapp = await waInstance?.audioWhatsapp(data); this.logger.verbose('audio sent'); - return; + return audioWhatsapp; } this.logger.verbose('send media to instance: ' + waInstance.instanceName); @@ -934,10 +938,10 @@ export class ChatwootService { data.mediaMessage.caption = caption; } - await waInstance?.mediaMessage(data); + const mediaMessage = await waInstance?.mediaMessage(data); this.logger.verbose('media sent'); - return; + return mediaMessage; } catch (error) { this.logger.error(error); } @@ -1067,7 +1071,18 @@ export class ChatwootService { }, }; - await waInstance?.textMessage(data); + const message = await waInstance?.textMessage(data); + const conversationId = body?.conversation?.id; + const messageId = body?.id; + const dataUpdated = { + source_id: message.key.id, + }; + await client.messages.update({ + accountId: this.provider.account_id, + conversationId, + data: dataUpdated, + messageId, + }); } } } @@ -1142,6 +1157,38 @@ export class ChatwootService { return types; } + private getContextIdTypeMessage(msg: any) { + this.logger.verbose('get type message'); + + const types = { + conversation: msg.conversation?.contextInfo?.stanzaId, + imageMessage: msg.imageMessage?.contextInfo?.stanzaId, + videoMessage: msg.videoMessage?.contextInfo?.stanzaId, + extendedTextMessage: msg.extendedTextMessage?.contextInfo?.stanzaId, + messageContextInfo: msg.messageContextInfo?.stanzaId, + stickerMessage: undefined, + documentMessage: msg.documentMessage?.contextInfo?.stanzaId, + documentWithCaptionMessage: msg.documentWithCaptionMessage?.message?.documentMessage?.contextInfo?.stanzaId, + audioMessage: msg.audioMessage?.contextInfo?.stanzaId, + contactMessage: msg.contactMessage?.vcard, + contactsArrayMessage: msg.contactsArrayMessage, + locationMessage: msg.locationMessage, + liveLocationMessage: msg.liveLocationMessage, + }; + + this.logger.verbose('type message: ' + types); + + return types; + } + + private getContextMessageContent(types: any) { + this.logger.verbose('get message content'); + const typeKey = Object.keys(types).find((key) => types[key] !== undefined); + + const result = typeKey ? types[typeKey] : undefined; + return result; + } + private getMessageContent(types: any) { this.logger.verbose('get message content'); const typeKey = Object.keys(types).find((key) => types[key] !== undefined); @@ -1241,6 +1288,18 @@ export class ChatwootService { return messageContent; } + private getContextConversationMessage(msg: any) { + this.logger.verbose('get context conversation message'); + + const types = this.getContextIdTypeMessage(msg); + + const messageContent = this.getContextMessageContent(types); + + this.logger.verbose('context conversation message: ' + messageContent); + + return messageContent; + } + public async eventWhatsapp(event: string, instance: InstanceDto, body: any) { this.logger.verbose('event whatsapp to instance: ' + instance.instanceName); try { @@ -1269,6 +1328,8 @@ export class ChatwootService { this.logger.verbose('get conversation message'); const bodyMessage = await this.getConversationMessage(body.message); + const source_reply_id = this.getContextConversationMessage(body.message); + const isMedia = this.isMediaMessage(body.message); if (!bodyMessage && !isMedia) { @@ -1286,6 +1347,8 @@ export class ChatwootService { const messageType = body.key.fromMe ? 'outgoing' : 'incoming'; + const source_id = body.key?.id; + this.logger.verbose('message type: ' + messageType); this.logger.verbose('is media: ' + isMedia); @@ -1387,7 +1450,14 @@ 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, + getConversion, + content, + messageType, + source_id, + source_reply_id, + ); if (!send) { this.logger.warn('message not sent'); @@ -1408,7 +1478,14 @@ 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, + getConversion, + bodyMessage, + messageType, + source_id, + source_reply_id, + ); if (!send) { this.logger.warn('message not sent'); diff --git a/src/whatsapp/services/whatsapp.service.ts b/src/whatsapp/services/whatsapp.service.ts index d11946ee..f6a86f04 100644 --- a/src/whatsapp/services/whatsapp.service.ts +++ b/src/whatsapp/services/whatsapp.service.ts @@ -1992,6 +1992,7 @@ export class WAStartupService { messageTimestamp: messageSent.messageTimestamp as number, owner: this.instance.name, source: getDevice(messageSent.key.id), + source_id: messageSent.key.id, }; this.logger.log(messageRaw); From bd0a47964502994f1eaa615e241da2fe2c46015c Mon Sep 17 00:00:00 2001 From: raimartinsb Date: Wed, 6 Sep 2023 09:11:15 -0300 Subject: [PATCH 2/7] added source_id in media messages --- package.json | 2 +- src/whatsapp/services/chatwoot.service.ts | 29 +++++++++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index c28271ca..282265a9 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "dependencies": { "@adiwajshing/keyed-db": "^0.2.4", "@ffmpeg-installer/ffmpeg": "^1.1.0", - "@figuro/chatwoot-sdk": "github:raimartinsb/chatwoot-sdk", + "@figuro/chatwoot-sdk": "^1.1.16", "@hapi/boom": "^10.0.1", "@sentry/node": "^7.59.2", "@whiskeysockets/baileys": "github:EvolutionAPI/Baileys", diff --git a/src/whatsapp/services/chatwoot.service.ts b/src/whatsapp/services/chatwoot.service.ts index b489a2c6..7061f866 100644 --- a/src/whatsapp/services/chatwoot.service.ts +++ b/src/whatsapp/services/chatwoot.service.ts @@ -732,6 +732,8 @@ export class ChatwootService { file: string, messageType: 'incoming' | 'outgoing' | undefined, content?: string, + source_id?: string, + source_reply_id?: string, ) { this.logger.verbose('send data to chatwoot'); @@ -748,6 +750,12 @@ export class ChatwootService { this.logger.verbose('temp file found'); data.append('attachments[]', createReadStream(file)); + this.logger.verbose('message context: ' + source_id); + data.append('source_id', source_id); + + this.logger.verbose('message reply context: ' + source_reply_id); + data.append('source_reply_id', source_reply_id); + this.logger.verbose('get client to instance: ' + this.provider.instanceName); const config = { method: 'post', @@ -1170,10 +1178,10 @@ export class ChatwootService { documentMessage: msg.documentMessage?.contextInfo?.stanzaId, documentWithCaptionMessage: msg.documentWithCaptionMessage?.message?.documentMessage?.contextInfo?.stanzaId, audioMessage: msg.audioMessage?.contextInfo?.stanzaId, - contactMessage: msg.contactMessage?.vcard, - contactsArrayMessage: msg.contactsArrayMessage, - locationMessage: msg.locationMessage, - liveLocationMessage: msg.liveLocationMessage, + contactMessage: msg.contactMessage?.contextInfo?.stanzaId, + contactsArrayMessage: msg.contactsArrayMessage?.contextInfo?.stanzaId, + locationMessage: msg.locationMessage?.contextInfo?.stanzaId, + liveLocationMessage: msg.liveLocationMessage?.contextInfo?.stanzaId, }; this.logger.verbose('type message: ' + types); @@ -1182,7 +1190,7 @@ export class ChatwootService { } private getContextMessageContent(types: any) { - this.logger.verbose('get message content'); + this.logger.verbose('get message context content'); const typeKey = Object.keys(types).find((key) => types[key] !== undefined); const result = typeKey ? types[typeKey] : undefined; @@ -1393,7 +1401,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(getConversion, fileName, messageType, content, source_id, source_reply_id); if (!send) { this.logger.warn('message not sent'); @@ -1414,7 +1422,14 @@ 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( + getConversion, + fileName, + messageType, + bodyMessage, + source_id, + source_reply_id, + ); if (!send) { this.logger.warn('message not sent'); From cb942e512dfad64d2cc399952810e16f14ce7776 Mon Sep 17 00:00:00 2001 From: raimartinsb Date: Wed, 6 Sep 2023 13:28:42 -0300 Subject: [PATCH 3/7] improved message update --- src/whatsapp/services/chatwoot.service.ts | 67 ++++++++++++++++------- src/whatsapp/services/whatsapp.service.ts | 1 - 2 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/whatsapp/services/chatwoot.service.ts b/src/whatsapp/services/chatwoot.service.ts index 7061f866..56a90f67 100644 --- a/src/whatsapp/services/chatwoot.service.ts +++ b/src/whatsapp/services/chatwoot.service.ts @@ -750,11 +750,15 @@ export class ChatwootService { this.logger.verbose('temp file found'); data.append('attachments[]', createReadStream(file)); - this.logger.verbose('message context: ' + source_id); - data.append('source_id', source_id); + if (source_id) { + this.logger.verbose('source_id found'); + data.append('source_id', source_id); + } - this.logger.verbose('message reply context: ' + source_reply_id); - data.append('source_reply_id', source_reply_id); + if (source_reply_id) { + this.logger.verbose('source_reply_id found'); + data.append('source_reply_id', source_reply_id); + } this.logger.verbose('get client to instance: ' + this.provider.instanceName); const config = { @@ -955,6 +959,35 @@ export class ChatwootService { } } + public async updateMessage( + instance: InstanceDto, + accountId: number, + conversationId: number, + messageId: number, + sourceId: string | null, + ) { + this.logger.verbose('update message to chatwoot instance: ' + instance.instanceName); + const client = await this.clientCw(instance); + + if (!client) { + this.logger.warn('client not found'); + return null; + } + this.logger.verbose('check if sourceId to update'); + if (sourceId) { + this.logger.verbose('update message to chatwoot'); + const dataUpdated = { + source_id: sourceId, + }; + await client.messages.update({ + accountId, + conversationId, + data: dataUpdated, + messageId, + }); + } + } + public async receiveWebhook(instance: InstanceDto, body: any) { try { this.logger.verbose('receive webhook to chatwoot instance: ' + instance.instanceName); @@ -1052,6 +1085,9 @@ export class ChatwootService { } for (const message of body.conversation.messages) { + const messageId = message?.id; + const conversationId = message?.conversation_id; + const accountId = message?.account_id; this.logger.verbose('check if message is media'); if (message.attachments && message.attachments.length > 0) { this.logger.verbose('message is media'); @@ -1062,7 +1098,8 @@ export class ChatwootService { formatText = null; } - await this.sendAttachment(waInstance, chatId, attachment.data_url, formatText); + const mediaMessage = await this.sendAttachment(waInstance, chatId, attachment.data_url, formatText); + await this.updateMessage(instance, accountId, conversationId, messageId, mediaMessage?.key?.id); } } else { this.logger.verbose('message is text'); @@ -1080,17 +1117,7 @@ export class ChatwootService { }; const message = await waInstance?.textMessage(data); - const conversationId = body?.conversation?.id; - const messageId = body?.id; - const dataUpdated = { - source_id: message.key.id, - }; - await client.messages.update({ - accountId: this.provider.account_id, - conversationId, - data: dataUpdated, - messageId, - }); + await this.updateMessage(instance, accountId, conversationId, messageId, message?.key?.id); } } } @@ -1191,7 +1218,7 @@ export class ChatwootService { private getContextMessageContent(types: any) { this.logger.verbose('get message context content'); - const typeKey = Object.keys(types).find((key) => types[key] !== undefined); + const typeKey = Object.keys(types).find((key) => types[key] !== undefined && types[key] !== ''); const result = typeKey ? types[typeKey] : undefined; return result; @@ -1301,11 +1328,11 @@ export class ChatwootService { const types = this.getContextIdTypeMessage(msg); - const messageContent = this.getContextMessageContent(types); + const messageContext = this.getContextMessageContent(types); - this.logger.verbose('context conversation message: ' + messageContent); + this.logger.verbose('context conversation message: ' + messageContext); - return messageContent; + return messageContext; } public async eventWhatsapp(event: string, instance: InstanceDto, body: any) { diff --git a/src/whatsapp/services/whatsapp.service.ts b/src/whatsapp/services/whatsapp.service.ts index f6a86f04..d11946ee 100644 --- a/src/whatsapp/services/whatsapp.service.ts +++ b/src/whatsapp/services/whatsapp.service.ts @@ -1992,7 +1992,6 @@ export class WAStartupService { messageTimestamp: messageSent.messageTimestamp as number, owner: this.instance.name, source: getDevice(messageSent.key.id), - source_id: messageSent.key.id, }; this.logger.log(messageRaw); From 72dae22ef422dd36d2d81809d3ec23493e3519f2 Mon Sep 17 00:00:00 2001 From: raimartinsb Date: Mon, 11 Sep 2023 07:44:09 -0300 Subject: [PATCH 4/7] Configuration to update source_id only when desired --- src/config/env.config.ts | 12 +++++-- src/dev-env.yml | 6 +++- src/whatsapp/services/chatwoot.service.ts | 42 +++++++++++++---------- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/config/env.config.ts b/src/config/env.config.ts index 9c63b893..15e70dd6 100644 --- a/src/config/env.config.ts +++ b/src/config/env.config.ts @@ -70,6 +70,10 @@ export type Websocket = { ENABLED: boolean; }; +export type Chatwoot = { + USE_REPLY_ID: boolean; +}; + export type EventsWebhook = { APPLICATION_STARTUP: boolean; QRCODE_UPDATED: boolean; @@ -134,6 +138,7 @@ export interface Env { QRCODE: QrCode; AUTHENTICATION: Auth; PRODUCTION?: Production; + CHATWOOT?: Chatwoot; } export type Key = keyof Env; @@ -224,9 +229,7 @@ export class ConfigService { COLOR: process.env?.LOG_COLOR === 'true', BAILEYS: (process.env?.LOG_BAILEYS as LogBaileys) || 'error', }, - DEL_INSTANCE: process.env?.DEL_INSTANCE === 'true' - ? 5 - : Number.parseInt(process.env.DEL_INSTANCE) || false, + DEL_INSTANCE: process.env?.DEL_INSTANCE === 'true' ? 5 : Number.parseInt(process.env.DEL_INSTANCE) || false, WEBHOOK: { GLOBAL: { URL: process.env?.WEBHOOK_GLOBAL_URL, @@ -278,6 +281,9 @@ export class ConfigService { SECRET: process.env.AUTHENTICATION_JWT_SECRET, }, }, + CHATWOOT: { + USE_REPLY_ID: process.env?.USE_REPLY_ID === 'true', + }, }; } } diff --git a/src/dev-env.yml b/src/dev-env.yml index 235ec1b7..9f24f5a1 100644 --- a/src/dev-env.yml +++ b/src/dev-env.yml @@ -145,4 +145,8 @@ AUTHENTICATION: # Set the secret key to encrypt and decrypt your token and its expiration time. JWT: EXPIRIN_IN: 0 # seconds - 3600s === 1h | zero (0) - never expires - SECRET: L=0YWt]b2w[WF>#>:&E` \ No newline at end of file + SECRET: L=0YWt]b2w[WF>#>:&E` + +# Configure to chatwoot +CHATWOOT: + USE_REPLY_ID: false \ No newline at end of file diff --git a/src/whatsapp/services/chatwoot.service.ts b/src/whatsapp/services/chatwoot.service.ts index 56a90f67..06534bcf 100644 --- a/src/whatsapp/services/chatwoot.service.ts +++ b/src/whatsapp/services/chatwoot.service.ts @@ -5,7 +5,7 @@ import { createReadStream, readFileSync, unlinkSync, writeFileSync } from 'fs'; import mimeTypes from 'mime-types'; import path from 'path'; -import { ConfigService } from '../../config/env.config'; +import { Chatwoot, ConfigService } from '../../config/env.config'; import { Logger } from '../../config/logger.config'; import { ROOT_DIR } from '../../config/path.config'; import { ChatwootDto } from '../dto/chatwoot.dto'; @@ -966,25 +966,29 @@ export class ChatwootService { messageId: number, sourceId: string | null, ) { - this.logger.verbose('update message to chatwoot instance: ' + instance.instanceName); - const client = await this.clientCw(instance); + // const useReplyId = this.configService.get('DEL_INSTANCE'); + const useReplyId = this.configService.get('CHATWOOT')?.USE_REPLY_ID; + if (useReplyId === true) { + this.logger.verbose('update message to chatwoot instance: ' + instance.instanceName); + const client = await this.clientCw(instance); - if (!client) { - this.logger.warn('client not found'); - return null; - } - this.logger.verbose('check if sourceId to update'); - if (sourceId) { - this.logger.verbose('update message to chatwoot'); - const dataUpdated = { - source_id: sourceId, - }; - await client.messages.update({ - accountId, - conversationId, - data: dataUpdated, - messageId, - }); + if (!client) { + this.logger.warn('client not found'); + return null; + } + this.logger.verbose('check if sourceId to update'); + if (sourceId) { + this.logger.verbose('update message to chatwoot'); + const dataUpdated = { + source_id: sourceId, + }; + await client.messages.update({ + accountId, + conversationId, + data: dataUpdated, + messageId, + }); + } } } From c16f962d2b1110eadeffc9cc9fe0a3f94fb513f1 Mon Sep 17 00:00:00 2001 From: AdsonCicilioti Date: Tue, 12 Sep 2023 13:39:40 -0300 Subject: [PATCH 5/7] 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 6/7] 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 7/7] 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; };