diff --git a/src/validate/validate.schema.ts b/src/validate/validate.schema.ts index 9b75fd08..03b01a4a 100644 --- a/src/validate/validate.schema.ts +++ b/src/validate/validate.schema.ts @@ -866,7 +866,8 @@ export const chatwootSchema: JSONSchema7 = { account_id: { type: 'string' }, token: { type: 'string' }, url: { type: 'string' }, + sign_msg: { type: 'boolean', enum: [true, false] }, }, - required: ['enabled', 'account_id', 'token', 'url'], - ...isNotEmpty('account_id', 'token', 'url'), + required: ['enabled', 'account_id', 'token', 'url', 'sign_msg'], + ...isNotEmpty('account_id', 'token', 'url', 'sign_msg'), }; diff --git a/src/whatsapp/controllers/chatwoot.controller.ts b/src/whatsapp/controllers/chatwoot.controller.ts index e5887d26..71519c39 100644 --- a/src/whatsapp/controllers/chatwoot.controller.ts +++ b/src/whatsapp/controllers/chatwoot.controller.ts @@ -4,6 +4,7 @@ import { InstanceDto } from '../dto/instance.dto'; import { ChatwootDto } from '../dto/chatwoot.dto'; import { ChatwootService } from '../services/chatwoot.service'; import { Logger } from '../../config/logger.config'; +import { waMonitor } from '../whatsapp.module'; const logger = new Logger('ChatwootController'); @@ -27,6 +28,10 @@ export class ChatwootController { if (!data.token) { throw new BadRequestException('token is required'); } + + if (!data.sign_msg) { + throw new BadRequestException('sign_msg is required'); + } } if (!data.enabled) { @@ -34,22 +39,39 @@ export class ChatwootController { data.account_id = ''; data.token = ''; data.url = ''; + data.sign_msg = false; } data.name_inbox = instance.instanceName; - return this.chatwootService.create(instance, data); + const result = this.chatwootService.create(instance, data); + + const response = { + ...result, + webhook_url: `/chatwoot/webhook/${instance.instanceName}`, + }; + + return response; } public async findChatwoot(instance: InstanceDto) { logger.verbose('requested findChatwoot from ' + instance.instanceName + ' instance'); - return this.chatwootService.find(instance); + const result = this.chatwootService.find(instance); + + const response = { + ...result, + webhook_url: `/chatwoot/webhook/${instance.instanceName}`, + }; + + return response; } public async receiveWebhook(instance: InstanceDto, data: any) { logger.verbose( 'requested receiveWebhook from ' + instance.instanceName + ' instance', ); - return this.chatwootService.receiveWebhook(instance, data); + const chatwootService = new ChatwootService(waMonitor); + + return chatwootService.receiveWebhook(instance, data); } } diff --git a/src/whatsapp/controllers/instance.controller.ts b/src/whatsapp/controllers/instance.controller.ts index 9ffd7e47..51ad9b37 100644 --- a/src/whatsapp/controllers/instance.controller.ts +++ b/src/whatsapp/controllers/instance.controller.ts @@ -37,6 +37,7 @@ export class InstanceController { chatwoot_account_id, chatwoot_token, chatwoot_url, + chatwoot_sign_msg, }: InstanceDto) { this.logger.verbose('requested createInstance from ' + instanceName + ' instance'); @@ -78,7 +79,12 @@ export class InstanceController { this.logger.verbose('hash: ' + hash + ' generated'); - if (!chatwoot_account_id || !chatwoot_token || !chatwoot_url) { + if ( + !chatwoot_account_id || + !chatwoot_token || + !chatwoot_url || + !chatwoot_sign_msg + ) { let getEvents: string[]; if (webhook) { @@ -131,12 +137,17 @@ export class InstanceController { throw new BadRequestException('url is required'); } + if (!chatwoot_sign_msg) { + throw new BadRequestException('sign_msg is required'); + } + try { this.chatwootService.create(instance, { enabled: true, account_id: chatwoot_account_id, token: chatwoot_token, url: chatwoot_url, + sign_msg: chatwoot_sign_msg, name_inbox: instance.instanceName, }); } catch (error) { @@ -154,7 +165,9 @@ export class InstanceController { account_id: chatwoot_account_id, token: chatwoot_token, url: chatwoot_url, + sign_msg: chatwoot_sign_msg, name_inbox: instance.instanceName, + webhook_url: `/chatwoot/webhook/${instance.instanceName}`, }, }; } else { @@ -187,7 +200,12 @@ export class InstanceController { this.logger.verbose('hash: ' + hash + ' generated'); - if (!chatwoot_account_id || !chatwoot_token || !chatwoot_url) { + if ( + !chatwoot_account_id || + !chatwoot_token || + !chatwoot_url || + !chatwoot_sign_msg + ) { let getEvents: string[]; if (webhook) { @@ -253,12 +271,17 @@ export class InstanceController { throw new BadRequestException('url is required'); } + if (!chatwoot_sign_msg) { + throw new BadRequestException('sign_msg is required'); + } + try { this.chatwootService.create(instance, { enabled: true, account_id: chatwoot_account_id, token: chatwoot_token, url: chatwoot_url, + sign_msg: chatwoot_sign_msg, name_inbox: instance.instanceName, }); } catch (error) { @@ -276,7 +299,9 @@ export class InstanceController { account_id: chatwoot_account_id, token: chatwoot_token, url: chatwoot_url, + sign_msg: chatwoot_sign_msg, name_inbox: instance.instanceName, + webhook_url: `/chatwoot/webhook/${instance.instanceName}`, }, }; } diff --git a/src/whatsapp/dto/chatwoot.dto.ts b/src/whatsapp/dto/chatwoot.dto.ts index a65bbf71..e78b0676 100644 --- a/src/whatsapp/dto/chatwoot.dto.ts +++ b/src/whatsapp/dto/chatwoot.dto.ts @@ -4,4 +4,5 @@ export class ChatwootDto { token?: string; url?: string; name_inbox?: string; + sign_msg?: boolean; } diff --git a/src/whatsapp/dto/instance.dto.ts b/src/whatsapp/dto/instance.dto.ts index 479a1dae..ce282e03 100644 --- a/src/whatsapp/dto/instance.dto.ts +++ b/src/whatsapp/dto/instance.dto.ts @@ -8,4 +8,5 @@ export class InstanceDto { chatwoot_account_id?: string; chatwoot_token?: string; chatwoot_url?: string; + chatwoot_sign_msg?: boolean; } diff --git a/src/whatsapp/models/chatwoot.model.ts b/src/whatsapp/models/chatwoot.model.ts index 1ecdcf82..ca082309 100644 --- a/src/whatsapp/models/chatwoot.model.ts +++ b/src/whatsapp/models/chatwoot.model.ts @@ -8,6 +8,7 @@ export class ChatwootRaw { token?: string; url?: string; name_inbox?: string; + sign_msg?: boolean; } const chatwootSchema = new Schema({ @@ -17,6 +18,7 @@ const chatwootSchema = new Schema({ token: { type: String, required: true }, url: { type: String, required: true }, name_inbox: { type: String, required: true }, + sign_msg: { type: Boolean, required: true }, }); export const ChatwootModel = dbserver?.model( diff --git a/src/whatsapp/services/chatwoot.service.ts b/src/whatsapp/services/chatwoot.service.ts index 0f3c806f..c31a745a 100644 --- a/src/whatsapp/services/chatwoot.service.ts +++ b/src/whatsapp/services/chatwoot.service.ts @@ -4,21 +4,43 @@ import { ChatwootDto } from '../dto/chatwoot.dto'; import { WAMonitoringService } from './monitor.service'; import { Logger } from '../../config/logger.config'; import ChatwootClient from '@figuro/chatwoot-sdk'; -import { createReadStream, unlinkSync, writeFileSync } from 'fs'; +import { createReadStream, readFileSync, unlinkSync, writeFileSync } from 'fs'; import axios from 'axios'; import FormData from 'form-data'; import { SendTextDto } from '../dto/sendMessage.dto'; import mimeTypes from 'mime-types'; import { SendAudioDto } from '../dto/sendMessage.dto'; import { SendMediaDto } from '../dto/sendMessage.dto'; +import NodeCache from 'node-cache'; +import { ROOT_DIR } from '../../config/path.config'; export class ChatwootService { - constructor(private readonly waMonitor: WAMonitoringService) {} + private messageCacheFile: string; + private messageCache: Set; private readonly logger = new Logger(ChatwootService.name); private provider: any; + constructor(private readonly waMonitor: WAMonitoringService) { + this.messageCache = new Set(); + } + + private loadMessageCache(): Set { + try { + const cacheData = readFileSync(this.messageCacheFile, 'utf-8'); + const cacheArray = cacheData.split('\n'); + return new Set(cacheArray); + } catch (error) { + return new Set(); + } + } + + private saveMessageCache() { + const cacheData = Array.from(this.messageCache).join('\n'); + writeFileSync(this.messageCacheFile, cacheData, 'utf-8'); + } + private async getProvider(instance: InstanceDto) { const provider = await this.waMonitor.waInstances[ instance.instanceName @@ -436,12 +458,13 @@ export class ChatwootService { public async receiveWebhook(instance: InstanceDto, body: any) { try { + const client = await this.clientCw(instance); + if (!body?.conversation || body.private) return { message: 'bot' }; const chatId = body.conversation.meta.sender.phone_number.replace('+', ''); const messageReceived = body.content; const senderName = body?.sender?.name; - const accountId = body.account.id as number; const waInstance = this.waMonitor.waInstances[instance.instanceName]; if (chatId === '123456' && body.message_type === 'outgoing') { @@ -495,27 +518,31 @@ export class ChatwootService { body?.conversation?.messages?.length && chatId !== '123456' ) { - // if (IMPORT_MESSAGES_SENT && messages_sent.includes(body.id)) { - // console.log(`🚨 Não importar mensagens enviadas, ficaria duplicado.`); + this.messageCacheFile = path.join( + ROOT_DIR, + 'store', + 'chatwoot', + `${instance.instanceName}_cache.txt`, + ); - // const indexMessage = messages_sent.indexOf(body.id); - // messages_sent.splice(indexMessage, 1); + this.messageCache = this.loadMessageCache(); - // return { message: 'bot' }; - // } + if (this.messageCache.has(body.id.toString())) { + return { message: 'bot' }; + } let formatText: string; if (senderName === null || senderName === undefined) { formatText = messageReceived; } else { - // formatText = TOSIGN ? `*${senderName}*: ${messageReceived}` : messageReceived; - formatText = `*${senderName}*: ${messageReceived}`; + formatText = this.provider.sign_msg + ? `*${senderName}*: ${messageReceived}` + : messageReceived; } for (const message of body.conversation.messages) { if (message.attachments && message.attachments.length > 0) { for (const attachment of message.attachments) { - console.log(attachment); if (!messageReceived) { formatText = null; } @@ -609,7 +636,6 @@ export class ChatwootService { // } if (body.key.remoteJid === 'status@broadcast') { - console.log(`🚨 Ignorando status do whatsapp.`); return; } @@ -617,7 +643,6 @@ export class ChatwootService { const messageType = body.key.fromMe ? 'outgoing' : 'incoming'; if (!getConversion) { - console.log('🚨 Erro ao criar conversa'); return; } @@ -637,7 +662,11 @@ export class ChatwootService { const fileData = Buffer.from(downloadBase64.base64, 'base64'); - const fileName = `${path.join(waInstance?.storePath, 'temp', `${nameFile}`)}`; + const fileName = `${path.join( + waInstance?.storePath, + 'chatwoot', + `${nameFile}`, + )}`; writeFileSync(fileName, fileData, 'utf8'); @@ -651,6 +680,19 @@ export class ChatwootService { messageType, ); + this.messageCacheFile = path.join( + ROOT_DIR, + 'store', + 'chatwoot', + `${instance.instanceName}_cache.txt`, + ); + + this.messageCache = this.loadMessageCache(); + + this.messageCache.add(send.id.toString()); + + this.saveMessageCache(); + return send; } diff --git a/src/whatsapp/services/whatsapp.service.ts b/src/whatsapp/services/whatsapp.service.ts index 0f756d18..e21e57c2 100644 --- a/src/whatsapp/services/whatsapp.service.ts +++ b/src/whatsapp/services/whatsapp.service.ts @@ -300,6 +300,12 @@ export class WAStartupService { this.localChatwoot.url = data?.url; this.logger.verbose(`Chatwoot url: ${this.localChatwoot.url}`); + this.localChatwoot.name_inbox = data?.name_inbox; + this.logger.verbose(`Chatwoot inbox name: ${this.localChatwoot.name_inbox}`); + + this.localChatwoot.sign_msg = data?.sign_msg; + this.logger.verbose(`Chatwoot sign msg: ${this.localChatwoot.sign_msg}`); + this.logger.verbose('Chatwoot loaded'); } @@ -310,6 +316,7 @@ export class WAStartupService { this.logger.verbose(`Chatwoot token: ${data.token}`); this.logger.verbose(`Chatwoot url: ${data.url}`); this.logger.verbose(`Chatwoot inbox name: ${data.name_inbox}`); + this.logger.verbose(`Chatwoot sign msg: ${data.sign_msg}`); Object.assign(this.localChatwoot, data); this.logger.verbose('Chatwoot set'); @@ -328,6 +335,8 @@ export class WAStartupService { this.logger.verbose(`Chatwoot token: ${data.token}`); this.logger.verbose(`Chatwoot url: ${data.url}`); this.logger.verbose(`Chatwoot inbox name: ${data.name_inbox}`); + this.logger.verbose(`Chatwoot sign msg: ${data.sign_msg}`); + return data; } diff --git a/src/whatsapp/types/wa.types.ts b/src/whatsapp/types/wa.types.ts index e08aef78..1ebe3b40 100644 --- a/src/whatsapp/types/wa.types.ts +++ b/src/whatsapp/types/wa.types.ts @@ -47,6 +47,7 @@ export declare namespace wa { token?: string; url?: string; name_inbox?: string; + sign_msg?: boolean; }; export type StateConnection = {