From 1172b6c87111f0266673795d13619c5f6f07147b Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Mon, 8 Apr 2024 19:09:59 -0300 Subject: [PATCH 01/42] mobile connection --- package.json | 2 +- .../controllers/instance.controller.ts | 23 ++++- src/whatsapp/dto/instance.dto.ts | 3 +- src/whatsapp/routers/instance.router.ts | 18 +++- .../services/whatsapp.baileys.service.ts | 85 ++++++++++++++++++- .../services/whatsapp.business.service.ts | 6 +- 6 files changed, 127 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 69ea3b64..c1d8ddd2 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "@figuro/chatwoot-sdk": "^1.1.16", "@hapi/boom": "^10.0.1", "@sentry/node": "^7.59.2", - "@whiskeysockets/baileys": "6.6.0", + "@whiskeysockets/baileys": "github:AtendAI/Baileys", "amqplib": "^0.10.3", "aws-sdk": "^2.1499.0", "axios": "^1.6.5", diff --git a/src/whatsapp/controllers/instance.controller.ts b/src/whatsapp/controllers/instance.controller.ts index 91103e33..c389b819 100644 --- a/src/whatsapp/controllers/instance.controller.ts +++ b/src/whatsapp/controllers/instance.controller.ts @@ -53,6 +53,7 @@ export class InstanceController { events, qrcode, number, + mobile, integration, token, chatwoot_account_id, @@ -115,7 +116,7 @@ export class InstanceController { ); } - await this.waMonitor.saveInstance({ integration, instanceName, token, number }); + await this.waMonitor.saveInstance({ integration, instanceName, token, number, mobile }); instance.instanceName = instanceName; @@ -405,7 +406,7 @@ export class InstanceController { if (qrcode) { this.logger.verbose('creating qrcode'); - await instance.connectToWhatsapp(number); + await instance.connectToWhatsapp(number, mobile); await delay(5000); getQrcode = instance.qrCode; } @@ -569,7 +570,7 @@ export class InstanceController { } } - public async connectToWhatsapp({ instanceName, number = null }: InstanceDto) { + public async connectToWhatsapp({ instanceName, number = null, mobile = null }: InstanceDto) { try { this.logger.verbose('requested connectToWhatsapp from ' + instanceName + ' instance'); @@ -592,7 +593,7 @@ export class InstanceController { if (state == 'close') { this.logger.verbose('connecting'); - await instance.connectToWhatsapp(number); + await instance.connectToWhatsapp(number, mobile); await delay(5000); return instance.qrCode; @@ -633,6 +634,20 @@ export class InstanceController { } } + public async registerMobileCode({ instanceName }: InstanceDto, { mobileCode }: any) { + try { + this.logger.verbose('requested registerMobileCode from ' + instanceName + ' instance'); + + const instance = this.waMonitor.waInstances[instanceName]; + + console.log('mobileCode', mobileCode); + return await instance.receiveMobileCode(mobileCode); + // return { status: 'SUCCESS', error: false, response: { message: 'Mobile code registered' } }; + } catch (error) { + this.logger.error(error); + } + } + public async connectionState({ instanceName }: InstanceDto) { this.logger.verbose('requested connectionState from ' + instanceName + ' instance'); return { diff --git a/src/whatsapp/dto/instance.dto.ts b/src/whatsapp/dto/instance.dto.ts index eaf21aab..4b533de1 100644 --- a/src/whatsapp/dto/instance.dto.ts +++ b/src/whatsapp/dto/instance.dto.ts @@ -1,10 +1,11 @@ -import { WAPresence } from "@whiskeysockets/baileys"; +import { WAPresence } from '@whiskeysockets/baileys'; export class InstanceDto { instanceName: string; instanceId?: string; qrcode?: boolean; number?: string; + mobile?: boolean; integration?: string; token?: string; webhook?: string; diff --git a/src/whatsapp/routers/instance.router.ts b/src/whatsapp/routers/instance.router.ts index 6d4727e2..fa78c197 100644 --- a/src/whatsapp/routers/instance.router.ts +++ b/src/whatsapp/routers/instance.router.ts @@ -3,7 +3,7 @@ import { RequestHandler, Router } from 'express'; import { Auth, ConfigService, Database } from '../../config/env.config'; import { Logger } from '../../config/logger.config'; import { dbserver } from '../../libs/db.connect'; -import {instanceNameSchema, oldTokenSchema, presenceOnlySchema} from '../../validate/validate.schema'; +import { instanceNameSchema, oldTokenSchema, presenceOnlySchema } from '../../validate/validate.schema'; import { RouterBroker } from '../abstract/abstract.router'; import { InstanceDto, SetPresenceDto } from '../dto/instance.dto'; import { OldToken } from '../services/auth.service'; @@ -50,6 +50,22 @@ export class InstanceRouter extends RouterBroker { return res.status(HttpStatus.OK).json(response); }) + .post(this.routerPath('registerMobileCode'), ...guards, async (req, res) => { + logger.verbose('request received in registerMobileCode'); + logger.verbose('request body: '); + logger.verbose(req.body); + + logger.verbose('request query: '); + logger.verbose(req.query); + const response = await this.dataValidate({ + request: req, + schema: instanceNameSchema, + ClassRef: SetPresenceDto, + execute: (instance, data) => instanceController.registerMobileCode(instance, data), + }); + + return res.status(HttpStatus.OK).json(response); + }) .get(this.routerPath('connect'), ...guards, async (req, res) => { logger.verbose('request received in connectInstance'); logger.verbose('request body: '); diff --git a/src/whatsapp/services/whatsapp.baileys.service.ts b/src/whatsapp/services/whatsapp.baileys.service.ts index f99e074d..6ac1e5e6 100644 --- a/src/whatsapp/services/whatsapp.baileys.service.ts +++ b/src/whatsapp/services/whatsapp.baileys.service.ts @@ -12,6 +12,7 @@ import makeWASocket, { DisconnectReason, downloadMediaMessage, fetchLatestBaileysVersion, + generateMobileNode, generateWAMessageFromContent, getAggregateVotesInPollMessage, getContentType, @@ -24,6 +25,7 @@ import makeWASocket, { MessageUpsertType, MiscMessageGenerationOptions, ParticipantAction, + PHONENUMBER_MCC, prepareWAMessageMedia, proto, useMultiFileAuthState, @@ -42,6 +44,7 @@ import { exec } from 'child_process'; import { arrayUnique, isBase64, isURL } from 'class-validator'; import EventEmitter2 from 'eventemitter2'; import fs, { existsSync, readFileSync } from 'fs'; +import { parsePhoneNumber } from 'libphonenumber-js'; import Long from 'long'; import NodeCache from 'node-cache'; import { getMIMEType } from 'node-mime-types'; @@ -132,6 +135,7 @@ export class BaileysStartupService extends WAStartupService { this.logger.verbose('BaileysStartupService initialized'); this.cleanStore(); this.instance.qrcode = { count: 0 }; + this.mobile = false; } private readonly msgRetryCounterCache: CacheStore = new NodeCache(); @@ -141,7 +145,8 @@ export class BaileysStartupService extends WAStartupService { public stateConnection: wa.StateConnection = { state: 'close' }; - private phoneNumber: string; + public phoneNumber: string; + public mobile: boolean; public get connectionStatus() { this.logger.verbose('Getting connection status'); @@ -389,6 +394,10 @@ export class BaileysStartupService extends WAStartupService { ); } } + + if (connection === 'connecting') { + if (this.mobile) this.sendMobileCode(); + } } private async getMessage(key: proto.IMessageKey, full = false) { @@ -446,7 +455,7 @@ export class BaileysStartupService extends WAStartupService { return await useMultiFileAuthState(join(INSTANCE_DIR, this.instance.name)); } - public async connectToWhatsapp(number?: string): Promise { + public async connectToWhatsapp(number?: string, mobile?: boolean): Promise { this.logger.verbose('Connecting to whatsapp'); try { this.loadWebhook(); @@ -461,7 +470,14 @@ export class BaileysStartupService extends WAStartupService { this.instance.authState = await this.defineAuthState(); + if (!mobile) { + this.mobile = false; + } else { + this.mobile = mobile; + } + const { version } = await fetchLatestBaileysVersion(); + this.logger.verbose('Baileys version: ' + version); const session = this.configService.get('CONFIG_SESSION_PHONE'); const browser: WABrowserDescription = [session.CLIENT, session.NAME, release()]; @@ -500,6 +516,7 @@ export class BaileysStartupService extends WAStartupService { }, logger: P({ level: this.logBaileys }), printQRInTerminal: false, + mobile, browser: number ? ['Chrome (Linux)', session.NAME, release()] : browser, version, markOnlineOnConnect: this.localSettings.always_online, @@ -564,6 +581,70 @@ export class BaileysStartupService extends WAStartupService { } } + private async sendMobileCode() { + const { registration } = this.client.authState.creds || null; + + let phoneNumber = registration.phoneNumber || this.phoneNumber; + + if (!phoneNumber.startsWith('+')) { + phoneNumber = '+' + phoneNumber; + } + + if (!phoneNumber) { + this.logger.error('Phone number not found'); + return; + } + + console.log('phoneNumber', phoneNumber); + + const parsedPhoneNumber = parsePhoneNumber(phoneNumber); + + console.log('parsedPhoneNumber', parsedPhoneNumber); + + if (!parsedPhoneNumber?.isValid()) { + this.logger.error('Phone number invalid'); + return; + } + + registration.phoneNumber = parsedPhoneNumber.format('E.164'); + registration.phoneNumberCountryCode = parsedPhoneNumber.countryCallingCode; + registration.phoneNumberNationalNumber = parsedPhoneNumber.nationalNumber; + + const mcc = await PHONENUMBER_MCC[parsedPhoneNumber.countryCallingCode]; + if (!mcc) { + this.logger.error('MCC not found'); + return; + } + + registration.phoneNumberMobileCountryCode = mcc; + registration.method = 'voice'; + + try { + const response = await this.client.requestRegistrationCode(registration); + + console.log('response', response); + if (['ok', 'sent'].includes(response?.status)) { + this.logger.verbose('Registration code sent successfully'); + + return response; + } + } catch (error) { + this.logger.error(error); + } + } + + public async receiveMobileCode(code: string) { + await this.client + .register(code.replace(/["']/g, '').trim().toLowerCase()) + .then(async (response) => { + this.logger.verbose('Registration code received successfully'); + console.log(response); + }) + .catch((error) => { + this.logger.error(error); + }); + } + public async reloadConnection(): Promise { try { this.instance.authState = await this.defineAuthState(); diff --git a/src/whatsapp/services/whatsapp.business.service.ts b/src/whatsapp/services/whatsapp.business.service.ts index 2b4a32cf..35b1e028 100644 --- a/src/whatsapp/services/whatsapp.business.service.ts +++ b/src/whatsapp/services/whatsapp.business.service.ts @@ -44,7 +44,8 @@ export class BusinessStartupService extends WAStartupService { public stateConnection: wa.StateConnection = { state: 'open' }; - private phoneNumber: string; + public phoneNumber: string; + public mobile: boolean; public get connectionStatus() { this.logger.verbose('Getting connection status'); @@ -1347,4 +1348,7 @@ export class BusinessStartupService extends WAStartupService { public async handleLabel() { throw new BadRequestException('Method not available on WhatsApp Business API'); } + public async receiveMobileCode() { + throw new BadRequestException('Method not available on WhatsApp Business API'); + } } From 9aba51cb451cad8f2acbf9cf8a7ff08ca9f5ea0a Mon Sep 17 00:00:00 2001 From: Joao Gabriel <22327462+gabrielgranado@users.noreply.github.com> Date: Mon, 8 Apr 2024 22:55:12 -0300 Subject: [PATCH 02/42] changed returned sessions on typebot status change --- src/whatsapp/services/typebot.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/whatsapp/services/typebot.service.ts b/src/whatsapp/services/typebot.service.ts index 4d79b660..7336ff24 100644 --- a/src/whatsapp/services/typebot.service.ts +++ b/src/whatsapp/services/typebot.service.ts @@ -57,7 +57,7 @@ export class TypebotService { if (session) { if (status === 'closed') { - findData.sessions.splice(findData.sessions.indexOf(session), 1); + const found_session : Session[] = findData.sessions.splice(findData.sessions.indexOf(session), 1); const typebotData = { enabled: findData.enabled, @@ -68,7 +68,7 @@ export class TypebotService { delay_message: findData.delay_message, unknown_message: findData.unknown_message, listening_from_me: findData.listening_from_me, - sessions: findData.sessions, + sessions: found_session, }; this.create(instance, typebotData); @@ -106,7 +106,7 @@ export class TypebotService { delay_message: findData.delay_message, unknown_message: findData.unknown_message, listening_from_me: findData.listening_from_me, - sessions: findData.sessions, + sessions: findData.sessions.splice(findData.sessions.indexOf(session), 1), }; this.create(instance, typebotData); From 04575d805188632a2703b0c47dd9d08e9b66affe Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Tue, 9 Apr 2024 06:44:59 -0300 Subject: [PATCH 03/42] adjusts in websocket --- Docker/.env.example | 1 + Dockerfile | 1 + src/config/env.config.ts | 2 + src/dev-env.yml | 1 + src/whatsapp/services/whatsapp.service.ts | 56 +++++++++++++++++------ 5 files changed, 47 insertions(+), 14 deletions(-) diff --git a/Docker/.env.example b/Docker/.env.example index f55e3d65..865ef877 100644 --- a/Docker/.env.example +++ b/Docker/.env.example @@ -53,6 +53,7 @@ RABBITMQ_EXCHANGE_NAME=evolution_exchange RABBITMQ_URI=amqp://guest:guest@rabbitmq:5672 WEBSOCKET_ENABLED=false +WEBSOCKET_GLOBAL_EVENTS=false WA_BUSINESS_TOKEN_WEBHOOK=evolution WA_BUSINESS_URL=https://graph.facebook.com diff --git a/Dockerfile b/Dockerfile index 3f24af28..599f8cca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -68,6 +68,7 @@ ENV RABBITMQ_EXCHANGE_NAME=evolution_exchange ENV RABBITMQ_URI=amqp://guest:guest@rabbitmq:5672 ENV WEBSOCKET_ENABLED=false +ENV WEBSOCKET_GLOBAL_EVENTS=false ENV WA_BUSINESS_TOKEN_WEBHOOK=evolution ENV WA_BUSINESS_URL=https://graph.facebook.com diff --git a/src/config/env.config.ts b/src/config/env.config.ts index 9ee778c1..b3991d08 100644 --- a/src/config/env.config.ts +++ b/src/config/env.config.ts @@ -86,6 +86,7 @@ export type Sqs = { export type Websocket = { ENABLED: boolean; + GLOBAL_EVENTS: boolean; }; export type WaBusiness = { @@ -299,6 +300,7 @@ export class ConfigService { }, WEBSOCKET: { ENABLED: process.env?.WEBSOCKET_ENABLED === 'true', + GLOBAL_EVENTS: process.env?.WEBSOCKET_GLOBAL_EVENTS === 'true', }, WA_BUSINESS: { TOKEN_WEBHOOK: process.env.WA_BUSINESS_TOKEN_WEBHOOK || '', diff --git a/src/dev-env.yml b/src/dev-env.yml index adc308e8..f791b721 100644 --- a/src/dev-env.yml +++ b/src/dev-env.yml @@ -97,6 +97,7 @@ SQS: WEBSOCKET: ENABLED: false + GLOBAL_EVENTS: false WA_BUSINESS: TOKEN_WEBHOOK: evolution diff --git a/src/whatsapp/services/whatsapp.service.ts b/src/whatsapp/services/whatsapp.service.ts index 030285b8..7c50b043 100644 --- a/src/whatsapp/services/whatsapp.service.ts +++ b/src/whatsapp/services/whatsapp.service.ts @@ -828,28 +828,56 @@ export class WAStartupService { } } - if (this.configService.get('WEBSOCKET')?.ENABLED && this.localWebsocket.enabled) { + if (this.configService.get('WEBSOCKET')?.ENABLED) { this.logger.verbose('Sending data to websocket on channel: ' + this.instance.name); - if (Array.isArray(websocketLocal) && websocketLocal.includes(we)) { - this.logger.verbose('Sending data to websocket on event: ' + event); - const io = getIO(); + const io = getIO(); - const message = { - event, - instance: this.instance.name, - data, - server_url: serverUrl, - date_time: now, - sender: this.wuid, - }; + const message = { + event, + instance: this.instance.name, + data, + server_url: serverUrl, + date_time: now, + sender: this.wuid, + }; - if (expose && instanceApikey) { - message['apikey'] = instanceApikey; + if (expose && instanceApikey) { + message['apikey'] = instanceApikey; + } + + if (this.configService.get('WEBSOCKET')?.GLOBAL_EVENTS) { + io.emit(event, message); + + if (this.configService.get('LOG').LEVEL.includes('WEBHOOKS')) { + const logData = { + local: WAStartupService.name + '.sendData-WebsocketGlobal', + event, + instance: this.instance.name, + data, + server_url: serverUrl, + apikey: (expose && instanceApikey) || null, + date_time: now, + sender: this.wuid, + }; + + if (expose && instanceApikey) { + logData['apikey'] = instanceApikey; + } + + this.logger.log(logData); } + } + + if (this.localWebsocket.enabled && Array.isArray(websocketLocal) && websocketLocal.includes(we)) { + this.logger.verbose('Sending data to websocket on event: ' + event); this.logger.verbose('Sending data to socket.io in channel: ' + this.instance.name); io.of(`/${this.instance.name}`).emit(event, message); + if (this.configService.get('WEBSOCKET')?.GLOBAL_EVENTS) { + io.emit(event, message); + } + if (this.configService.get('LOG').LEVEL.includes('WEBHOOKS')) { const logData = { local: WAStartupService.name + '.sendData-Websocket', From 3bc692d894c7ecdd79dee52a1a58853766a0ec22 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Tue, 9 Apr 2024 07:30:15 -0300 Subject: [PATCH 04/42] adjusts in redis --- src/libs/redis.client.ts | 54 +++++++++++-------- .../use-multi-file-auth-state-redis-db.ts | 6 +-- src/whatsapp/services/monitor.service.ts | 2 +- .../services/whatsapp.baileys.service.ts | 3 +- 4 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/libs/redis.client.ts b/src/libs/redis.client.ts index 1d74ff15..c1a0fd84 100644 --- a/src/libs/redis.client.ts +++ b/src/libs/redis.client.ts @@ -43,73 +43,81 @@ export class RedisCache { } } - public async instanceKeys(): Promise { + public async getInstanceKeys(): Promise { const keys: string[] = []; try { this.logger.verbose('Fetching instance keys'); for await (const key of this.client.scanIterator({ MATCH: `${this.redisEnv.PREFIX_KEY}:*` })) { keys.push(key); } + return keys; } catch (error) { this.logger.error('Error fetching instance keys ' + error); + throw error; } - return keys; } public async keyExists(key?: string) { - if (key) { - this.logger.verbose('keyExists: ' + key); - return !!(await this.instanceKeys()).find((i) => i === key); + try { + const keys = await this.getInstanceKeys(); + const targetKey = key || this.instanceName; + this.logger.verbose('keyExists: ' + targetKey); + return keys.includes(targetKey); + } catch (error) { + return false; } - this.logger.verbose('keyExists: ' + this.instanceName); - return !!(await this.instanceKeys()).find((i) => i === this.instanceName); } - public async writeData(field: string, data: any) { + public async setData(field: string, data: any) { try { - this.logger.verbose('writeData: ' + field); + this.logger.verbose('setData: ' + field); const json = JSON.stringify(data, BufferJSON.replacer); - - return await this.client.hSet(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field, json); + await this.client.hSet(`${this.redisEnv.PREFIX_KEY}-${this.instanceName}`, field, json); + return true; } catch (error) { this.logger.error(error); + return false; } } - public async readData(field: string) { + public async getData(field: string): Promise { try { - this.logger.verbose('readData: ' + field); - const data = await this.client.hGet(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field); + this.logger.verbose('getData: ' + field); + const data = await this.client.hGet(`${this.redisEnv.PREFIX_KEY}-${this.instanceName}`, field); if (data) { - this.logger.verbose('readData: ' + field + ' success'); + this.logger.verbose('getData: ' + field + ' success'); return JSON.parse(data, BufferJSON.reviver); } - this.logger.verbose('readData: ' + field + ' not found'); + this.logger.verbose('getData: ' + field + ' not found'); return null; } catch (error) { this.logger.error(error); + return null; } } - public async removeData(field: string) { + public async removeData(field: string): Promise { try { this.logger.verbose('removeData: ' + field); - return await this.client.hDel(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field); + await this.client.hDel(`${this.redisEnv.PREFIX_KEY}-${this.instanceName}`, field); + return true; } catch (error) { this.logger.error(error); + return false; } } - public async delAll(hash?: string) { + public async delAll(hash?: string): Promise { try { - this.logger.verbose('instance delAll: ' + hash); - const result = await this.client.del(hash || this.redisEnv.PREFIX_KEY + ':' + this.instanceName); - - return result; + const targetHash = hash || `${this.redisEnv.PREFIX_KEY}-${this.instanceName}`; + this.logger.verbose('instance delAll: ' + targetHash); + const result = await this.client.del(targetHash); + return !!result; } catch (error) { this.logger.error(error); + return false; } } } diff --git a/src/utils/use-multi-file-auth-state-redis-db.ts b/src/utils/use-multi-file-auth-state-redis-db.ts index 8e685b54..eb88d678 100644 --- a/src/utils/use-multi-file-auth-state-redis-db.ts +++ b/src/utils/use-multi-file-auth-state-redis-db.ts @@ -17,7 +17,7 @@ export async function useMultiFileAuthStateRedisDb(cache: RedisCache): Promise<{ const writeData = async (data: any, key: string): Promise => { try { - return await cache.writeData(key, data); + return await cache.setData(key, data); } catch (error) { return logger.error({ localError: 'writeData', error }); } @@ -25,9 +25,9 @@ export async function useMultiFileAuthStateRedisDb(cache: RedisCache): Promise<{ const readData = async (key: string): Promise => { try { - return await cache.readData(key); + return await cache.getData(key); } catch (error) { - logger.error({ readData: 'writeData', error }); + logger.error({ localError: 'readData', error }); return; } }; diff --git a/src/whatsapp/services/monitor.service.ts b/src/whatsapp/services/monitor.service.ts index e7eb0bc1..f8148926 100644 --- a/src/whatsapp/services/monitor.service.ts +++ b/src/whatsapp/services/monitor.service.ts @@ -375,7 +375,7 @@ export class WAMonitoringService { private async loadInstancesFromRedis() { this.logger.verbose('Redis enabled'); await this.cache.connect(this.redis as Redis); - const keys = await this.cache.instanceKeys(); + const keys = await this.cache.getInstanceKeys(); if (keys?.length > 0) { this.logger.verbose('Reading instance keys and setting instances'); diff --git a/src/whatsapp/services/whatsapp.baileys.service.ts b/src/whatsapp/services/whatsapp.baileys.service.ts index 6ac1e5e6..cd26d84b 100644 --- a/src/whatsapp/services/whatsapp.baileys.service.ts +++ b/src/whatsapp/services/whatsapp.baileys.service.ts @@ -1032,7 +1032,8 @@ export class BaileysStartupService extends WAStartupService { if ( (type !== 'notify' && type !== 'append') || received.message?.protocolMessage || - received.message?.pollUpdateMessage + received.message?.pollUpdateMessage || + !received?.message ) { this.logger.verbose('message rejected'); return; From e153515847fdd2a48c262aff4ec8b3b87967d125 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Tue, 9 Apr 2024 07:31:37 -0300 Subject: [PATCH 05/42] adjusts in redis --- CHANGELOG.md | 11 +++++++++++ src/whatsapp/services/whatsapp.baileys.service.ts | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 960f2f3b..73b07a1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +# 1.7.2 (develop) + +### Feature + +* Mobile connection via sms + +### Fixed + +* Adjusts in redis +* Send global event in websocket + # 1.7.1 (2024-04-03 10:19) ### Fixed diff --git a/src/whatsapp/services/whatsapp.baileys.service.ts b/src/whatsapp/services/whatsapp.baileys.service.ts index cd26d84b..9f0475cd 100644 --- a/src/whatsapp/services/whatsapp.baileys.service.ts +++ b/src/whatsapp/services/whatsapp.baileys.service.ts @@ -617,7 +617,7 @@ export class BaileysStartupService extends WAStartupService { } registration.phoneNumberMobileCountryCode = mcc; - registration.method = 'voice'; + registration.method = 'sms'; try { const response = await this.client.requestRegistrationCode(registration); From 5d951a96b5d4cae02dbc6f5d06461df0e67fa929 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Tue, 9 Apr 2024 07:40:45 -0300 Subject: [PATCH 06/42] adjusts in redis --- src/libs/redis.client.ts | 8 ++++---- .../controllers/instance.controller.ts | 4 ++-- .../services/whatsapp.baileys.service.ts | 19 ++++++++++--------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/libs/redis.client.ts b/src/libs/redis.client.ts index c1a0fd84..4b3e1991 100644 --- a/src/libs/redis.client.ts +++ b/src/libs/redis.client.ts @@ -72,7 +72,7 @@ export class RedisCache { try { this.logger.verbose('setData: ' + field); const json = JSON.stringify(data, BufferJSON.replacer); - await this.client.hSet(`${this.redisEnv.PREFIX_KEY}-${this.instanceName}`, field, json); + await this.client.hSet(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field, json); return true; } catch (error) { this.logger.error(error); @@ -83,7 +83,7 @@ export class RedisCache { public async getData(field: string): Promise { try { this.logger.verbose('getData: ' + field); - const data = await this.client.hGet(`${this.redisEnv.PREFIX_KEY}-${this.instanceName}`, field); + const data = await this.client.hGet(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field); if (data) { this.logger.verbose('getData: ' + field + ' success'); @@ -101,7 +101,7 @@ export class RedisCache { public async removeData(field: string): Promise { try { this.logger.verbose('removeData: ' + field); - await this.client.hDel(`${this.redisEnv.PREFIX_KEY}-${this.instanceName}`, field); + await this.client.hDel(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field); return true; } catch (error) { this.logger.error(error); @@ -111,7 +111,7 @@ export class RedisCache { public async delAll(hash?: string): Promise { try { - const targetHash = hash || `${this.redisEnv.PREFIX_KEY}-${this.instanceName}`; + const targetHash = hash || this.redisEnv.PREFIX_KEY + ':' + this.instanceName; this.logger.verbose('instance delAll: ' + targetHash); const result = await this.client.del(targetHash); return !!result; diff --git a/src/whatsapp/controllers/instance.controller.ts b/src/whatsapp/controllers/instance.controller.ts index c389b819..8fab7f2f 100644 --- a/src/whatsapp/controllers/instance.controller.ts +++ b/src/whatsapp/controllers/instance.controller.ts @@ -641,8 +641,8 @@ export class InstanceController { const instance = this.waMonitor.waInstances[instanceName]; console.log('mobileCode', mobileCode); - return await instance.receiveMobileCode(mobileCode); - // return { status: 'SUCCESS', error: false, response: { message: 'Mobile code registered' } }; + await instance.receiveMobileCode(mobileCode); + return { status: 'SUCCESS', error: false, response: { message: 'Mobile code registered' } }; } catch (error) { this.logger.error(error); } diff --git a/src/whatsapp/services/whatsapp.baileys.service.ts b/src/whatsapp/services/whatsapp.baileys.service.ts index 9f0475cd..e3f698b5 100644 --- a/src/whatsapp/services/whatsapp.baileys.service.ts +++ b/src/whatsapp/services/whatsapp.baileys.service.ts @@ -634,15 +634,16 @@ export class BaileysStartupService extends WAStartupService { } public async receiveMobileCode(code: string) { - await this.client - .register(code.replace(/["']/g, '').trim().toLowerCase()) - .then(async (response) => { - this.logger.verbose('Registration code received successfully'); - console.log(response); - }) - .catch((error) => { - this.logger.error(error); - }); + console.log('code', code); + // await this.client + // .register(code.replace(/["']/g, '').trim().toLowerCase()) + // .then(async (response) => { + // this.logger.verbose('Registration code received successfully'); + // console.log(response); + // }) + // .catch((error) => { + // this.logger.error(error); + // }); } public async reloadConnection(): Promise { From a5477509bd2c555ceaf6d8eca8370ff5b25e1ecd Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Tue, 9 Apr 2024 07:43:20 -0300 Subject: [PATCH 07/42] adjusts in redis --- .../services/whatsapp.baileys.service.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/whatsapp/services/whatsapp.baileys.service.ts b/src/whatsapp/services/whatsapp.baileys.service.ts index e3f698b5..9f0475cd 100644 --- a/src/whatsapp/services/whatsapp.baileys.service.ts +++ b/src/whatsapp/services/whatsapp.baileys.service.ts @@ -634,16 +634,15 @@ export class BaileysStartupService extends WAStartupService { } public async receiveMobileCode(code: string) { - console.log('code', code); - // await this.client - // .register(code.replace(/["']/g, '').trim().toLowerCase()) - // .then(async (response) => { - // this.logger.verbose('Registration code received successfully'); - // console.log(response); - // }) - // .catch((error) => { - // this.logger.error(error); - // }); + await this.client + .register(code.replace(/["']/g, '').trim().toLowerCase()) + .then(async (response) => { + this.logger.verbose('Registration code received successfully'); + console.log(response); + }) + .catch((error) => { + this.logger.error(error); + }); } public async reloadConnection(): Promise { From 589dec52a31a3a1ba65609e7d05d80e4e9df01d3 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Tue, 9 Apr 2024 16:52:22 -0300 Subject: [PATCH 08/42] ajustes proxy --- .../controllers/instance.controller.ts | 15 +++ src/whatsapp/controllers/proxy.controller.ts | 2 +- src/whatsapp/dto/instance.dto.ts | 4 +- src/whatsapp/routers/chat.router.ts | 1 - src/whatsapp/services/typebot.service.ts | 107 +++++++++--------- .../services/whatsapp.baileys.service.ts | 93 +++++++++++++-- src/whatsapp/services/whatsapp.service.ts | 2 +- src/whatsapp/whatsapp.module.ts | 1 + 8 files changed, 157 insertions(+), 68 deletions(-) diff --git a/src/whatsapp/controllers/instance.controller.ts b/src/whatsapp/controllers/instance.controller.ts index 8fab7f2f..cf731064 100644 --- a/src/whatsapp/controllers/instance.controller.ts +++ b/src/whatsapp/controllers/instance.controller.ts @@ -23,6 +23,7 @@ import { WebsocketService } from '../services/websocket.service'; import { BaileysStartupService } from '../services/whatsapp.baileys.service'; import { BusinessStartupService } from '../services/whatsapp.business.service'; import { Events, Integration, wa } from '../types/wa.types'; +import { ProxyController } from './proxy.controller'; export class InstanceController { constructor( @@ -39,6 +40,7 @@ export class InstanceController { private readonly sqsService: SqsService, private readonly typebotService: TypebotService, private readonly integrationService: IntegrationService, + private readonly proxyService: ProxyController, private readonly cache: RedisCache, private readonly chatwootCache: CacheService, ) {} @@ -85,6 +87,7 @@ export class InstanceController { typebot_delay_message, typebot_unknown_message, typebot_listening_from_me, + proxy, }: InstanceDto) { try { this.logger.verbose('requested createInstance from ' + instanceName + ' instance'); @@ -346,6 +349,18 @@ export class InstanceController { } } + if (proxy) { + const testProxy = await this.proxyService.testProxy(proxy); + if (!testProxy) { + throw new BadRequestException('Invalid proxy'); + } + + await this.proxyService.createProxy(instance, { + enabled: true, + proxy, + }); + } + if (typebot_url) { try { if (!isURL(typebot_url, { require_tld: false })) { diff --git a/src/whatsapp/controllers/proxy.controller.ts b/src/whatsapp/controllers/proxy.controller.ts index d826d8c4..7b34a9d9 100644 --- a/src/whatsapp/controllers/proxy.controller.ts +++ b/src/whatsapp/controllers/proxy.controller.ts @@ -46,7 +46,7 @@ export class ProxyController { return this.proxyService.find(instance); } - private async testProxy(proxy: ProxyDto['proxy']) { + public async testProxy(proxy: ProxyDto['proxy']) { logger.verbose('requested testProxy'); try { const serverIp = await axios.get('https://icanhazip.com/'); diff --git a/src/whatsapp/dto/instance.dto.ts b/src/whatsapp/dto/instance.dto.ts index 4b533de1..b703b9da 100644 --- a/src/whatsapp/dto/instance.dto.ts +++ b/src/whatsapp/dto/instance.dto.ts @@ -1,5 +1,7 @@ import { WAPresence } from '@whiskeysockets/baileys'; +import { ProxyDto } from './proxy.dto'; + export class InstanceDto { instanceName: string; instanceId?: string; @@ -41,7 +43,7 @@ export class InstanceDto { typebot_delay_message?: number; typebot_unknown_message?: string; typebot_listening_from_me?: boolean; - proxy?: string; + proxy?: ProxyDto['proxy']; } export class SetPresenceDto { diff --git a/src/whatsapp/routers/chat.router.ts b/src/whatsapp/routers/chat.router.ts index d8096c79..a0ce3216 100644 --- a/src/whatsapp/routers/chat.router.ts +++ b/src/whatsapp/routers/chat.router.ts @@ -9,7 +9,6 @@ import { messageUpSchema, messageValidateSchema, presenceSchema, - presenceOnlySchema, privacySettingsSchema, profileNameSchema, profilePictureSchema, diff --git a/src/whatsapp/services/typebot.service.ts b/src/whatsapp/services/typebot.service.ts index 7336ff24..8c267759 100644 --- a/src/whatsapp/services/typebot.service.ts +++ b/src/whatsapp/services/typebot.service.ts @@ -57,7 +57,7 @@ export class TypebotService { if (session) { if (status === 'closed') { - const found_session : Session[] = findData.sessions.splice(findData.sessions.indexOf(session), 1); + const found_session: Session[] = findData.sessions.splice(findData.sessions.indexOf(session), 1); const typebotData = { enabled: findData.enabled, @@ -269,27 +269,30 @@ export class TypebotService { } private getTypeMessage(msg: any) { - this.logger.verbose('get type message'); - const types = { - conversation: msg.conversation, - extendedTextMessage: msg.extendedTextMessage?.text, - audioMessage: msg.audioMessage?.url, - imageMessage: msg.imageMessage?.url, - videoMessage: msg.videoMessage?.url, - documentMessage: msg.documentMessage?.fileName, - contactMessage: msg.contactMessage?.displayName, - locationMessage: msg.locationMessage?.degreesLatitude, - viewOnceMessageV2: msg.viewOnceMessageV2?.message?.imageMessage?.url || msg.viewOnceMessageV2?.message?.videoMessage?.url || msg.viewOnceMessageV2?.message?.audioMessage?.url, - listResponseMessage: msg.listResponseMessage?.singleSelectReply?.selectedRowId, - responseRowId: msg.listResponseMessage?.singleSelectReply?.selectedRowId, - }; + this.logger.verbose('get type message'); + const types = { + conversation: msg.conversation, + extendedTextMessage: msg.extendedTextMessage?.text, + audioMessage: msg.audioMessage?.url, + imageMessage: msg.imageMessage?.url, + videoMessage: msg.videoMessage?.url, + documentMessage: msg.documentMessage?.fileName, + contactMessage: msg.contactMessage?.displayName, + locationMessage: msg.locationMessage?.degreesLatitude, + viewOnceMessageV2: + msg.viewOnceMessageV2?.message?.imageMessage?.url || + msg.viewOnceMessageV2?.message?.videoMessage?.url || + msg.viewOnceMessageV2?.message?.audioMessage?.url, + listResponseMessage: msg.listResponseMessage?.singleSelectReply?.selectedRowId, + responseRowId: msg.listResponseMessage?.singleSelectReply?.selectedRowId, + }; - const messageType = Object.keys(types).find(key => types[key] !== undefined) || 'unknown'; - - this.logger.verbose('Type message: ' + JSON.stringify(types)); - return { ...types, messageType }; + const messageType = Object.keys(types).find((key) => types[key] !== undefined) || 'unknown'; + + this.logger.verbose('Type message: ' + JSON.stringify(types)); + return { ...types, messageType }; } - + private getMessageContent(types: any) { this.logger.verbose('get message content'); const typeKey = Object.keys(types).find((key) => types[key] !== undefined); @@ -317,7 +320,7 @@ export class TypebotService { this.logger.verbose('get audio message content'); const types = this.getTypeMessage(msg); - + const audioContent = types.audioMessage; this.logger.verbose('audio message URL: ' + audioContent); @@ -327,85 +330,85 @@ export class TypebotService { private getImageMessageContent(msg: any) { this.logger.verbose('get image message content'); - + const types = this.getTypeMessage(msg); - + const imageContent = types.imageMessage; - + this.logger.verbose('image message URL: ' + imageContent); - + return imageContent; } - + private getVideoMessageContent(msg: any) { this.logger.verbose('get video message content'); - + const types = this.getTypeMessage(msg); - + const videoContent = types.videoMessage; - + this.logger.verbose('video message URL: ' + videoContent); - + return videoContent; } - + private getDocumentMessageContent(msg: any) { this.logger.verbose('get document message content'); - + const types = this.getTypeMessage(msg); - + const documentContent = types.documentMessage; - + this.logger.verbose('document message fileName: ' + documentContent); - + return documentContent; } private getContactMessageContent(msg: any) { this.logger.verbose('get contact message content'); - + const types = this.getTypeMessage(msg); - + const contactContent = types.contactMessage; - + this.logger.verbose('contact message displayName: ' + contactContent); - + return contactContent; } private getLocationMessageContent(msg: any) { this.logger.verbose('get location message content'); - + const types = this.getTypeMessage(msg); - + const locationContent = types.locationMessage; - + this.logger.verbose('location message degreesLatitude: ' + locationContent); - + return locationContent; } private getViewOnceMessageV2Content(msg: any) { this.logger.verbose('get viewOnceMessageV2 content'); - + const types = this.getTypeMessage(msg); - + const viewOnceContent = types.viewOnceMessageV2; - + this.logger.verbose('viewOnceMessageV2 URL: ' + viewOnceContent); - + return viewOnceContent; } private getListResponseMessageContent(msg: any) { this.logger.verbose('get listResponseMessage content'); - + const types = this.getTypeMessage(msg); - + const listResponseContent = types.listResponseMessage || types.responseRowId; - + this.logger.verbose('listResponseMessage selectedRowId: ' + listResponseContent); - + return listResponseContent; } public async createNewSession(instance: InstanceDto, data: any) { @@ -791,7 +794,7 @@ export class TypebotService { sessions: sessions, remoteJid: remoteJid, pushName: msg.pushName, - prefilledVariables: { + prefilledVariables: { messageType: messageType, }, }); diff --git a/src/whatsapp/services/whatsapp.baileys.service.ts b/src/whatsapp/services/whatsapp.baileys.service.ts index 9f0475cd..088548e2 100644 --- a/src/whatsapp/services/whatsapp.baileys.service.ts +++ b/src/whatsapp/services/whatsapp.baileys.service.ts @@ -12,7 +12,6 @@ import makeWASocket, { DisconnectReason, downloadMediaMessage, fetchLatestBaileysVersion, - generateMobileNode, generateWAMessageFromContent, getAggregateVotesInPollMessage, getContentType, @@ -486,7 +485,7 @@ export class BaileysStartupService extends WAStartupService { let options; if (this.localProxy.enabled) { - this.logger.info('Proxy enabled: ' + this.localProxy.proxy); + this.logger.info('Proxy enabled: ' + this.localProxy.proxy.host); if (this.localProxy?.proxy?.host?.includes('proxyscrape')) { try { @@ -656,11 +655,26 @@ export class BaileysStartupService extends WAStartupService { let options; if (this.localProxy.enabled) { - this.logger.verbose('Proxy enabled'); - options = { - agent: makeProxyAgent(this.localProxy.proxy), - fetchAgent: makeProxyAgent(this.localProxy.proxy), - }; + this.logger.info('Proxy enabled: ' + this.localProxy.proxy.host); + + if (this.localProxy?.proxy?.host?.includes('proxyscrape')) { + try { + const response = await axios.get(this.localProxy.proxy.host); + const text = response.data; + const proxyUrls = text.split('\r\n'); + const rand = Math.floor(Math.random() * Math.floor(proxyUrls.length)); + const proxyUrl = 'http://' + proxyUrls[rand]; + options = { + agent: makeProxyAgent(proxyUrl), + }; + } catch (error) { + this.localProxy.enabled = false; + } + } else { + options = { + agent: makeProxyAgent(this.localProxy.proxy), + }; + } } const socketConfig: UserFacingSocketConfig = { @@ -2147,7 +2161,18 @@ export class BaileysStartupService extends WAStartupService { mimetype = getMIMEType(mediaMessage.fileName); if (!mimetype && isURL(mediaMessage.media)) { - const response = await axios.get(mediaMessage.media, { responseType: 'arraybuffer' }); + let config: any = { + responseType: 'arraybuffer', + }; + + if (this.localProxy.enabled) { + config = { + ...config, + httpsAgent: makeProxyAgent(this.localProxy.proxy), + }; + } + + const response = await axios.get(mediaMessage.media, config); mimetype = response.headers['content-type']; } @@ -2216,7 +2241,18 @@ export class BaileysStartupService extends WAStartupService { const url = `${image}?timestamp=${timestamp}`; this.logger.verbose('including timestamp in url: ' + url); - const response = await axios.get(url, { responseType: 'arraybuffer' }); + let config: any = { + responseType: 'arraybuffer', + }; + + if (this.localProxy.enabled) { + config = { + ...config, + httpsAgent: makeProxyAgent(this.localProxy.proxy), + }; + } + + const response = await axios.get(url, config); this.logger.verbose('Getting image from url'); const imageBuffer = Buffer.from(response.data, 'binary'); @@ -2286,7 +2322,18 @@ export class BaileysStartupService extends WAStartupService { this.logger.verbose('Including timestamp in url: ' + url); - const response = await axios.get(url, { responseType: 'arraybuffer' }); + let config: any = { + responseType: 'arraybuffer', + }; + + if (this.localProxy.enabled) { + config = { + ...config, + httpsAgent: makeProxyAgent(this.localProxy.proxy), + }; + } + + const response = await axios.get(url, config); this.logger.verbose('Getting audio from url'); fs.writeFileSync(tempAudioPath, response.data); @@ -2920,7 +2967,18 @@ export class BaileysStartupService extends WAStartupService { const url = `${picture}?timestamp=${timestamp}`; this.logger.verbose('Including timestamp in url: ' + url); - pic = (await axios.get(url, { responseType: 'arraybuffer' })).data; + let config: any = { + responseType: 'arraybuffer', + }; + + if (this.localProxy.enabled) { + config = { + ...config, + httpsAgent: makeProxyAgent(this.localProxy.proxy), + }; + } + + pic = (await axios.get(url, config)).data; this.logger.verbose('Getting picture from url'); } else if (isBase64(picture)) { this.logger.verbose('Picture is base64'); @@ -3080,7 +3138,18 @@ export class BaileysStartupService extends WAStartupService { const url = `${picture.image}?timestamp=${timestamp}`; this.logger.verbose('Including timestamp in url: ' + url); - pic = (await axios.get(url, { responseType: 'arraybuffer' })).data; + let config: any = { + responseType: 'arraybuffer', + }; + + if (this.localProxy.enabled) { + config = { + ...config, + httpsAgent: makeProxyAgent(this.localProxy.proxy), + }; + } + + pic = (await axios.get(url, config)).data; this.logger.verbose('Getting picture from url'); } else if (isBase64(picture.image)) { this.logger.verbose('Picture is base64'); diff --git a/src/whatsapp/services/whatsapp.service.ts b/src/whatsapp/services/whatsapp.service.ts index 7c50b043..eaa4dc65 100644 --- a/src/whatsapp/services/whatsapp.service.ts +++ b/src/whatsapp/services/whatsapp.service.ts @@ -583,7 +583,7 @@ export class WAStartupService { this.logger.verbose(`Proxy enabled: ${this.localProxy.enabled}`); this.localProxy.proxy = data?.proxy; - this.logger.verbose(`Proxy proxy: ${this.localProxy.proxy}`); + this.logger.verbose(`Proxy proxy: ${this.localProxy.proxy.host}`); this.logger.verbose('Proxy loaded'); } diff --git a/src/whatsapp/whatsapp.module.ts b/src/whatsapp/whatsapp.module.ts index c3fe2665..366988e2 100644 --- a/src/whatsapp/whatsapp.module.ts +++ b/src/whatsapp/whatsapp.module.ts @@ -167,6 +167,7 @@ export const instanceController = new InstanceController( sqsService, typebotService, integrationService, + proxyController, cache, chatwootCache, ); From 3e85af958962ac26e9f6fe6b1baace71f15d00a8 Mon Sep 17 00:00:00 2001 From: jaison-x Date: Tue, 26 Mar 2024 15:42:32 -0300 Subject: [PATCH 09/42] fix(chatwoot): fix when receiving/sending messages from whatsapp desktop with ephemeral messages enabled --- src/whatsapp/services/chatwoot.service.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/whatsapp/services/chatwoot.service.ts b/src/whatsapp/services/chatwoot.service.ts index 43d8f5be..0fb6272e 100644 --- a/src/whatsapp/services/chatwoot.service.ts +++ b/src/whatsapp/services/chatwoot.service.ts @@ -1774,6 +1774,13 @@ export class ChatwootService { return; } + // fix when receiving/sending messages from whatsapp desktop with ephemeral messages enabled + if (body.message?.ephemeralMessage?.message) { + body.message = { + ...body.message?.ephemeralMessage?.message, + }; + } + this.logger.verbose('get conversation message'); // Whatsapp to Chatwoot From 6e2a3a410a91d8cd7e7945083f12eecf260e7316 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 12 Apr 2024 11:20:18 -0300 Subject: [PATCH 10/42] fix: audio encoding --- CHANGELOG.md | 1 + .../services/whatsapp.baileys.service.ts | 34 ++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73b07a1c..8d375397 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Adjusts in redis * Send global event in websocket +* Fix audio encoding # 1.7.1 (2024-04-03 10:19) diff --git a/src/whatsapp/services/whatsapp.baileys.service.ts b/src/whatsapp/services/whatsapp.baileys.service.ts index 088548e2..0e5a5a75 100644 --- a/src/whatsapp/services/whatsapp.baileys.service.ts +++ b/src/whatsapp/services/whatsapp.baileys.service.ts @@ -39,9 +39,9 @@ import makeWASocket, { import { Label } from '@whiskeysockets/baileys/lib/Types/Label'; import { LabelAssociation } from '@whiskeysockets/baileys/lib/Types/LabelAssociation'; import axios from 'axios'; -import { exec } from 'child_process'; import { arrayUnique, isBase64, isURL } from 'class-validator'; import EventEmitter2 from 'eventemitter2'; +import ffmpeg from 'fluent-ffmpeg'; import fs, { existsSync, readFileSync } from 'fs'; import { parsePhoneNumber } from 'libphonenumber-js'; import Long from 'long'; @@ -2311,7 +2311,7 @@ export class BaileysStartupService extends WAStartupService { if (isURL(audio)) { this.logger.verbose('Audio is url'); - outputAudio = `${join(this.storePath, 'temp', `${hash}.mp4`)}`; + outputAudio = `${join(this.storePath, 'temp', `${hash}.ogg`)}`; tempAudioPath = `${join(this.storePath, 'temp', `temp-${hash}.mp3`)}`; this.logger.verbose('Output audio path: ' + outputAudio); @@ -2340,7 +2340,7 @@ export class BaileysStartupService extends WAStartupService { } else { this.logger.verbose('Audio is base64'); - outputAudio = `${join(this.storePath, 'temp', `${hash}.mp4`)}`; + outputAudio = `${join(this.storePath, 'temp', `${hash}.ogg`)}`; tempAudioPath = `${join(this.storePath, 'temp', `temp-${hash}.mp3`)}`; this.logger.verbose('Output audio path: ' + outputAudio); @@ -2353,15 +2353,25 @@ export class BaileysStartupService extends WAStartupService { this.logger.verbose('Converting audio to mp4'); return new Promise((resolve, reject) => { - exec(`${ffmpegPath.path} -i ${tempAudioPath} -vn -ab 128k -ar 44100 -f ipod ${outputAudio} -y`, (error) => { - fs.unlinkSync(tempAudioPath); - this.logger.verbose('Temp audio deleted'); + // This fix was suggested by @PurpShell + ffmpeg.setFfmpegPath(ffmpegPath.path); - if (error) reject(error); - - this.logger.verbose('Audio converted to mp4'); - resolve(outputAudio); - }); + ffmpeg() + .input(tempAudioPath) + .outputFormat('ogg') + .noVideo() + .audioCodec('libopus') + .save(outputAudio) + .on('error', function (error) { + console.log('error', error); + fs.unlinkSync(tempAudioPath); + if (error) reject(error); + }) + .on('end', async function () { + fs.unlinkSync(tempAudioPath); + resolve(outputAudio); + }) + .run(); }); } @@ -2381,7 +2391,7 @@ export class BaileysStartupService extends WAStartupService { { audio: Buffer.from(audio, 'base64'), ptt: true, - mimetype: 'audio/mp4', + mimetype: 'audio/ogg; codecs=opus', }, { presence: 'recording', delay: data?.options?.delay }, isChatwoot, From 28581f88b2083ae09ee37cbaacaef6c64a82449c Mon Sep 17 00:00:00 2001 From: jaison-x Date: Fri, 12 Apr 2024 10:51:36 -0300 Subject: [PATCH 11/42] fix(chatwoot): fix conversation read on chatwoot version 3.7 if contact has more than one conversation, we could get the wrong conversation. --- src/whatsapp/services/chatwoot.service.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/whatsapp/services/chatwoot.service.ts b/src/whatsapp/services/chatwoot.service.ts index 0fb6272e..d2c1f139 100644 --- a/src/whatsapp/services/chatwoot.service.ts +++ b/src/whatsapp/services/chatwoot.service.ts @@ -1,4 +1,12 @@ -import ChatwootClient, { ChatwootAPIConfig, contact, conversation, generic_id, inbox } from '@figuro/chatwoot-sdk'; +import ChatwootClient, { + ChatwootAPIConfig, + contact, + contact_inboxes, + conversation, + conversation_show, + generic_id, + inbox, +} from '@figuro/chatwoot-sdk'; import { request as chatwootRequest } from '@figuro/chatwoot-sdk/dist/core/request'; import axios from 'axios'; import FormData from 'form-data'; @@ -2130,12 +2138,13 @@ export class ChatwootService { }; if (!sourceId && inbox) { - const contact = (await this.findContact( - instance, - this.getNumberFromRemoteJid(body.key.remoteJid), - )) as contact; - const contactInbox = contact?.contact_inboxes?.find((contactInbox) => contactInbox?.inbox?.id === inbox.id); - sourceId = contactInbox?.source_id; + const conversation = (await client.conversations.get({ + accountId: this.provider.account_id, + conversationId: conversationId, + })) as conversation_show & { + last_non_activity_message: { conversation: { contact_inbox: contact_inboxes } }; + }; + sourceId = conversation.last_non_activity_message?.conversation?.contact_inbox?.source_id; } if (sourceId && inbox?.inbox_identifier) { From 0edf6bdcb13d92f4aa124cde4bc029998a6f2ca9 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 12 Apr 2024 12:00:14 -0300 Subject: [PATCH 12/42] fix: audio encoding --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index c1d8ddd2..aaef4f8a 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "exiftool-vendored": "^22.0.0", "express": "^4.18.2", "express-async-errors": "^3.1.1", + "fluent-ffmpeg": "^2.1.2", "form-data": "^4.0.0", "hbs": "^4.2.0", "https-proxy-agent": "^7.0.2", From d5d8f2a318fd61234bd1f3e101a9fcb2c5facc8c Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 12 Apr 2024 12:33:31 -0300 Subject: [PATCH 13/42] fix: send contact.upsert via webhook --- CHANGELOG.md | 5 ++++- src/whatsapp/services/whatsapp.baileys.service.ts | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d375397..c35ec8c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,16 @@ ### Feature -* Mobile connection via sms +* Mobile connection via sms (test) ### Fixed * Adjusts in redis * Send global event in websocket * Fix audio encoding +* Fix conversation read on chatwoot version 3.7 +* Fix when receiving/sending messages from whatsapp desktop with ephemeral messages enabled +* Changed returned sessions on typebot status change # 1.7.1 (2024-04-03 10:19) diff --git a/src/whatsapp/services/whatsapp.baileys.service.ts b/src/whatsapp/services/whatsapp.baileys.service.ts index 0e5a5a75..e4a2ce09 100644 --- a/src/whatsapp/services/whatsapp.baileys.service.ts +++ b/src/whatsapp/services/whatsapp.baileys.service.ts @@ -829,7 +829,7 @@ export class BaileysStartupService extends WAStartupService { } this.logger.verbose('Sending data to webhook in event CONTACTS_UPSERT'); - this.sendDataWebhook(Events.CONTACTS_UPSERT, contactsRaw); + if (contactsRaw.length > 0) this.sendDataWebhook(Events.CONTACTS_UPSERT, contactsRaw); this.logger.verbose('Inserting contacts in database'); this.repository.contact.insert(contactsRaw, this.instance.name, database.SAVE_DATA.CONTACTS); @@ -851,7 +851,7 @@ export class BaileysStartupService extends WAStartupService { } this.logger.verbose('Sending data to webhook in event CONTACTS_UPDATE'); - this.sendDataWebhook(Events.CONTACTS_UPSERT, contactsRaw); + if (contactsRaw.length > 0) this.sendDataWebhook(Events.CONTACTS_UPSERT, contactsRaw); this.logger.verbose('Updating contacts in database'); this.repository.contact.update(contactsRaw, this.instance.name, database.SAVE_DATA.CONTACTS); From 86e978faad36c5c7140916d95f2280832044e703 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 12 Apr 2024 12:51:13 -0300 Subject: [PATCH 14/42] fix: send contact.upsert via webhook --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c35ec8c1..f86bcbfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Adjusts in redis * Send global event in websocket +* Adjusts in proxy * Fix audio encoding * Fix conversation read on chatwoot version 3.7 * Fix when receiving/sending messages from whatsapp desktop with ephemeral messages enabled From ef4a9ab66b478b83b616c2cbf4c5c81864724e60 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 12 Apr 2024 15:11:04 -0300 Subject: [PATCH 15/42] fix: retry messages --- .../services/whatsapp.baileys.service.ts | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/whatsapp/services/whatsapp.baileys.service.ts b/src/whatsapp/services/whatsapp.baileys.service.ts index e4a2ce09..d38c6d8b 100644 --- a/src/whatsapp/services/whatsapp.baileys.service.ts +++ b/src/whatsapp/services/whatsapp.baileys.service.ts @@ -120,7 +120,7 @@ import { waMonitor } from '../whatsapp.module'; import { CacheService } from './cache.service'; import { WAStartupService } from './whatsapp.service'; -const retryCache = {}; +// const retryCache = {}; export class BaileysStartupService extends WAStartupService { constructor( @@ -1472,27 +1472,27 @@ export class BaileysStartupService extends WAStartupService { if (events['messages.upsert']) { this.logger.verbose('Listening event: messages.upsert'); const payload = events['messages.upsert']; - if (payload.messages.find((a) => a?.messageStubType === 2)) { - const msg = payload.messages[0]; - retryCache[msg.key.id] = msg; - return; - } + // if (payload.messages.find((a) => a?.messageStubType === 2)) { + // const msg = payload.messages[0]; + // retryCache[msg.key.id] = msg; + // return; + // } this.messageHandle['messages.upsert'](payload, database, settings); } if (events['messages.update']) { this.logger.verbose('Listening event: messages.update'); const payload = events['messages.update']; - payload.forEach((message) => { - if (retryCache[message.key.id]) { - this.client.ev.emit('messages.upsert', { - messages: [message], - type: 'notify', - }); - delete retryCache[message.key.id]; - return; - } - }); + // payload.forEach((message) => { + // if (retryCache[message.key.id]) { + // this.client.ev.emit('messages.upsert', { + // messages: [message], + // type: 'notify', + // }); + // delete retryCache[message.key.id]; + // return; + // } + // }); this.messageHandle['messages.update'](payload, database, settings); } From 794213b5c6b095926ab8da3e65ecdc8e84ce8515 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 12 Apr 2024 15:53:06 -0300 Subject: [PATCH 16/42] fix: quoted messages --- src/whatsapp/services/whatsapp.baileys.service.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/whatsapp/services/whatsapp.baileys.service.ts b/src/whatsapp/services/whatsapp.baileys.service.ts index d38c6d8b..4cf9f4e2 100644 --- a/src/whatsapp/services/whatsapp.baileys.service.ts +++ b/src/whatsapp/services/whatsapp.baileys.service.ts @@ -1772,12 +1772,10 @@ export class BaileysStartupService extends WAStartupService { const msg = m?.message ? m : ((await this.getMessage(m.key, true)) as proto.IWebMessageInfo); - if (!msg) { - throw 'Message not found'; + if (msg) { + quoted = msg; + this.logger.verbose('Quoted message'); } - - quoted = msg; - this.logger.verbose('Quoted message'); } let mentions: string[]; From 8ece6fb9981e403ffb1ee81a718596d1debe9ff1 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 12 Apr 2024 17:13:15 -0300 Subject: [PATCH 17/42] fix: reorganization of files and folders --- CHANGELOG.md | 1 + package.json | 2 +- .../abstract/abstract.cache.ts | 0 .../abstract/abstract.repository.ts | 0 .../abstract/abstract.router.ts | 0 .../controllers/chamaai.controller.ts | 0 .../controllers/chat.controller.ts | 0 .../controllers/group.controller.ts | 0 .../controllers/instance.controller.ts | 10 +- .../controllers/label.controller.ts | 0 .../controllers/proxy.controller.ts | 0 .../controllers/sendMessage.controller.ts | 0 .../controllers/settings.controller.ts | 0 .../controllers/webhook.controller.ts | 0 src/{whatsapp => api}/dto/chamaai.dto.ts | 0 src/{whatsapp => api}/dto/chat.dto.ts | 0 src/{whatsapp => api}/dto/group.dto.ts | 0 src/{whatsapp => api}/dto/instance.dto.ts | 0 src/{whatsapp => api}/dto/integration.dto.ts | 0 src/{whatsapp => api}/dto/label.dto.ts | 0 src/{whatsapp => api}/dto/proxy.dto.ts | 0 src/{whatsapp => api}/dto/sendMessage.dto.ts | 0 src/{whatsapp => api}/dto/settings.dto.ts | 0 src/{whatsapp => api}/dto/webhook.dto.ts | 0 src/{whatsapp => api}/guards/auth.guard.ts | 2 +- .../guards/instance.guard.ts | 2 +- .../chatwoot/cache}/cacheengine.ts | 4 +- .../chatwoot/cache}/localcache.ts | 4 +- .../chatwoot/cache}/rediscache.client.ts | 4 +- .../chatwoot/cache}/rediscache.ts | 6 +- .../controllers/chatwoot.controller.ts | 16 +- .../chatwoot}/dto/chatwoot.dto.ts | 0 .../chatwoot}/libs/postgres.client.ts | 4 +- .../chatwoot}/models/chatwoot.model.ts | 2 +- .../repository/chatwoot.repository.ts | 8 +- .../chatwoot/routes}/chatwoot.router.ts | 12 +- .../chatwoot}/services/chatwoot.service.ts | 22 +-- .../chatwoot}/utils/chatwoot-import-helper.ts | 10 +- .../chatwoot/validate/chatwoot.schema.ts | 42 +++++ .../controllers/rabbitmq.controller.ts | 4 +- .../rabbitmq}/dto/rabbitmq.dto.ts | 0 .../rabbitmq}/libs/amqp.server.ts | 4 +- .../rabbitmq}/models/rabbitmq.model.ts | 2 +- .../repository/rabbitmq.repository.ts | 8 +- .../rabbitmq/routes}/rabbitmq.router.ts | 12 +- .../rabbitmq}/services/rabbitmq.service.ts | 10 +- .../rabbitmq/validate/rabbitmq.schema.ts | 66 ++++++++ .../sqs}/controllers/sqs.controller.ts | 4 +- .../integrations/sqs}/dto/sqs.dto.ts | 0 .../integrations/sqs}/libs/sqs.server.ts | 4 +- .../integrations/sqs}/models/sqs.model.ts | 2 +- .../sqs}/repository/sqs.repository.ts | 8 +- .../integrations/sqs/routes}/sqs.router.ts | 12 +- .../integrations/sqs}/services/sqs.service.ts | 10 +- .../integrations/sqs/validate/sqs.schema.ts | 66 ++++++++ .../controllers/typebot.controller.ts | 4 +- .../integrations/typebot}/dto/typebot.dto.ts | 0 .../typebot}/models/typebot.model.ts | 2 +- .../typebot}/repository/typebot.repository.ts | 8 +- .../typebot/routes}/typebot.router.ts | 12 +- .../typebot}/services/typebot.service.ts | 12 +- .../typebot/validate/typebot.schema.ts | 60 +++++++ .../controllers/websocket.controller.ts | 4 +- .../websocket}/dto/websocket.dto.ts | 0 .../websocket}/libs/socket.server.ts | 4 +- .../websocket}/models/websocket.model.ts | 2 +- .../repository/websocket.repository.ts | 8 +- .../websocket/routes}/websocket.router.ts | 12 +- .../websocket}/services/websocket.service.ts | 8 +- .../websocket/validate/websocket.schema.ts | 66 ++++++++ src/{whatsapp => api}/models/auth.model.ts | 0 src/{whatsapp => api}/models/chamaai.model.ts | 0 src/{whatsapp => api}/models/chat.model.ts | 0 src/{whatsapp => api}/models/contact.model.ts | 0 src/{whatsapp => api}/models/index.ts | 10 +- .../models/integration.model.ts | 0 src/{whatsapp => api}/models/label.model.ts | 0 src/{whatsapp => api}/models/message.model.ts | 0 src/{whatsapp => api}/models/proxy.model.ts | 0 .../models/settings.model.ts | 0 src/{whatsapp => api}/models/webhook.model.ts | 0 .../repository/auth.repository.ts | 0 .../repository/chamaai.repository.ts | 0 .../repository/chat.repository.ts | 0 .../repository/contact.repository.ts | 0 .../repository/integration.repository.ts | 0 .../repository/label.repository.ts | 0 .../repository/message.repository.ts | 0 .../repository/messageUp.repository.ts | 0 .../repository/proxy.repository.ts | 0 .../repository/repository.manager.ts | 10 +- .../repository/settings.repository.ts | 0 .../repository/webhook.repository.ts | 0 .../routers/chamaai.router.ts | 2 +- src/{whatsapp => api}/routers/chat.router.ts | 2 +- src/{whatsapp => api}/routers/group.router.ts | 2 +- src/{whatsapp => api}/routers/index.router.ts | 10 +- .../routers/instance.router.ts | 2 +- src/{whatsapp => api}/routers/label.router.ts | 2 +- src/{whatsapp => api}/routers/proxy.router.ts | 2 +- .../routers/sendMessage.router.ts | 2 +- .../routers/settings.router.ts | 2 +- src/{whatsapp => api}/routers/view.router.ts | 0 .../routers/webhook.router.ts | 2 +- .../server.module.ts} | 32 ++-- .../services/auth.service.ts | 0 .../services/cache.service.ts | 0 .../services/chamaai.service.ts | 0 .../services/integration.service.ts | 0 .../services/monitor.service.ts | 0 .../services/proxy.service.ts | 0 .../services/settings.service.ts | 0 .../services/webhook.service.ts | 0 .../services/whatsapp.baileys.service.ts | 4 +- .../services/whatsapp.business.service.ts | 0 .../services/whatsapp.service.ts | 16 +- src/{whatsapp => api}/types/wa.types.ts | 0 src/exceptions/400.exception.ts | 2 +- src/exceptions/401.exception.ts | 2 +- src/exceptions/403.exception.ts | 2 +- src/exceptions/404.exception.ts | 2 +- src/exceptions/500.exception.ts | 2 +- src/main.ts | 10 +- src/utils/makeProxyAgent.ts | 2 +- src/validate/validate.schema.ts | 156 +----------------- 125 files changed, 500 insertions(+), 343 deletions(-) rename src/{whatsapp => api}/abstract/abstract.cache.ts (100%) rename src/{whatsapp => api}/abstract/abstract.repository.ts (100%) rename src/{whatsapp => api}/abstract/abstract.router.ts (100%) rename src/{whatsapp => api}/controllers/chamaai.controller.ts (100%) rename src/{whatsapp => api}/controllers/chat.controller.ts (100%) rename src/{whatsapp => api}/controllers/group.controller.ts (100%) rename src/{whatsapp => api}/controllers/instance.controller.ts (98%) rename src/{whatsapp => api}/controllers/label.controller.ts (100%) rename src/{whatsapp => api}/controllers/proxy.controller.ts (100%) rename src/{whatsapp => api}/controllers/sendMessage.controller.ts (100%) rename src/{whatsapp => api}/controllers/settings.controller.ts (100%) rename src/{whatsapp => api}/controllers/webhook.controller.ts (100%) rename src/{whatsapp => api}/dto/chamaai.dto.ts (100%) rename src/{whatsapp => api}/dto/chat.dto.ts (100%) rename src/{whatsapp => api}/dto/group.dto.ts (100%) rename src/{whatsapp => api}/dto/instance.dto.ts (100%) rename src/{whatsapp => api}/dto/integration.dto.ts (100%) rename src/{whatsapp => api}/dto/label.dto.ts (100%) rename src/{whatsapp => api}/dto/proxy.dto.ts (100%) rename src/{whatsapp => api}/dto/sendMessage.dto.ts (100%) rename src/{whatsapp => api}/dto/settings.dto.ts (100%) rename src/{whatsapp => api}/dto/webhook.dto.ts (100%) rename src/{whatsapp => api}/guards/auth.guard.ts (98%) rename src/{whatsapp => api}/guards/instance.guard.ts (97%) rename src/{libs => api/integrations/chatwoot/cache}/cacheengine.ts (81%) rename src/{libs => api/integrations/chatwoot/cache}/localcache.ts (89%) rename src/{libs => api/integrations/chatwoot/cache}/rediscache.client.ts (90%) rename src/{libs => api/integrations/chatwoot/cache}/rediscache.ts (90%) rename src/{whatsapp => api/integrations/chatwoot}/controllers/chatwoot.controller.ts (86%) rename src/{whatsapp => api/integrations/chatwoot}/dto/chatwoot.dto.ts (100%) rename src/{ => api/integrations/chatwoot}/libs/postgres.client.ts (88%) rename src/{whatsapp => api/integrations/chatwoot}/models/chatwoot.model.ts (95%) rename src/{whatsapp => api/integrations/chatwoot}/repository/chatwoot.repository.ts (87%) rename src/{whatsapp/routers => api/integrations/chatwoot/routes}/chatwoot.router.ts (84%) rename src/{whatsapp => api/integrations/chatwoot}/services/chatwoot.service.ts (99%) rename src/{ => api/integrations/chatwoot}/utils/chatwoot-import-helper.ts (98%) create mode 100644 src/api/integrations/chatwoot/validate/chatwoot.schema.ts rename src/{whatsapp => api/integrations/rabbitmq}/controllers/rabbitmq.controller.ts (93%) rename src/{whatsapp => api/integrations/rabbitmq}/dto/rabbitmq.dto.ts (100%) rename src/{ => api/integrations/rabbitmq}/libs/amqp.server.ts (94%) rename src/{whatsapp => api/integrations/rabbitmq}/models/rabbitmq.model.ts (88%) rename src/{whatsapp => api/integrations/rabbitmq}/repository/rabbitmq.repository.ts (87%) rename src/{whatsapp/routers => api/integrations/rabbitmq/routes}/rabbitmq.router.ts (79%) rename src/{whatsapp => api/integrations/rabbitmq}/services/rabbitmq.service.ts (77%) create mode 100644 src/api/integrations/rabbitmq/validate/rabbitmq.schema.ts rename src/{whatsapp => api/integrations/sqs}/controllers/sqs.controller.ts (92%) rename src/{whatsapp => api/integrations/sqs}/dto/sqs.dto.ts (100%) rename src/{ => api/integrations/sqs}/libs/sqs.server.ts (94%) rename src/{whatsapp => api/integrations/sqs}/models/sqs.model.ts (87%) rename src/{whatsapp => api/integrations/sqs}/repository/sqs.repository.ts (87%) rename src/{whatsapp/routers => api/integrations/sqs/routes}/sqs.router.ts (79%) rename src/{whatsapp => api/integrations/sqs}/services/sqs.service.ts (76%) create mode 100644 src/api/integrations/sqs/validate/sqs.schema.ts rename src/{whatsapp => api/integrations/typebot}/controllers/typebot.controller.ts (92%) rename src/{whatsapp => api/integrations/typebot}/dto/typebot.dto.ts (100%) rename src/{whatsapp => api/integrations/typebot}/models/typebot.model.ts (96%) rename src/{whatsapp => api/integrations/typebot}/repository/typebot.repository.ts (88%) rename src/{whatsapp/routers => api/integrations/typebot/routes}/typebot.router.ts (88%) rename src/{whatsapp => api/integrations/typebot}/services/typebot.service.ts (98%) create mode 100644 src/api/integrations/typebot/validate/typebot.schema.ts rename src/{whatsapp => api/integrations/websocket}/controllers/websocket.controller.ts (93%) rename src/{whatsapp => api/integrations/websocket}/dto/websocket.dto.ts (100%) rename src/{ => api/integrations/websocket}/libs/socket.server.ts (86%) rename src/{whatsapp => api/integrations/websocket}/models/websocket.model.ts (89%) rename src/{whatsapp => api/integrations/websocket}/repository/websocket.repository.ts (87%) rename src/{whatsapp/routers => api/integrations/websocket/routes}/websocket.router.ts (79%) rename src/{whatsapp => api/integrations/websocket}/services/websocket.service.ts (79%) create mode 100644 src/api/integrations/websocket/validate/websocket.schema.ts rename src/{whatsapp => api}/models/auth.model.ts (100%) rename src/{whatsapp => api}/models/chamaai.model.ts (100%) rename src/{whatsapp => api}/models/chat.model.ts (100%) rename src/{whatsapp => api}/models/contact.model.ts (100%) rename src/{whatsapp => api}/models/index.ts (51%) rename src/{whatsapp => api}/models/integration.model.ts (100%) rename src/{whatsapp => api}/models/label.model.ts (100%) rename src/{whatsapp => api}/models/message.model.ts (100%) rename src/{whatsapp => api}/models/proxy.model.ts (100%) rename src/{whatsapp => api}/models/settings.model.ts (100%) rename src/{whatsapp => api}/models/webhook.model.ts (100%) rename src/{whatsapp => api}/repository/auth.repository.ts (100%) rename src/{whatsapp => api}/repository/chamaai.repository.ts (100%) rename src/{whatsapp => api}/repository/chat.repository.ts (100%) rename src/{whatsapp => api}/repository/contact.repository.ts (100%) rename src/{whatsapp => api}/repository/integration.repository.ts (100%) rename src/{whatsapp => api}/repository/label.repository.ts (100%) rename src/{whatsapp => api}/repository/message.repository.ts (100%) rename src/{whatsapp => api}/repository/messageUp.repository.ts (100%) rename src/{whatsapp => api}/repository/proxy.repository.ts (100%) rename src/{whatsapp => api}/repository/repository.manager.ts (93%) rename src/{whatsapp => api}/repository/settings.repository.ts (100%) rename src/{whatsapp => api}/repository/webhook.repository.ts (100%) rename src/{whatsapp => api}/routers/chamaai.router.ts (96%) rename src/{whatsapp => api}/routers/chat.router.ts (99%) rename src/{whatsapp => api}/routers/group.router.ts (99%) rename src/{whatsapp => api}/routers/index.router.ts (86%) rename src/{whatsapp => api}/routers/instance.router.ts (99%) rename src/{whatsapp => api}/routers/label.router.ts (97%) rename src/{whatsapp => api}/routers/proxy.router.ts (97%) rename src/{whatsapp => api}/routers/sendMessage.router.ts (99%) rename src/{whatsapp => api}/routers/settings.router.ts (96%) rename src/{whatsapp => api}/routers/view.router.ts (100%) rename src/{whatsapp => api}/routers/webhook.router.ts (98%) rename src/{whatsapp/whatsapp.module.ts => api/server.module.ts} (82%) rename src/{whatsapp => api}/services/auth.service.ts (100%) rename src/{whatsapp => api}/services/cache.service.ts (100%) rename src/{whatsapp => api}/services/chamaai.service.ts (100%) rename src/{whatsapp => api}/services/integration.service.ts (100%) rename src/{whatsapp => api}/services/monitor.service.ts (100%) rename src/{whatsapp => api}/services/proxy.service.ts (100%) rename src/{whatsapp => api}/services/settings.service.ts (100%) rename src/{whatsapp => api}/services/webhook.service.ts (100%) rename src/{whatsapp => api}/services/whatsapp.baileys.service.ts (99%) rename src/{whatsapp => api}/services/whatsapp.business.service.ts (100%) rename src/{whatsapp => api}/services/whatsapp.service.ts (98%) rename src/{whatsapp => api}/types/wa.types.ts (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index f86bcbfd..52d7080e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * Fix conversation read on chatwoot version 3.7 * Fix when receiving/sending messages from whatsapp desktop with ephemeral messages enabled * Changed returned sessions on typebot status change +* Reorganization of files and folders # 1.7.1 (2024-04-03 10:19) diff --git a/package.json b/package.json index aaef4f8a..8b31f902 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "evolution-api", - "version": "1.7.1", + "version": "1.7.2", "description": "Rest api for communication with WhatsApp", "main": "./dist/src/main.js", "scripts": { diff --git a/src/whatsapp/abstract/abstract.cache.ts b/src/api/abstract/abstract.cache.ts similarity index 100% rename from src/whatsapp/abstract/abstract.cache.ts rename to src/api/abstract/abstract.cache.ts diff --git a/src/whatsapp/abstract/abstract.repository.ts b/src/api/abstract/abstract.repository.ts similarity index 100% rename from src/whatsapp/abstract/abstract.repository.ts rename to src/api/abstract/abstract.repository.ts diff --git a/src/whatsapp/abstract/abstract.router.ts b/src/api/abstract/abstract.router.ts similarity index 100% rename from src/whatsapp/abstract/abstract.router.ts rename to src/api/abstract/abstract.router.ts diff --git a/src/whatsapp/controllers/chamaai.controller.ts b/src/api/controllers/chamaai.controller.ts similarity index 100% rename from src/whatsapp/controllers/chamaai.controller.ts rename to src/api/controllers/chamaai.controller.ts diff --git a/src/whatsapp/controllers/chat.controller.ts b/src/api/controllers/chat.controller.ts similarity index 100% rename from src/whatsapp/controllers/chat.controller.ts rename to src/api/controllers/chat.controller.ts diff --git a/src/whatsapp/controllers/group.controller.ts b/src/api/controllers/group.controller.ts similarity index 100% rename from src/whatsapp/controllers/group.controller.ts rename to src/api/controllers/group.controller.ts diff --git a/src/whatsapp/controllers/instance.controller.ts b/src/api/controllers/instance.controller.ts similarity index 98% rename from src/whatsapp/controllers/instance.controller.ts rename to src/api/controllers/instance.controller.ts index cf731064..4767db73 100644 --- a/src/whatsapp/controllers/instance.controller.ts +++ b/src/api/controllers/instance.controller.ts @@ -8,18 +8,18 @@ import { Logger } from '../../config/logger.config'; import { BadRequestException, InternalServerErrorException } from '../../exceptions'; import { RedisCache } from '../../libs/redis.client'; import { InstanceDto, SetPresenceDto } from '../dto/instance.dto'; +import { ChatwootService } from '../integrations/chatwoot/services/chatwoot.service'; +import { RabbitmqService } from '../integrations/rabbitmq/services/rabbitmq.service'; +import { SqsService } from '../integrations/sqs/services/sqs.service'; +import { TypebotService } from '../integrations/typebot/services/typebot.service'; +import { WebsocketService } from '../integrations/websocket/services/websocket.service'; import { RepositoryBroker } from '../repository/repository.manager'; import { AuthService, OldToken } from '../services/auth.service'; import { CacheService } from '../services/cache.service'; -import { ChatwootService } from '../services/chatwoot.service'; import { IntegrationService } from '../services/integration.service'; import { WAMonitoringService } from '../services/monitor.service'; -import { RabbitmqService } from '../services/rabbitmq.service'; import { SettingsService } from '../services/settings.service'; -import { SqsService } from '../services/sqs.service'; -import { TypebotService } from '../services/typebot.service'; import { WebhookService } from '../services/webhook.service'; -import { WebsocketService } from '../services/websocket.service'; import { BaileysStartupService } from '../services/whatsapp.baileys.service'; import { BusinessStartupService } from '../services/whatsapp.business.service'; import { Events, Integration, wa } from '../types/wa.types'; diff --git a/src/whatsapp/controllers/label.controller.ts b/src/api/controllers/label.controller.ts similarity index 100% rename from src/whatsapp/controllers/label.controller.ts rename to src/api/controllers/label.controller.ts diff --git a/src/whatsapp/controllers/proxy.controller.ts b/src/api/controllers/proxy.controller.ts similarity index 100% rename from src/whatsapp/controllers/proxy.controller.ts rename to src/api/controllers/proxy.controller.ts diff --git a/src/whatsapp/controllers/sendMessage.controller.ts b/src/api/controllers/sendMessage.controller.ts similarity index 100% rename from src/whatsapp/controllers/sendMessage.controller.ts rename to src/api/controllers/sendMessage.controller.ts diff --git a/src/whatsapp/controllers/settings.controller.ts b/src/api/controllers/settings.controller.ts similarity index 100% rename from src/whatsapp/controllers/settings.controller.ts rename to src/api/controllers/settings.controller.ts diff --git a/src/whatsapp/controllers/webhook.controller.ts b/src/api/controllers/webhook.controller.ts similarity index 100% rename from src/whatsapp/controllers/webhook.controller.ts rename to src/api/controllers/webhook.controller.ts diff --git a/src/whatsapp/dto/chamaai.dto.ts b/src/api/dto/chamaai.dto.ts similarity index 100% rename from src/whatsapp/dto/chamaai.dto.ts rename to src/api/dto/chamaai.dto.ts diff --git a/src/whatsapp/dto/chat.dto.ts b/src/api/dto/chat.dto.ts similarity index 100% rename from src/whatsapp/dto/chat.dto.ts rename to src/api/dto/chat.dto.ts diff --git a/src/whatsapp/dto/group.dto.ts b/src/api/dto/group.dto.ts similarity index 100% rename from src/whatsapp/dto/group.dto.ts rename to src/api/dto/group.dto.ts diff --git a/src/whatsapp/dto/instance.dto.ts b/src/api/dto/instance.dto.ts similarity index 100% rename from src/whatsapp/dto/instance.dto.ts rename to src/api/dto/instance.dto.ts diff --git a/src/whatsapp/dto/integration.dto.ts b/src/api/dto/integration.dto.ts similarity index 100% rename from src/whatsapp/dto/integration.dto.ts rename to src/api/dto/integration.dto.ts diff --git a/src/whatsapp/dto/label.dto.ts b/src/api/dto/label.dto.ts similarity index 100% rename from src/whatsapp/dto/label.dto.ts rename to src/api/dto/label.dto.ts diff --git a/src/whatsapp/dto/proxy.dto.ts b/src/api/dto/proxy.dto.ts similarity index 100% rename from src/whatsapp/dto/proxy.dto.ts rename to src/api/dto/proxy.dto.ts diff --git a/src/whatsapp/dto/sendMessage.dto.ts b/src/api/dto/sendMessage.dto.ts similarity index 100% rename from src/whatsapp/dto/sendMessage.dto.ts rename to src/api/dto/sendMessage.dto.ts diff --git a/src/whatsapp/dto/settings.dto.ts b/src/api/dto/settings.dto.ts similarity index 100% rename from src/whatsapp/dto/settings.dto.ts rename to src/api/dto/settings.dto.ts diff --git a/src/whatsapp/dto/webhook.dto.ts b/src/api/dto/webhook.dto.ts similarity index 100% rename from src/whatsapp/dto/webhook.dto.ts rename to src/api/dto/webhook.dto.ts diff --git a/src/whatsapp/guards/auth.guard.ts b/src/api/guards/auth.guard.ts similarity index 98% rename from src/whatsapp/guards/auth.guard.ts rename to src/api/guards/auth.guard.ts index a72ebfff..ccc73a58 100644 --- a/src/whatsapp/guards/auth.guard.ts +++ b/src/api/guards/auth.guard.ts @@ -7,8 +7,8 @@ import { Auth, configService } from '../../config/env.config'; import { Logger } from '../../config/logger.config'; import { ForbiddenException, UnauthorizedException } from '../../exceptions'; import { InstanceDto } from '../dto/instance.dto'; +import { repository } from '../server.module'; import { JwtPayload } from '../services/auth.service'; -import { repository } from '../whatsapp.module'; const logger = new Logger('GUARD'); diff --git a/src/whatsapp/guards/instance.guard.ts b/src/api/guards/instance.guard.ts similarity index 97% rename from src/whatsapp/guards/instance.guard.ts rename to src/api/guards/instance.guard.ts index 6b193411..2214bd43 100644 --- a/src/whatsapp/guards/instance.guard.ts +++ b/src/api/guards/instance.guard.ts @@ -12,7 +12,7 @@ import { } from '../../exceptions'; import { dbserver } from '../../libs/db.connect'; import { InstanceDto } from '../dto/instance.dto'; -import { cache, waMonitor } from '../whatsapp.module'; +import { cache, waMonitor } from '../server.module'; async function getInstance(instanceName: string) { try { diff --git a/src/libs/cacheengine.ts b/src/api/integrations/chatwoot/cache/cacheengine.ts similarity index 81% rename from src/libs/cacheengine.ts rename to src/api/integrations/chatwoot/cache/cacheengine.ts index a22d7e68..a05e3dae 100644 --- a/src/libs/cacheengine.ts +++ b/src/api/integrations/chatwoot/cache/cacheengine.ts @@ -1,5 +1,5 @@ -import { CacheConf, ConfigService } from '../config/env.config'; -import { ICache } from '../whatsapp/abstract/abstract.cache'; +import { CacheConf, ConfigService } from '../../../../config/env.config'; +import { ICache } from '../../../abstract/abstract.cache'; import { LocalCache } from './localcache'; import { RedisCache } from './rediscache'; diff --git a/src/libs/localcache.ts b/src/api/integrations/chatwoot/cache/localcache.ts similarity index 89% rename from src/libs/localcache.ts rename to src/api/integrations/chatwoot/cache/localcache.ts index fe1f295f..7bf53e71 100644 --- a/src/libs/localcache.ts +++ b/src/api/integrations/chatwoot/cache/localcache.ts @@ -1,7 +1,7 @@ import NodeCache from 'node-cache'; -import { CacheConf, CacheConfLocal, ConfigService } from '../config/env.config'; -import { ICache } from '../whatsapp/abstract/abstract.cache'; +import { CacheConf, CacheConfLocal, ConfigService } from '../../../../config/env.config'; +import { ICache } from '../../../abstract/abstract.cache'; export class LocalCache implements ICache { private conf: CacheConfLocal; diff --git a/src/libs/rediscache.client.ts b/src/api/integrations/chatwoot/cache/rediscache.client.ts similarity index 90% rename from src/libs/rediscache.client.ts rename to src/api/integrations/chatwoot/cache/rediscache.client.ts index b3f8dead..0a3ef4fc 100644 --- a/src/libs/rediscache.client.ts +++ b/src/api/integrations/chatwoot/cache/rediscache.client.ts @@ -1,7 +1,7 @@ import { createClient, RedisClientType } from 'redis'; -import { CacheConf, CacheConfRedis, configService } from '../config/env.config'; -import { Logger } from '../config/logger.config'; +import { CacheConf, CacheConfRedis, configService } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; class Redis { private logger = new Logger(Redis.name); diff --git a/src/libs/rediscache.ts b/src/api/integrations/chatwoot/cache/rediscache.ts similarity index 90% rename from src/libs/rediscache.ts rename to src/api/integrations/chatwoot/cache/rediscache.ts index cd0b1283..2a08fb3a 100644 --- a/src/libs/rediscache.ts +++ b/src/api/integrations/chatwoot/cache/rediscache.ts @@ -1,8 +1,8 @@ import { RedisClientType } from 'redis'; -import { CacheConf, CacheConfRedis, ConfigService } from '../config/env.config'; -import { Logger } from '../config/logger.config'; -import { ICache } from '../whatsapp/abstract/abstract.cache'; +import { CacheConf, CacheConfRedis, ConfigService } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; +import { ICache } from '../../../abstract/abstract.cache'; import { redisClient } from './rediscache.client'; export class RedisCache implements ICache { diff --git a/src/whatsapp/controllers/chatwoot.controller.ts b/src/api/integrations/chatwoot/controllers/chatwoot.controller.ts similarity index 86% rename from src/whatsapp/controllers/chatwoot.controller.ts rename to src/api/integrations/chatwoot/controllers/chatwoot.controller.ts index 2cccf280..03282ce5 100644 --- a/src/whatsapp/controllers/chatwoot.controller.ts +++ b/src/api/integrations/chatwoot/controllers/chatwoot.controller.ts @@ -1,15 +1,15 @@ import { isURL } from 'class-validator'; -import { ConfigService, HttpServer } from '../../config/env.config'; -import { Logger } from '../../config/logger.config'; -import { BadRequestException } from '../../exceptions'; -import { CacheEngine } from '../../libs/cacheengine'; +import { ConfigService, HttpServer } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; +import { BadRequestException } from '../../../../exceptions'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { RepositoryBroker } from '../../../repository/repository.manager'; +import { waMonitor } from '../../../server.module'; +import { CacheService } from '../../../services/cache.service'; +import { CacheEngine } from '../cache/cacheengine'; import { ChatwootDto } from '../dto/chatwoot.dto'; -import { InstanceDto } from '../dto/instance.dto'; -import { RepositoryBroker } from '../repository/repository.manager'; -import { CacheService } from '../services/cache.service'; import { ChatwootService } from '../services/chatwoot.service'; -import { waMonitor } from '../whatsapp.module'; const logger = new Logger('ChatwootController'); diff --git a/src/whatsapp/dto/chatwoot.dto.ts b/src/api/integrations/chatwoot/dto/chatwoot.dto.ts similarity index 100% rename from src/whatsapp/dto/chatwoot.dto.ts rename to src/api/integrations/chatwoot/dto/chatwoot.dto.ts diff --git a/src/libs/postgres.client.ts b/src/api/integrations/chatwoot/libs/postgres.client.ts similarity index 88% rename from src/libs/postgres.client.ts rename to src/api/integrations/chatwoot/libs/postgres.client.ts index d1a68cdf..1211b075 100644 --- a/src/libs/postgres.client.ts +++ b/src/api/integrations/chatwoot/libs/postgres.client.ts @@ -1,7 +1,7 @@ import postgresql from 'pg'; -import { Chatwoot, configService } from '../config/env.config'; -import { Logger } from '../config/logger.config'; +import { Chatwoot, configService } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; const { Pool } = postgresql; diff --git a/src/whatsapp/models/chatwoot.model.ts b/src/api/integrations/chatwoot/models/chatwoot.model.ts similarity index 95% rename from src/whatsapp/models/chatwoot.model.ts rename to src/api/integrations/chatwoot/models/chatwoot.model.ts index e16352e1..659b847c 100644 --- a/src/whatsapp/models/chatwoot.model.ts +++ b/src/api/integrations/chatwoot/models/chatwoot.model.ts @@ -1,6 +1,6 @@ import { Schema } from 'mongoose'; -import { dbserver } from '../../libs/db.connect'; +import { dbserver } from '../../../../libs/db.connect'; export class ChatwootRaw { _id?: string; diff --git a/src/whatsapp/repository/chatwoot.repository.ts b/src/api/integrations/chatwoot/repository/chatwoot.repository.ts similarity index 87% rename from src/whatsapp/repository/chatwoot.repository.ts rename to src/api/integrations/chatwoot/repository/chatwoot.repository.ts index 47398d68..820f54af 100644 --- a/src/whatsapp/repository/chatwoot.repository.ts +++ b/src/api/integrations/chatwoot/repository/chatwoot.repository.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'fs'; import { join } from 'path'; -import { ConfigService } from '../../config/env.config'; -import { Logger } from '../../config/logger.config'; -import { IInsert, Repository } from '../abstract/abstract.repository'; -import { ChatwootRaw, IChatwootModel } from '../models'; +import { ConfigService } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; +import { IInsert, Repository } from '../../../abstract/abstract.repository'; +import { ChatwootRaw, IChatwootModel } from '../../../models'; export class ChatwootRepository extends Repository { constructor(private readonly chatwootModel: IChatwootModel, private readonly configService: ConfigService) { diff --git a/src/whatsapp/routers/chatwoot.router.ts b/src/api/integrations/chatwoot/routes/chatwoot.router.ts similarity index 84% rename from src/whatsapp/routers/chatwoot.router.ts rename to src/api/integrations/chatwoot/routes/chatwoot.router.ts index c232e007..2df2f18f 100644 --- a/src/whatsapp/routers/chatwoot.router.ts +++ b/src/api/integrations/chatwoot/routes/chatwoot.router.ts @@ -1,12 +1,12 @@ import { RequestHandler, Router } from 'express'; -import { Logger } from '../../config/logger.config'; -import { chatwootSchema, instanceNameSchema } from '../../validate/validate.schema'; -import { RouterBroker } from '../abstract/abstract.router'; +import { Logger } from '../../../../config/logger.config'; +import { chatwootSchema, instanceNameSchema } from '../../../../validate/validate.schema'; +import { RouterBroker } from '../../../abstract/abstract.router'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { HttpStatus } from '../../../routers/index.router'; +import { chatwootController } from '../../../server.module'; import { ChatwootDto } from '../dto/chatwoot.dto'; -import { InstanceDto } from '../dto/instance.dto'; -import { chatwootController } from '../whatsapp.module'; -import { HttpStatus } from './index.router'; const logger = new Logger('ChatwootRouter'); diff --git a/src/whatsapp/services/chatwoot.service.ts b/src/api/integrations/chatwoot/services/chatwoot.service.ts similarity index 99% rename from src/whatsapp/services/chatwoot.service.ts rename to src/api/integrations/chatwoot/services/chatwoot.service.ts index d2c1f139..35fbb7af 100644 --- a/src/whatsapp/services/chatwoot.service.ts +++ b/src/api/integrations/chatwoot/services/chatwoot.service.ts @@ -15,18 +15,18 @@ import Jimp from 'jimp'; import mimeTypes from 'mime-types'; import path from 'path'; -import { Chatwoot, ConfigService, HttpServer } from '../../config/env.config'; -import { Logger } from '../../config/logger.config'; -import { chatwootImport } from '../../utils/chatwoot-import-helper'; -import i18next from '../../utils/i18n'; -import { ICache } from '../abstract/abstract.cache'; +import { Chatwoot, ConfigService, HttpServer } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; +import i18next from '../../../../utils/i18n'; +import { ICache } from '../../../abstract/abstract.cache'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { Options, Quoted, SendAudioDto, SendMediaDto, SendTextDto } from '../../../dto/sendMessage.dto'; +import { ChatwootRaw, ContactRaw, MessageRaw } from '../../../models'; +import { RepositoryBroker } from '../../../repository/repository.manager'; +import { WAMonitoringService } from '../../../services/monitor.service'; +import { Events } from '../../../types/wa.types'; import { ChatwootDto } from '../dto/chatwoot.dto'; -import { InstanceDto } from '../dto/instance.dto'; -import { Options, Quoted, SendAudioDto, SendMediaDto, SendTextDto } from '../dto/sendMessage.dto'; -import { ChatwootRaw, ContactRaw, MessageRaw } from '../models'; -import { RepositoryBroker } from '../repository/repository.manager'; -import { Events } from '../types/wa.types'; -import { WAMonitoringService } from './monitor.service'; +import { chatwootImport } from '../utils/chatwoot-import-helper'; export class ChatwootService { private readonly logger = new Logger(ChatwootService.name); diff --git a/src/utils/chatwoot-import-helper.ts b/src/api/integrations/chatwoot/utils/chatwoot-import-helper.ts similarity index 98% rename from src/utils/chatwoot-import-helper.ts rename to src/api/integrations/chatwoot/utils/chatwoot-import-helper.ts index 3283683f..dd0bb23a 100644 --- a/src/utils/chatwoot-import-helper.ts +++ b/src/api/integrations/chatwoot/utils/chatwoot-import-helper.ts @@ -1,12 +1,12 @@ import { inbox } from '@figuro/chatwoot-sdk'; import { proto } from '@whiskeysockets/baileys'; -import { Chatwoot, configService } from '../config/env.config'; -import { Logger } from '../config/logger.config'; +import { InstanceDto } from '../../../../api/dto/instance.dto'; +import { ChatwootRaw, ContactRaw, MessageRaw } from '../../../../api/models'; +import { Chatwoot, configService } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; import { postgresClient } from '../libs/postgres.client'; -import { InstanceDto } from '../whatsapp/dto/instance.dto'; -import { ChatwootRaw, ContactRaw, MessageRaw } from '../whatsapp/models'; -import { ChatwootService } from '../whatsapp/services/chatwoot.service'; +import { ChatwootService } from '../services/chatwoot.service'; type ChatwootUser = { user_type: string; diff --git a/src/api/integrations/chatwoot/validate/chatwoot.schema.ts b/src/api/integrations/chatwoot/validate/chatwoot.schema.ts new file mode 100644 index 00000000..d2784daf --- /dev/null +++ b/src/api/integrations/chatwoot/validate/chatwoot.schema.ts @@ -0,0 +1,42 @@ +import { JSONSchema7 } from 'json-schema'; +import { v4 } from 'uuid'; + +const isNotEmpty = (...propertyNames: string[]): JSONSchema7 => { + const properties = {}; + propertyNames.forEach( + (property) => + (properties[property] = { + minLength: 1, + description: `The "${property}" cannot be empty`, + }), + ); + return { + if: { + propertyNames: { + enum: [...propertyNames], + }, + }, + then: { properties }, + }; +}; + +export const chatwootSchema: JSONSchema7 = { + $id: v4(), + type: 'object', + properties: { + enabled: { type: 'boolean', enum: [true, false] }, + account_id: { type: 'string' }, + token: { type: 'string' }, + url: { type: 'string' }, + sign_msg: { type: 'boolean', enum: [true, false] }, + sign_delimiter: { type: ['string', 'null'] }, + reopen_conversation: { type: 'boolean', enum: [true, false] }, + conversation_pending: { type: 'boolean', enum: [true, false] }, + auto_create: { type: 'boolean', enum: [true, false] }, + import_contacts: { type: 'boolean', enum: [true, false] }, + import_messages: { type: 'boolean', enum: [true, false] }, + days_limit_import_messages: { type: 'number' }, + }, + required: ['enabled', 'account_id', 'token', 'url', 'sign_msg', 'reopen_conversation', 'conversation_pending'], + ...isNotEmpty('account_id', 'token', 'url', 'sign_msg', 'reopen_conversation', 'conversation_pending'), +}; diff --git a/src/whatsapp/controllers/rabbitmq.controller.ts b/src/api/integrations/rabbitmq/controllers/rabbitmq.controller.ts similarity index 93% rename from src/whatsapp/controllers/rabbitmq.controller.ts rename to src/api/integrations/rabbitmq/controllers/rabbitmq.controller.ts index 527c5006..0b10e954 100644 --- a/src/whatsapp/controllers/rabbitmq.controller.ts +++ b/src/api/integrations/rabbitmq/controllers/rabbitmq.controller.ts @@ -1,5 +1,5 @@ -import { Logger } from '../../config/logger.config'; -import { InstanceDto } from '../dto/instance.dto'; +import { Logger } from '../../../../config/logger.config'; +import { InstanceDto } from '../../../dto/instance.dto'; import { RabbitmqDto } from '../dto/rabbitmq.dto'; import { RabbitmqService } from '../services/rabbitmq.service'; diff --git a/src/whatsapp/dto/rabbitmq.dto.ts b/src/api/integrations/rabbitmq/dto/rabbitmq.dto.ts similarity index 100% rename from src/whatsapp/dto/rabbitmq.dto.ts rename to src/api/integrations/rabbitmq/dto/rabbitmq.dto.ts diff --git a/src/libs/amqp.server.ts b/src/api/integrations/rabbitmq/libs/amqp.server.ts similarity index 94% rename from src/libs/amqp.server.ts rename to src/api/integrations/rabbitmq/libs/amqp.server.ts index fc95b33c..5628fac9 100644 --- a/src/libs/amqp.server.ts +++ b/src/api/integrations/rabbitmq/libs/amqp.server.ts @@ -1,7 +1,7 @@ import * as amqp from 'amqplib/callback_api'; -import { configService, Rabbitmq } from '../config/env.config'; -import { Logger } from '../config/logger.config'; +import { configService, Rabbitmq } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; const logger = new Logger('AMQP'); diff --git a/src/whatsapp/models/rabbitmq.model.ts b/src/api/integrations/rabbitmq/models/rabbitmq.model.ts similarity index 88% rename from src/whatsapp/models/rabbitmq.model.ts rename to src/api/integrations/rabbitmq/models/rabbitmq.model.ts index e89ee3b1..ba0ac1af 100644 --- a/src/whatsapp/models/rabbitmq.model.ts +++ b/src/api/integrations/rabbitmq/models/rabbitmq.model.ts @@ -1,6 +1,6 @@ import { Schema } from 'mongoose'; -import { dbserver } from '../../libs/db.connect'; +import { dbserver } from '../../../../libs/db.connect'; export class RabbitmqRaw { _id?: string; diff --git a/src/whatsapp/repository/rabbitmq.repository.ts b/src/api/integrations/rabbitmq/repository/rabbitmq.repository.ts similarity index 87% rename from src/whatsapp/repository/rabbitmq.repository.ts rename to src/api/integrations/rabbitmq/repository/rabbitmq.repository.ts index 3dfb5ec2..cb30c7c3 100644 --- a/src/whatsapp/repository/rabbitmq.repository.ts +++ b/src/api/integrations/rabbitmq/repository/rabbitmq.repository.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'fs'; import { join } from 'path'; -import { ConfigService } from '../../config/env.config'; -import { Logger } from '../../config/logger.config'; -import { IInsert, Repository } from '../abstract/abstract.repository'; -import { IRabbitmqModel, RabbitmqRaw } from '../models'; +import { ConfigService } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; +import { IInsert, Repository } from '../../../abstract/abstract.repository'; +import { IRabbitmqModel, RabbitmqRaw } from '../../../models'; export class RabbitmqRepository extends Repository { constructor(private readonly rabbitmqModel: IRabbitmqModel, private readonly configService: ConfigService) { diff --git a/src/whatsapp/routers/rabbitmq.router.ts b/src/api/integrations/rabbitmq/routes/rabbitmq.router.ts similarity index 79% rename from src/whatsapp/routers/rabbitmq.router.ts rename to src/api/integrations/rabbitmq/routes/rabbitmq.router.ts index e3f65283..c7d567e1 100644 --- a/src/whatsapp/routers/rabbitmq.router.ts +++ b/src/api/integrations/rabbitmq/routes/rabbitmq.router.ts @@ -1,12 +1,12 @@ import { RequestHandler, Router } from 'express'; -import { Logger } from '../../config/logger.config'; -import { instanceNameSchema, rabbitmqSchema } from '../../validate/validate.schema'; -import { RouterBroker } from '../abstract/abstract.router'; -import { InstanceDto } from '../dto/instance.dto'; +import { Logger } from '../../../../config/logger.config'; +import { instanceNameSchema, rabbitmqSchema } from '../../../../validate/validate.schema'; +import { RouterBroker } from '../../../abstract/abstract.router'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { HttpStatus } from '../../../routers/index.router'; +import { rabbitmqController } from '../../../server.module'; import { RabbitmqDto } from '../dto/rabbitmq.dto'; -import { rabbitmqController } from '../whatsapp.module'; -import { HttpStatus } from './index.router'; const logger = new Logger('RabbitmqRouter'); diff --git a/src/whatsapp/services/rabbitmq.service.ts b/src/api/integrations/rabbitmq/services/rabbitmq.service.ts similarity index 77% rename from src/whatsapp/services/rabbitmq.service.ts rename to src/api/integrations/rabbitmq/services/rabbitmq.service.ts index a377595b..efb822fd 100644 --- a/src/whatsapp/services/rabbitmq.service.ts +++ b/src/api/integrations/rabbitmq/services/rabbitmq.service.ts @@ -1,9 +1,9 @@ -import { Logger } from '../../config/logger.config'; -import { initQueues } from '../../libs/amqp.server'; -import { InstanceDto } from '../dto/instance.dto'; +import { Logger } from '../../../../config/logger.config'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { RabbitmqRaw } from '../../../models'; +import { WAMonitoringService } from '../../../services/monitor.service'; import { RabbitmqDto } from '../dto/rabbitmq.dto'; -import { RabbitmqRaw } from '../models'; -import { WAMonitoringService } from './monitor.service'; +import { initQueues } from '../libs/amqp.server'; export class RabbitmqService { constructor(private readonly waMonitor: WAMonitoringService) {} diff --git a/src/api/integrations/rabbitmq/validate/rabbitmq.schema.ts b/src/api/integrations/rabbitmq/validate/rabbitmq.schema.ts new file mode 100644 index 00000000..7a786bb4 --- /dev/null +++ b/src/api/integrations/rabbitmq/validate/rabbitmq.schema.ts @@ -0,0 +1,66 @@ +import { JSONSchema7 } from 'json-schema'; +import { v4 } from 'uuid'; + +const isNotEmpty = (...propertyNames: string[]): JSONSchema7 => { + const properties = {}; + propertyNames.forEach( + (property) => + (properties[property] = { + minLength: 1, + description: `The "${property}" cannot be empty`, + }), + ); + return { + if: { + propertyNames: { + enum: [...propertyNames], + }, + }, + then: { properties }, + }; +}; + +export const rabbitmqSchema: JSONSchema7 = { + $id: v4(), + type: 'object', + properties: { + enabled: { type: 'boolean', enum: [true, false] }, + events: { + type: 'array', + minItems: 0, + items: { + type: 'string', + enum: [ + 'APPLICATION_STARTUP', + 'QRCODE_UPDATED', + 'MESSAGES_SET', + 'MESSAGES_UPSERT', + 'MESSAGES_UPDATE', + 'MESSAGES_DELETE', + 'SEND_MESSAGE', + 'CONTACTS_SET', + 'CONTACTS_UPSERT', + 'CONTACTS_UPDATE', + 'PRESENCE_UPDATE', + 'CHATS_SET', + 'CHATS_UPSERT', + 'CHATS_UPDATE', + 'CHATS_DELETE', + 'GROUPS_UPSERT', + 'GROUP_UPDATE', + 'GROUP_PARTICIPANTS_UPDATE', + 'CONNECTION_UPDATE', + 'LABELS_EDIT', + 'LABELS_ASSOCIATION', + 'CALL', + 'NEW_JWT_TOKEN', + 'TYPEBOT_START', + 'TYPEBOT_CHANGE_STATUS', + 'CHAMA_AI_ACTION', + ], + }, + }, + }, + required: ['enabled'], + ...isNotEmpty('enabled'), +}; diff --git a/src/whatsapp/controllers/sqs.controller.ts b/src/api/integrations/sqs/controllers/sqs.controller.ts similarity index 92% rename from src/whatsapp/controllers/sqs.controller.ts rename to src/api/integrations/sqs/controllers/sqs.controller.ts index 8dfebc6c..d6dd346b 100644 --- a/src/whatsapp/controllers/sqs.controller.ts +++ b/src/api/integrations/sqs/controllers/sqs.controller.ts @@ -1,5 +1,5 @@ -import { Logger } from '../../config/logger.config'; -import { InstanceDto } from '../dto/instance.dto'; +import { Logger } from '../../../../config/logger.config'; +import { InstanceDto } from '../../../dto/instance.dto'; import { SqsDto } from '../dto/sqs.dto'; import { SqsService } from '../services/sqs.service'; diff --git a/src/whatsapp/dto/sqs.dto.ts b/src/api/integrations/sqs/dto/sqs.dto.ts similarity index 100% rename from src/whatsapp/dto/sqs.dto.ts rename to src/api/integrations/sqs/dto/sqs.dto.ts diff --git a/src/libs/sqs.server.ts b/src/api/integrations/sqs/libs/sqs.server.ts similarity index 94% rename from src/libs/sqs.server.ts rename to src/api/integrations/sqs/libs/sqs.server.ts index 04184542..e1c328cb 100644 --- a/src/libs/sqs.server.ts +++ b/src/api/integrations/sqs/libs/sqs.server.ts @@ -1,7 +1,7 @@ import { SQS } from 'aws-sdk'; -import { configService, Sqs } from '../config/env.config'; -import { Logger } from '../config/logger.config'; +import { configService, Sqs } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; const logger = new Logger('SQS'); diff --git a/src/whatsapp/models/sqs.model.ts b/src/api/integrations/sqs/models/sqs.model.ts similarity index 87% rename from src/whatsapp/models/sqs.model.ts rename to src/api/integrations/sqs/models/sqs.model.ts index 2d5f432f..c3ac4fb1 100644 --- a/src/whatsapp/models/sqs.model.ts +++ b/src/api/integrations/sqs/models/sqs.model.ts @@ -1,6 +1,6 @@ import { Schema } from 'mongoose'; -import { dbserver } from '../../libs/db.connect'; +import { dbserver } from '../../../../libs/db.connect'; export class SqsRaw { _id?: string; diff --git a/src/whatsapp/repository/sqs.repository.ts b/src/api/integrations/sqs/repository/sqs.repository.ts similarity index 87% rename from src/whatsapp/repository/sqs.repository.ts rename to src/api/integrations/sqs/repository/sqs.repository.ts index 50ea1cd3..7e149daa 100644 --- a/src/whatsapp/repository/sqs.repository.ts +++ b/src/api/integrations/sqs/repository/sqs.repository.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'fs'; import { join } from 'path'; -import { ConfigService } from '../../config/env.config'; -import { Logger } from '../../config/logger.config'; -import { IInsert, Repository } from '../abstract/abstract.repository'; -import { ISqsModel, SqsRaw } from '../models'; +import { ConfigService } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; +import { IInsert, Repository } from '../../../abstract/abstract.repository'; +import { ISqsModel, SqsRaw } from '../../../models'; export class SqsRepository extends Repository { constructor(private readonly sqsModel: ISqsModel, private readonly configService: ConfigService) { diff --git a/src/whatsapp/routers/sqs.router.ts b/src/api/integrations/sqs/routes/sqs.router.ts similarity index 79% rename from src/whatsapp/routers/sqs.router.ts rename to src/api/integrations/sqs/routes/sqs.router.ts index e1bf8e93..8b03bb3a 100644 --- a/src/whatsapp/routers/sqs.router.ts +++ b/src/api/integrations/sqs/routes/sqs.router.ts @@ -1,12 +1,12 @@ import { RequestHandler, Router } from 'express'; -import { Logger } from '../../config/logger.config'; -import { instanceNameSchema, sqsSchema } from '../../validate/validate.schema'; -import { RouterBroker } from '../abstract/abstract.router'; -import { InstanceDto } from '../dto/instance.dto'; +import { Logger } from '../../../../config/logger.config'; +import { instanceNameSchema, sqsSchema } from '../../../../validate/validate.schema'; +import { RouterBroker } from '../../../abstract/abstract.router'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { HttpStatus } from '../../../routers/index.router'; +import { sqsController } from '../../../server.module'; import { SqsDto } from '../dto/sqs.dto'; -import { sqsController } from '../whatsapp.module'; -import { HttpStatus } from './index.router'; const logger = new Logger('SqsRouter'); diff --git a/src/whatsapp/services/sqs.service.ts b/src/api/integrations/sqs/services/sqs.service.ts similarity index 76% rename from src/whatsapp/services/sqs.service.ts rename to src/api/integrations/sqs/services/sqs.service.ts index 236d4ceb..52780104 100644 --- a/src/whatsapp/services/sqs.service.ts +++ b/src/api/integrations/sqs/services/sqs.service.ts @@ -1,9 +1,9 @@ -import { Logger } from '../../config/logger.config'; -import { initQueues } from '../../libs/sqs.server'; -import { InstanceDto } from '../dto/instance.dto'; +import { Logger } from '../../../../config/logger.config'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { SqsRaw } from '../../../models'; +import { WAMonitoringService } from '../../../services/monitor.service'; import { SqsDto } from '../dto/sqs.dto'; -import { SqsRaw } from '../models'; -import { WAMonitoringService } from './monitor.service'; +import { initQueues } from '../libs/sqs.server'; export class SqsService { constructor(private readonly waMonitor: WAMonitoringService) {} diff --git a/src/api/integrations/sqs/validate/sqs.schema.ts b/src/api/integrations/sqs/validate/sqs.schema.ts new file mode 100644 index 00000000..54379c29 --- /dev/null +++ b/src/api/integrations/sqs/validate/sqs.schema.ts @@ -0,0 +1,66 @@ +import { JSONSchema7 } from 'json-schema'; +import { v4 } from 'uuid'; + +const isNotEmpty = (...propertyNames: string[]): JSONSchema7 => { + const properties = {}; + propertyNames.forEach( + (property) => + (properties[property] = { + minLength: 1, + description: `The "${property}" cannot be empty`, + }), + ); + return { + if: { + propertyNames: { + enum: [...propertyNames], + }, + }, + then: { properties }, + }; +}; + +export const sqsSchema: JSONSchema7 = { + $id: v4(), + type: 'object', + properties: { + enabled: { type: 'boolean', enum: [true, false] }, + events: { + type: 'array', + minItems: 0, + items: { + type: 'string', + enum: [ + 'APPLICATION_STARTUP', + 'QRCODE_UPDATED', + 'MESSAGES_SET', + 'MESSAGES_UPSERT', + 'MESSAGES_UPDATE', + 'MESSAGES_DELETE', + 'SEND_MESSAGE', + 'CONTACTS_SET', + 'CONTACTS_UPSERT', + 'CONTACTS_UPDATE', + 'PRESENCE_UPDATE', + 'CHATS_SET', + 'CHATS_UPSERT', + 'CHATS_UPDATE', + 'CHATS_DELETE', + 'GROUPS_UPSERT', + 'GROUP_UPDATE', + 'GROUP_PARTICIPANTS_UPDATE', + 'CONNECTION_UPDATE', + 'LABELS_EDIT', + 'LABELS_ASSOCIATION', + 'CALL', + 'NEW_JWT_TOKEN', + 'TYPEBOT_START', + 'TYPEBOT_CHANGE_STATUS', + 'CHAMA_AI_ACTION', + ], + }, + }, + }, + required: ['enabled'], + ...isNotEmpty('enabled'), +}; diff --git a/src/whatsapp/controllers/typebot.controller.ts b/src/api/integrations/typebot/controllers/typebot.controller.ts similarity index 92% rename from src/whatsapp/controllers/typebot.controller.ts rename to src/api/integrations/typebot/controllers/typebot.controller.ts index 53dc967f..bb52a370 100644 --- a/src/whatsapp/controllers/typebot.controller.ts +++ b/src/api/integrations/typebot/controllers/typebot.controller.ts @@ -1,5 +1,5 @@ -import { Logger } from '../../config/logger.config'; -import { InstanceDto } from '../dto/instance.dto'; +import { Logger } from '../../../../config/logger.config'; +import { InstanceDto } from '../../../dto/instance.dto'; import { TypebotDto } from '../dto/typebot.dto'; import { TypebotService } from '../services/typebot.service'; diff --git a/src/whatsapp/dto/typebot.dto.ts b/src/api/integrations/typebot/dto/typebot.dto.ts similarity index 100% rename from src/whatsapp/dto/typebot.dto.ts rename to src/api/integrations/typebot/dto/typebot.dto.ts diff --git a/src/whatsapp/models/typebot.model.ts b/src/api/integrations/typebot/models/typebot.model.ts similarity index 96% rename from src/whatsapp/models/typebot.model.ts rename to src/api/integrations/typebot/models/typebot.model.ts index c8ae7105..9060b6e0 100644 --- a/src/whatsapp/models/typebot.model.ts +++ b/src/api/integrations/typebot/models/typebot.model.ts @@ -1,6 +1,6 @@ import { Schema } from 'mongoose'; -import { dbserver } from '../../libs/db.connect'; +import { dbserver } from '../../../../libs/db.connect'; class Session { remoteJid?: string; diff --git a/src/whatsapp/repository/typebot.repository.ts b/src/api/integrations/typebot/repository/typebot.repository.ts similarity index 88% rename from src/whatsapp/repository/typebot.repository.ts rename to src/api/integrations/typebot/repository/typebot.repository.ts index 8653e9c9..45453c63 100644 --- a/src/whatsapp/repository/typebot.repository.ts +++ b/src/api/integrations/typebot/repository/typebot.repository.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'fs'; import { join } from 'path'; -import { ConfigService } from '../../config/env.config'; -import { Logger } from '../../config/logger.config'; -import { IInsert, Repository } from '../abstract/abstract.repository'; -import { ITypebotModel, TypebotRaw } from '../models'; +import { ConfigService } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; +import { IInsert, Repository } from '../../../abstract/abstract.repository'; +import { ITypebotModel, TypebotRaw } from '../../../models'; export class TypebotRepository extends Repository { constructor(private readonly typebotModel: ITypebotModel, private readonly configService: ConfigService) { diff --git a/src/whatsapp/routers/typebot.router.ts b/src/api/integrations/typebot/routes/typebot.router.ts similarity index 88% rename from src/whatsapp/routers/typebot.router.ts rename to src/api/integrations/typebot/routes/typebot.router.ts index 0f785de3..b9694c54 100644 --- a/src/whatsapp/routers/typebot.router.ts +++ b/src/api/integrations/typebot/routes/typebot.router.ts @@ -1,17 +1,17 @@ import { RequestHandler, Router } from 'express'; -import { Logger } from '../../config/logger.config'; +import { Logger } from '../../../../config/logger.config'; import { instanceNameSchema, typebotSchema, typebotStartSchema, typebotStatusSchema, -} from '../../validate/validate.schema'; -import { RouterBroker } from '../abstract/abstract.router'; -import { InstanceDto } from '../dto/instance.dto'; +} from '../../../../validate/validate.schema'; +import { RouterBroker } from '../../../abstract/abstract.router'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { HttpStatus } from '../../../routers/index.router'; +import { typebotController } from '../../../server.module'; import { TypebotDto } from '../dto/typebot.dto'; -import { typebotController } from '../whatsapp.module'; -import { HttpStatus } from './index.router'; const logger = new Logger('TypebotRouter'); diff --git a/src/whatsapp/services/typebot.service.ts b/src/api/integrations/typebot/services/typebot.service.ts similarity index 98% rename from src/whatsapp/services/typebot.service.ts rename to src/api/integrations/typebot/services/typebot.service.ts index 8c267759..6c322552 100644 --- a/src/whatsapp/services/typebot.service.ts +++ b/src/api/integrations/typebot/services/typebot.service.ts @@ -1,13 +1,13 @@ import axios from 'axios'; import EventEmitter2 from 'eventemitter2'; -import { ConfigService, Typebot } from '../../config/env.config'; -import { Logger } from '../../config/logger.config'; -import { InstanceDto } from '../dto/instance.dto'; +import { ConfigService, Typebot } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { MessageRaw } from '../../../models'; +import { WAMonitoringService } from '../../../services/monitor.service'; +import { Events } from '../../../types/wa.types'; import { Session, TypebotDto } from '../dto/typebot.dto'; -import { MessageRaw } from '../models'; -import { Events } from '../types/wa.types'; -import { WAMonitoringService } from './monitor.service'; export class TypebotService { constructor( diff --git a/src/api/integrations/typebot/validate/typebot.schema.ts b/src/api/integrations/typebot/validate/typebot.schema.ts new file mode 100644 index 00000000..fde9d973 --- /dev/null +++ b/src/api/integrations/typebot/validate/typebot.schema.ts @@ -0,0 +1,60 @@ +import { JSONSchema7 } from 'json-schema'; +import { v4 } from 'uuid'; + +const isNotEmpty = (...propertyNames: string[]): JSONSchema7 => { + const properties = {}; + propertyNames.forEach( + (property) => + (properties[property] = { + minLength: 1, + description: `The "${property}" cannot be empty`, + }), + ); + return { + if: { + propertyNames: { + enum: [...propertyNames], + }, + }, + then: { properties }, + }; +}; + +export const typebotSchema: JSONSchema7 = { + $id: v4(), + type: 'object', + properties: { + enabled: { type: 'boolean', enum: [true, false] }, + url: { type: 'string' }, + typebot: { type: 'string' }, + expire: { type: 'integer' }, + delay_message: { type: 'integer' }, + unknown_message: { type: 'string' }, + listening_from_me: { type: 'boolean', enum: [true, false] }, + }, + required: ['enabled', 'url', 'typebot', 'expire', 'delay_message', 'unknown_message', 'listening_from_me'], + ...isNotEmpty('enabled', 'url', 'typebot', 'expire', 'delay_message', 'unknown_message', 'listening_from_me'), +}; + +export const typebotStatusSchema: JSONSchema7 = { + $id: v4(), + type: 'object', + properties: { + remoteJid: { type: 'string' }, + status: { type: 'string', enum: ['opened', 'closed', 'paused'] }, + }, + required: ['remoteJid', 'status'], + ...isNotEmpty('remoteJid', 'status'), +}; + +export const typebotStartSchema: JSONSchema7 = { + $id: v4(), + type: 'object', + properties: { + remoteJid: { type: 'string' }, + url: { type: 'string' }, + typebot: { type: 'string' }, + }, + required: ['remoteJid', 'url', 'typebot'], + ...isNotEmpty('remoteJid', 'url', 'typebot'), +}; diff --git a/src/whatsapp/controllers/websocket.controller.ts b/src/api/integrations/websocket/controllers/websocket.controller.ts similarity index 93% rename from src/whatsapp/controllers/websocket.controller.ts rename to src/api/integrations/websocket/controllers/websocket.controller.ts index 15abde70..2d207b74 100644 --- a/src/whatsapp/controllers/websocket.controller.ts +++ b/src/api/integrations/websocket/controllers/websocket.controller.ts @@ -1,5 +1,5 @@ -import { Logger } from '../../config/logger.config'; -import { InstanceDto } from '../dto/instance.dto'; +import { Logger } from '../../../../config/logger.config'; +import { InstanceDto } from '../../../dto/instance.dto'; import { WebsocketDto } from '../dto/websocket.dto'; import { WebsocketService } from '../services/websocket.service'; diff --git a/src/whatsapp/dto/websocket.dto.ts b/src/api/integrations/websocket/dto/websocket.dto.ts similarity index 100% rename from src/whatsapp/dto/websocket.dto.ts rename to src/api/integrations/websocket/dto/websocket.dto.ts diff --git a/src/libs/socket.server.ts b/src/api/integrations/websocket/libs/socket.server.ts similarity index 86% rename from src/libs/socket.server.ts rename to src/api/integrations/websocket/libs/socket.server.ts index ecf01ab1..81f97847 100644 --- a/src/libs/socket.server.ts +++ b/src/api/integrations/websocket/libs/socket.server.ts @@ -1,8 +1,8 @@ import { Server } from 'http'; import { Server as SocketIO } from 'socket.io'; -import { configService, Cors, Websocket } from '../config/env.config'; -import { Logger } from '../config/logger.config'; +import { configService, Cors, Websocket } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; const logger = new Logger('Socket'); diff --git a/src/whatsapp/models/websocket.model.ts b/src/api/integrations/websocket/models/websocket.model.ts similarity index 89% rename from src/whatsapp/models/websocket.model.ts rename to src/api/integrations/websocket/models/websocket.model.ts index e96332b1..9e824597 100644 --- a/src/whatsapp/models/websocket.model.ts +++ b/src/api/integrations/websocket/models/websocket.model.ts @@ -1,6 +1,6 @@ import { Schema } from 'mongoose'; -import { dbserver } from '../../libs/db.connect'; +import { dbserver } from '../../../../libs/db.connect'; export class WebsocketRaw { _id?: string; diff --git a/src/whatsapp/repository/websocket.repository.ts b/src/api/integrations/websocket/repository/websocket.repository.ts similarity index 87% rename from src/whatsapp/repository/websocket.repository.ts rename to src/api/integrations/websocket/repository/websocket.repository.ts index 19823194..48d5b7d3 100644 --- a/src/whatsapp/repository/websocket.repository.ts +++ b/src/api/integrations/websocket/repository/websocket.repository.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'fs'; import { join } from 'path'; -import { ConfigService } from '../../config/env.config'; -import { Logger } from '../../config/logger.config'; -import { IInsert, Repository } from '../abstract/abstract.repository'; -import { IWebsocketModel, WebsocketRaw } from '../models'; +import { ConfigService } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; +import { IInsert, Repository } from '../../../abstract/abstract.repository'; +import { IWebsocketModel, WebsocketRaw } from '../../../models'; export class WebsocketRepository extends Repository { constructor(private readonly websocketModel: IWebsocketModel, private readonly configService: ConfigService) { diff --git a/src/whatsapp/routers/websocket.router.ts b/src/api/integrations/websocket/routes/websocket.router.ts similarity index 79% rename from src/whatsapp/routers/websocket.router.ts rename to src/api/integrations/websocket/routes/websocket.router.ts index f04cad0d..271c1ce2 100644 --- a/src/whatsapp/routers/websocket.router.ts +++ b/src/api/integrations/websocket/routes/websocket.router.ts @@ -1,12 +1,12 @@ import { RequestHandler, Router } from 'express'; -import { Logger } from '../../config/logger.config'; -import { instanceNameSchema, websocketSchema } from '../../validate/validate.schema'; -import { RouterBroker } from '../abstract/abstract.router'; -import { InstanceDto } from '../dto/instance.dto'; +import { Logger } from '../../../../config/logger.config'; +import { instanceNameSchema, websocketSchema } from '../../../../validate/validate.schema'; +import { RouterBroker } from '../../../abstract/abstract.router'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { HttpStatus } from '../../../routers/index.router'; +import { websocketController } from '../../../server.module'; import { WebsocketDto } from '../dto/websocket.dto'; -import { websocketController } from '../whatsapp.module'; -import { HttpStatus } from './index.router'; const logger = new Logger('WebsocketRouter'); diff --git a/src/whatsapp/services/websocket.service.ts b/src/api/integrations/websocket/services/websocket.service.ts similarity index 79% rename from src/whatsapp/services/websocket.service.ts rename to src/api/integrations/websocket/services/websocket.service.ts index 20663bbf..fcbb4353 100644 --- a/src/whatsapp/services/websocket.service.ts +++ b/src/api/integrations/websocket/services/websocket.service.ts @@ -1,8 +1,8 @@ -import { Logger } from '../../config/logger.config'; -import { InstanceDto } from '../dto/instance.dto'; +import { Logger } from '../../../../config/logger.config'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { WebsocketRaw } from '../../../models'; +import { WAMonitoringService } from '../../../services/monitor.service'; import { WebsocketDto } from '../dto/websocket.dto'; -import { WebsocketRaw } from '../models'; -import { WAMonitoringService } from './monitor.service'; export class WebsocketService { constructor(private readonly waMonitor: WAMonitoringService) {} diff --git a/src/api/integrations/websocket/validate/websocket.schema.ts b/src/api/integrations/websocket/validate/websocket.schema.ts new file mode 100644 index 00000000..ddddeee2 --- /dev/null +++ b/src/api/integrations/websocket/validate/websocket.schema.ts @@ -0,0 +1,66 @@ +import { JSONSchema7 } from 'json-schema'; +import { v4 } from 'uuid'; + +const isNotEmpty = (...propertyNames: string[]): JSONSchema7 => { + const properties = {}; + propertyNames.forEach( + (property) => + (properties[property] = { + minLength: 1, + description: `The "${property}" cannot be empty`, + }), + ); + return { + if: { + propertyNames: { + enum: [...propertyNames], + }, + }, + then: { properties }, + }; +}; + +export const websocketSchema: JSONSchema7 = { + $id: v4(), + type: 'object', + properties: { + enabled: { type: 'boolean', enum: [true, false] }, + events: { + type: 'array', + minItems: 0, + items: { + type: 'string', + enum: [ + 'APPLICATION_STARTUP', + 'QRCODE_UPDATED', + 'MESSAGES_SET', + 'MESSAGES_UPSERT', + 'MESSAGES_UPDATE', + 'MESSAGES_DELETE', + 'SEND_MESSAGE', + 'CONTACTS_SET', + 'CONTACTS_UPSERT', + 'CONTACTS_UPDATE', + 'PRESENCE_UPDATE', + 'CHATS_SET', + 'CHATS_UPSERT', + 'CHATS_UPDATE', + 'CHATS_DELETE', + 'GROUPS_UPSERT', + 'GROUP_UPDATE', + 'GROUP_PARTICIPANTS_UPDATE', + 'CONNECTION_UPDATE', + 'LABELS_EDIT', + 'LABELS_ASSOCIATION', + 'CALL', + 'NEW_JWT_TOKEN', + 'TYPEBOT_START', + 'TYPEBOT_CHANGE_STATUS', + 'CHAMA_AI_ACTION', + ], + }, + }, + }, + required: ['enabled'], + ...isNotEmpty('enabled'), +}; diff --git a/src/whatsapp/models/auth.model.ts b/src/api/models/auth.model.ts similarity index 100% rename from src/whatsapp/models/auth.model.ts rename to src/api/models/auth.model.ts diff --git a/src/whatsapp/models/chamaai.model.ts b/src/api/models/chamaai.model.ts similarity index 100% rename from src/whatsapp/models/chamaai.model.ts rename to src/api/models/chamaai.model.ts diff --git a/src/whatsapp/models/chat.model.ts b/src/api/models/chat.model.ts similarity index 100% rename from src/whatsapp/models/chat.model.ts rename to src/api/models/chat.model.ts diff --git a/src/whatsapp/models/contact.model.ts b/src/api/models/contact.model.ts similarity index 100% rename from src/whatsapp/models/contact.model.ts rename to src/api/models/contact.model.ts diff --git a/src/whatsapp/models/index.ts b/src/api/models/index.ts similarity index 51% rename from src/whatsapp/models/index.ts rename to src/api/models/index.ts index 743b9760..6cec09a9 100644 --- a/src/whatsapp/models/index.ts +++ b/src/api/models/index.ts @@ -1,15 +1,15 @@ +export * from '../integrations/chatwoot/models/chatwoot.model'; +export * from '../integrations/rabbitmq/models/rabbitmq.model'; +export * from '../integrations/sqs/models/sqs.model'; +export * from '../integrations/typebot/models/typebot.model'; +export * from '../integrations/websocket/models/websocket.model'; export * from './auth.model'; export * from './chamaai.model'; export * from './chat.model'; -export * from './chatwoot.model'; export * from './contact.model'; export * from './integration.model'; export * from './label.model'; export * from './message.model'; export * from './proxy.model'; -export * from './rabbitmq.model'; export * from './settings.model'; -export * from './sqs.model'; -export * from './typebot.model'; export * from './webhook.model'; -export * from './websocket.model'; diff --git a/src/whatsapp/models/integration.model.ts b/src/api/models/integration.model.ts similarity index 100% rename from src/whatsapp/models/integration.model.ts rename to src/api/models/integration.model.ts diff --git a/src/whatsapp/models/label.model.ts b/src/api/models/label.model.ts similarity index 100% rename from src/whatsapp/models/label.model.ts rename to src/api/models/label.model.ts diff --git a/src/whatsapp/models/message.model.ts b/src/api/models/message.model.ts similarity index 100% rename from src/whatsapp/models/message.model.ts rename to src/api/models/message.model.ts diff --git a/src/whatsapp/models/proxy.model.ts b/src/api/models/proxy.model.ts similarity index 100% rename from src/whatsapp/models/proxy.model.ts rename to src/api/models/proxy.model.ts diff --git a/src/whatsapp/models/settings.model.ts b/src/api/models/settings.model.ts similarity index 100% rename from src/whatsapp/models/settings.model.ts rename to src/api/models/settings.model.ts diff --git a/src/whatsapp/models/webhook.model.ts b/src/api/models/webhook.model.ts similarity index 100% rename from src/whatsapp/models/webhook.model.ts rename to src/api/models/webhook.model.ts diff --git a/src/whatsapp/repository/auth.repository.ts b/src/api/repository/auth.repository.ts similarity index 100% rename from src/whatsapp/repository/auth.repository.ts rename to src/api/repository/auth.repository.ts diff --git a/src/whatsapp/repository/chamaai.repository.ts b/src/api/repository/chamaai.repository.ts similarity index 100% rename from src/whatsapp/repository/chamaai.repository.ts rename to src/api/repository/chamaai.repository.ts diff --git a/src/whatsapp/repository/chat.repository.ts b/src/api/repository/chat.repository.ts similarity index 100% rename from src/whatsapp/repository/chat.repository.ts rename to src/api/repository/chat.repository.ts diff --git a/src/whatsapp/repository/contact.repository.ts b/src/api/repository/contact.repository.ts similarity index 100% rename from src/whatsapp/repository/contact.repository.ts rename to src/api/repository/contact.repository.ts diff --git a/src/whatsapp/repository/integration.repository.ts b/src/api/repository/integration.repository.ts similarity index 100% rename from src/whatsapp/repository/integration.repository.ts rename to src/api/repository/integration.repository.ts diff --git a/src/whatsapp/repository/label.repository.ts b/src/api/repository/label.repository.ts similarity index 100% rename from src/whatsapp/repository/label.repository.ts rename to src/api/repository/label.repository.ts diff --git a/src/whatsapp/repository/message.repository.ts b/src/api/repository/message.repository.ts similarity index 100% rename from src/whatsapp/repository/message.repository.ts rename to src/api/repository/message.repository.ts diff --git a/src/whatsapp/repository/messageUp.repository.ts b/src/api/repository/messageUp.repository.ts similarity index 100% rename from src/whatsapp/repository/messageUp.repository.ts rename to src/api/repository/messageUp.repository.ts diff --git a/src/whatsapp/repository/proxy.repository.ts b/src/api/repository/proxy.repository.ts similarity index 100% rename from src/whatsapp/repository/proxy.repository.ts rename to src/api/repository/proxy.repository.ts diff --git a/src/whatsapp/repository/repository.manager.ts b/src/api/repository/repository.manager.ts similarity index 93% rename from src/whatsapp/repository/repository.manager.ts rename to src/api/repository/repository.manager.ts index 10207eb3..2ea54aa1 100644 --- a/src/whatsapp/repository/repository.manager.ts +++ b/src/api/repository/repository.manager.ts @@ -4,22 +4,22 @@ import { join } from 'path'; import { Auth, ConfigService, Database } from '../../config/env.config'; import { Logger } from '../../config/logger.config'; +import { ChatwootRepository } from '../integrations/chatwoot/repository/chatwoot.repository'; +import { RabbitmqRepository } from '../integrations/rabbitmq/repository/rabbitmq.repository'; +import { SqsRepository } from '../integrations/sqs/repository/sqs.repository'; +import { TypebotRepository } from '../integrations/typebot/repository/typebot.repository'; +import { WebsocketRepository } from '../integrations/websocket/repository/websocket.repository'; import { AuthRepository } from './auth.repository'; import { ChamaaiRepository } from './chamaai.repository'; import { ChatRepository } from './chat.repository'; -import { ChatwootRepository } from './chatwoot.repository'; import { ContactRepository } from './contact.repository'; import { IntegrationRepository } from './integration.repository'; import { LabelRepository } from './label.repository'; import { MessageRepository } from './message.repository'; import { MessageUpRepository } from './messageUp.repository'; import { ProxyRepository } from './proxy.repository'; -import { RabbitmqRepository } from './rabbitmq.repository'; import { SettingsRepository } from './settings.repository'; -import { SqsRepository } from './sqs.repository'; -import { TypebotRepository } from './typebot.repository'; import { WebhookRepository } from './webhook.repository'; -import { WebsocketRepository } from './websocket.repository'; export class RepositoryBroker { constructor( public readonly message: MessageRepository, diff --git a/src/whatsapp/repository/settings.repository.ts b/src/api/repository/settings.repository.ts similarity index 100% rename from src/whatsapp/repository/settings.repository.ts rename to src/api/repository/settings.repository.ts diff --git a/src/whatsapp/repository/webhook.repository.ts b/src/api/repository/webhook.repository.ts similarity index 100% rename from src/whatsapp/repository/webhook.repository.ts rename to src/api/repository/webhook.repository.ts diff --git a/src/whatsapp/routers/chamaai.router.ts b/src/api/routers/chamaai.router.ts similarity index 96% rename from src/whatsapp/routers/chamaai.router.ts rename to src/api/routers/chamaai.router.ts index e8021306..93644af3 100644 --- a/src/whatsapp/routers/chamaai.router.ts +++ b/src/api/routers/chamaai.router.ts @@ -5,7 +5,7 @@ import { chamaaiSchema, instanceNameSchema } from '../../validate/validate.schem import { RouterBroker } from '../abstract/abstract.router'; import { ChamaaiDto } from '../dto/chamaai.dto'; import { InstanceDto } from '../dto/instance.dto'; -import { chamaaiController } from '../whatsapp.module'; +import { chamaaiController } from '../server.module'; import { HttpStatus } from './index.router'; const logger = new Logger('ChamaaiRouter'); diff --git a/src/whatsapp/routers/chat.router.ts b/src/api/routers/chat.router.ts similarity index 99% rename from src/whatsapp/routers/chat.router.ts rename to src/api/routers/chat.router.ts index a0ce3216..e8c82a16 100644 --- a/src/whatsapp/routers/chat.router.ts +++ b/src/api/routers/chat.router.ts @@ -38,7 +38,7 @@ import { InstanceDto } from '../dto/instance.dto'; import { ContactQuery } from '../repository/contact.repository'; import { MessageQuery } from '../repository/message.repository'; import { MessageUpQuery } from '../repository/messageUp.repository'; -import { chatController } from '../whatsapp.module'; +import { chatController } from '../server.module'; import { HttpStatus } from './index.router'; const logger = new Logger('ChatRouter'); diff --git a/src/whatsapp/routers/group.router.ts b/src/api/routers/group.router.ts similarity index 99% rename from src/whatsapp/routers/group.router.ts rename to src/api/routers/group.router.ts index bf088129..244dfee2 100644 --- a/src/whatsapp/routers/group.router.ts +++ b/src/api/routers/group.router.ts @@ -30,7 +30,7 @@ import { GroupUpdateParticipantDto, GroupUpdateSettingDto, } from '../dto/group.dto'; -import { groupController } from '../whatsapp.module'; +import { groupController } from '../server.module'; import { HttpStatus } from './index.router'; const logger = new Logger('GroupRouter'); diff --git a/src/whatsapp/routers/index.router.ts b/src/api/routers/index.router.ts similarity index 86% rename from src/whatsapp/routers/index.router.ts rename to src/api/routers/index.router.ts index 51460339..8d17ab6f 100644 --- a/src/whatsapp/routers/index.router.ts +++ b/src/api/routers/index.router.ts @@ -4,21 +4,21 @@ import fs from 'fs'; import { Auth, configService } from '../../config/env.config'; import { authGuard } from '../guards/auth.guard'; import { instanceExistsGuard, instanceLoggedGuard } from '../guards/instance.guard'; +import { ChatwootRouter } from '../integrations/chatwoot/routes/chatwoot.router'; +import { RabbitmqRouter } from '../integrations/rabbitmq/routes/rabbitmq.router'; +import { SqsRouter } from '../integrations/sqs/routes/sqs.router'; +import { TypebotRouter } from '../integrations/typebot/routes/typebot.router'; +import { WebsocketRouter } from '../integrations/websocket/routes/websocket.router'; import { ChamaaiRouter } from './chamaai.router'; import { ChatRouter } from './chat.router'; -import { ChatwootRouter } from './chatwoot.router'; import { GroupRouter } from './group.router'; import { InstanceRouter } from './instance.router'; import { LabelRouter } from './label.router'; import { ProxyRouter } from './proxy.router'; -import { RabbitmqRouter } from './rabbitmq.router'; import { MessageRouter } from './sendMessage.router'; import { SettingsRouter } from './settings.router'; -import { SqsRouter } from './sqs.router'; -import { TypebotRouter } from './typebot.router'; import { ViewsRouter } from './view.router'; import { WebhookRouter } from './webhook.router'; -import { WebsocketRouter } from './websocket.router'; enum HttpStatus { OK = 200, diff --git a/src/whatsapp/routers/instance.router.ts b/src/api/routers/instance.router.ts similarity index 99% rename from src/whatsapp/routers/instance.router.ts rename to src/api/routers/instance.router.ts index fa78c197..a56271a4 100644 --- a/src/whatsapp/routers/instance.router.ts +++ b/src/api/routers/instance.router.ts @@ -6,8 +6,8 @@ import { dbserver } from '../../libs/db.connect'; import { instanceNameSchema, oldTokenSchema, presenceOnlySchema } from '../../validate/validate.schema'; import { RouterBroker } from '../abstract/abstract.router'; import { InstanceDto, SetPresenceDto } from '../dto/instance.dto'; +import { instanceController } from '../server.module'; import { OldToken } from '../services/auth.service'; -import { instanceController } from '../whatsapp.module'; import { HttpStatus } from './index.router'; const logger = new Logger('InstanceRouter'); diff --git a/src/whatsapp/routers/label.router.ts b/src/api/routers/label.router.ts similarity index 97% rename from src/whatsapp/routers/label.router.ts rename to src/api/routers/label.router.ts index a856ff6d..a6002bb9 100644 --- a/src/whatsapp/routers/label.router.ts +++ b/src/api/routers/label.router.ts @@ -4,7 +4,7 @@ import { Logger } from '../../config/logger.config'; import { handleLabelSchema } from '../../validate/validate.schema'; import { RouterBroker } from '../abstract/abstract.router'; import { HandleLabelDto, LabelDto } from '../dto/label.dto'; -import { labelController } from '../whatsapp.module'; +import { labelController } from '../server.module'; import { HttpStatus } from './index.router'; const logger = new Logger('LabelRouter'); diff --git a/src/whatsapp/routers/proxy.router.ts b/src/api/routers/proxy.router.ts similarity index 97% rename from src/whatsapp/routers/proxy.router.ts rename to src/api/routers/proxy.router.ts index 2ae0141b..284fe368 100644 --- a/src/whatsapp/routers/proxy.router.ts +++ b/src/api/routers/proxy.router.ts @@ -5,7 +5,7 @@ import { instanceNameSchema, proxySchema } from '../../validate/validate.schema' import { RouterBroker } from '../abstract/abstract.router'; import { InstanceDto } from '../dto/instance.dto'; import { ProxyDto } from '../dto/proxy.dto'; -import { proxyController } from '../whatsapp.module'; +import { proxyController } from '../server.module'; import { HttpStatus } from './index.router'; const logger = new Logger('ProxyRouter'); diff --git a/src/whatsapp/routers/sendMessage.router.ts b/src/api/routers/sendMessage.router.ts similarity index 99% rename from src/whatsapp/routers/sendMessage.router.ts rename to src/api/routers/sendMessage.router.ts index 51b60593..908a1a58 100644 --- a/src/whatsapp/routers/sendMessage.router.ts +++ b/src/api/routers/sendMessage.router.ts @@ -30,7 +30,7 @@ import { SendTemplateDto, SendTextDto, } from '../dto/sendMessage.dto'; -import { sendMessageController } from '../whatsapp.module'; +import { sendMessageController } from '../server.module'; import { HttpStatus } from './index.router'; const logger = new Logger('MessageRouter'); diff --git a/src/whatsapp/routers/settings.router.ts b/src/api/routers/settings.router.ts similarity index 96% rename from src/whatsapp/routers/settings.router.ts rename to src/api/routers/settings.router.ts index 57e56b0d..c2d3bad9 100644 --- a/src/whatsapp/routers/settings.router.ts +++ b/src/api/routers/settings.router.ts @@ -5,7 +5,7 @@ import { instanceNameSchema, settingsSchema } from '../../validate/validate.sche import { RouterBroker } from '../abstract/abstract.router'; import { InstanceDto } from '../dto/instance.dto'; import { SettingsDto } from '../dto/settings.dto'; -import { settingsController } from '../whatsapp.module'; +import { settingsController } from '../server.module'; import { HttpStatus } from './index.router'; const logger = new Logger('SettingsRouter'); diff --git a/src/whatsapp/routers/view.router.ts b/src/api/routers/view.router.ts similarity index 100% rename from src/whatsapp/routers/view.router.ts rename to src/api/routers/view.router.ts diff --git a/src/whatsapp/routers/webhook.router.ts b/src/api/routers/webhook.router.ts similarity index 98% rename from src/whatsapp/routers/webhook.router.ts rename to src/api/routers/webhook.router.ts index 255b6ac5..1e4ddcac 100644 --- a/src/whatsapp/routers/webhook.router.ts +++ b/src/api/routers/webhook.router.ts @@ -6,7 +6,7 @@ import { instanceNameSchema, webhookSchema } from '../../validate/validate.schem import { RouterBroker } from '../abstract/abstract.router'; import { InstanceDto } from '../dto/instance.dto'; import { WebhookDto } from '../dto/webhook.dto'; -import { webhookController } from '../whatsapp.module'; +import { webhookController } from '../server.module'; import { HttpStatus } from './index.router'; const logger = new Logger('WebhookRouter'); diff --git a/src/whatsapp/whatsapp.module.ts b/src/api/server.module.ts similarity index 82% rename from src/whatsapp/whatsapp.module.ts rename to src/api/server.module.ts index 366988e2..67512cac 100644 --- a/src/whatsapp/whatsapp.module.ts +++ b/src/api/server.module.ts @@ -1,23 +1,33 @@ import { configService } from '../config/env.config'; import { eventEmitter } from '../config/event.config'; import { Logger } from '../config/logger.config'; -import { CacheEngine } from '../libs/cacheengine'; import { dbserver } from '../libs/db.connect'; import { RedisCache } from '../libs/redis.client'; import { ChamaaiController } from './controllers/chamaai.controller'; import { ChatController } from './controllers/chat.controller'; -import { ChatwootController } from './controllers/chatwoot.controller'; import { GroupController } from './controllers/group.controller'; import { InstanceController } from './controllers/instance.controller'; import { LabelController } from './controllers/label.controller'; import { ProxyController } from './controllers/proxy.controller'; -import { RabbitmqController } from './controllers/rabbitmq.controller'; import { SendMessageController } from './controllers/sendMessage.controller'; import { SettingsController } from './controllers/settings.controller'; -import { SqsController } from './controllers/sqs.controller'; -import { TypebotController } from './controllers/typebot.controller'; import { WebhookController } from './controllers/webhook.controller'; -import { WebsocketController } from './controllers/websocket.controller'; +import { CacheEngine } from './integrations/chatwoot/cache/cacheengine'; +import { ChatwootController } from './integrations/chatwoot/controllers/chatwoot.controller'; +import { ChatwootRepository } from './integrations/chatwoot/repository/chatwoot.repository'; +import { ChatwootService } from './integrations/chatwoot/services/chatwoot.service'; +import { RabbitmqController } from './integrations/rabbitmq/controllers/rabbitmq.controller'; +import { RabbitmqRepository } from './integrations/rabbitmq/repository/rabbitmq.repository'; +import { RabbitmqService } from './integrations/rabbitmq/services/rabbitmq.service'; +import { SqsController } from './integrations/sqs/controllers/sqs.controller'; +import { SqsRepository } from './integrations/sqs/repository/sqs.repository'; +import { SqsService } from './integrations/sqs/services/sqs.service'; +import { TypebotController } from './integrations/typebot/controllers/typebot.controller'; +import { TypebotRepository } from './integrations/typebot/repository/typebot.repository'; +import { TypebotService } from './integrations/typebot/services/typebot.service'; +import { WebsocketController } from './integrations/websocket/controllers/websocket.controller'; +import { WebsocketRepository } from './integrations/websocket/repository/websocket.repository'; +import { WebsocketService } from './integrations/websocket/services/websocket.service'; import { AuthModel, ChamaaiModel, @@ -39,33 +49,23 @@ import { LabelModel } from './models/label.model'; import { AuthRepository } from './repository/auth.repository'; import { ChamaaiRepository } from './repository/chamaai.repository'; import { ChatRepository } from './repository/chat.repository'; -import { ChatwootRepository } from './repository/chatwoot.repository'; import { ContactRepository } from './repository/contact.repository'; import { IntegrationRepository } from './repository/integration.repository'; import { LabelRepository } from './repository/label.repository'; import { MessageRepository } from './repository/message.repository'; import { MessageUpRepository } from './repository/messageUp.repository'; import { ProxyRepository } from './repository/proxy.repository'; -import { RabbitmqRepository } from './repository/rabbitmq.repository'; import { RepositoryBroker } from './repository/repository.manager'; import { SettingsRepository } from './repository/settings.repository'; -import { SqsRepository } from './repository/sqs.repository'; -import { TypebotRepository } from './repository/typebot.repository'; import { WebhookRepository } from './repository/webhook.repository'; -import { WebsocketRepository } from './repository/websocket.repository'; import { AuthService } from './services/auth.service'; import { CacheService } from './services/cache.service'; import { ChamaaiService } from './services/chamaai.service'; -import { ChatwootService } from './services/chatwoot.service'; import { IntegrationService } from './services/integration.service'; import { WAMonitoringService } from './services/monitor.service'; import { ProxyService } from './services/proxy.service'; -import { RabbitmqService } from './services/rabbitmq.service'; import { SettingsService } from './services/settings.service'; -import { SqsService } from './services/sqs.service'; -import { TypebotService } from './services/typebot.service'; import { WebhookService } from './services/webhook.service'; -import { WebsocketService } from './services/websocket.service'; const logger = new Logger('WA MODULE'); diff --git a/src/whatsapp/services/auth.service.ts b/src/api/services/auth.service.ts similarity index 100% rename from src/whatsapp/services/auth.service.ts rename to src/api/services/auth.service.ts diff --git a/src/whatsapp/services/cache.service.ts b/src/api/services/cache.service.ts similarity index 100% rename from src/whatsapp/services/cache.service.ts rename to src/api/services/cache.service.ts diff --git a/src/whatsapp/services/chamaai.service.ts b/src/api/services/chamaai.service.ts similarity index 100% rename from src/whatsapp/services/chamaai.service.ts rename to src/api/services/chamaai.service.ts diff --git a/src/whatsapp/services/integration.service.ts b/src/api/services/integration.service.ts similarity index 100% rename from src/whatsapp/services/integration.service.ts rename to src/api/services/integration.service.ts diff --git a/src/whatsapp/services/monitor.service.ts b/src/api/services/monitor.service.ts similarity index 100% rename from src/whatsapp/services/monitor.service.ts rename to src/api/services/monitor.service.ts diff --git a/src/whatsapp/services/proxy.service.ts b/src/api/services/proxy.service.ts similarity index 100% rename from src/whatsapp/services/proxy.service.ts rename to src/api/services/proxy.service.ts diff --git a/src/whatsapp/services/settings.service.ts b/src/api/services/settings.service.ts similarity index 100% rename from src/whatsapp/services/settings.service.ts rename to src/api/services/settings.service.ts diff --git a/src/whatsapp/services/webhook.service.ts b/src/api/services/webhook.service.ts similarity index 100% rename from src/whatsapp/services/webhook.service.ts rename to src/api/services/webhook.service.ts diff --git a/src/whatsapp/services/whatsapp.baileys.service.ts b/src/api/services/whatsapp.baileys.service.ts similarity index 99% rename from src/whatsapp/services/whatsapp.baileys.service.ts rename to src/api/services/whatsapp.baileys.service.ts index 4cf9f4e2..ef39b0fc 100644 --- a/src/whatsapp/services/whatsapp.baileys.service.ts +++ b/src/api/services/whatsapp.baileys.service.ts @@ -59,7 +59,6 @@ import { INSTANCE_DIR } from '../../config/path.config'; import { BadRequestException, InternalServerErrorException, NotFoundException } from '../../exceptions'; import { dbserver } from '../../libs/db.connect'; import { RedisCache } from '../../libs/redis.client'; -import { chatwootImport } from '../../utils/chatwoot-import-helper'; import { makeProxyAgent } from '../../utils/makeProxyAgent'; import { useMultiFileAuthStateDb } from '../../utils/use-multi-file-auth-state-db'; import { useMultiFileAuthStateRedisDb } from '../../utils/use-multi-file-auth-state-redis-db'; @@ -110,13 +109,14 @@ import { SendTextDto, StatusMessage, } from '../dto/sendMessage.dto'; +import { chatwootImport } from '../integrations/chatwoot/utils/chatwoot-import-helper'; import { SettingsRaw } from '../models'; import { ChatRaw } from '../models/chat.model'; import { ContactRaw } from '../models/contact.model'; import { MessageRaw, MessageUpdateRaw } from '../models/message.model'; import { RepositoryBroker } from '../repository/repository.manager'; +import { waMonitor } from '../server.module'; import { Events, MessageSubtype, TypeMediaMessage, wa } from '../types/wa.types'; -import { waMonitor } from '../whatsapp.module'; import { CacheService } from './cache.service'; import { WAStartupService } from './whatsapp.service'; diff --git a/src/whatsapp/services/whatsapp.business.service.ts b/src/api/services/whatsapp.business.service.ts similarity index 100% rename from src/whatsapp/services/whatsapp.business.service.ts rename to src/api/services/whatsapp.business.service.ts diff --git a/src/whatsapp/services/whatsapp.service.ts b/src/api/services/whatsapp.service.ts similarity index 98% rename from src/whatsapp/services/whatsapp.service.ts rename to src/api/services/whatsapp.service.ts index eaa4dc65..b9cece5a 100644 --- a/src/whatsapp/services/whatsapp.service.ts +++ b/src/api/services/whatsapp.service.ts @@ -20,23 +20,23 @@ import { import { Logger } from '../../config/logger.config'; import { ROOT_DIR } from '../../config/path.config'; import { NotFoundException } from '../../exceptions'; -import { getAMQP, removeQueues } from '../../libs/amqp.server'; -import { getIO } from '../../libs/socket.server'; -import { getSQS, removeQueues as removeQueuesSQS } from '../../libs/sqs.server'; +import { ChatwootRaw } from '../integrations/chatwoot/models/chatwoot.model'; +import { ChatwootService } from '../integrations/chatwoot/services/chatwoot.service'; +import { getAMQP, removeQueues } from '../integrations/rabbitmq/libs/amqp.server'; +import { getSQS, removeQueues as removeQueuesSQS } from '../integrations/sqs/libs/sqs.server'; +import { TypebotService } from '../integrations/typebot/services/typebot.service'; +import { getIO } from '../integrations/websocket/libs/socket.server'; +import { WebsocketRaw } from '../integrations/websocket/models/websocket.model'; import { ChamaaiRaw, IntegrationRaw, ProxyRaw, RabbitmqRaw, SettingsRaw, SqsRaw, TypebotRaw } from '../models'; -import { ChatwootRaw } from '../models/chatwoot.model'; import { WebhookRaw } from '../models/webhook.model'; -import { WebsocketRaw } from '../models/websocket.model'; import { ContactQuery } from '../repository/contact.repository'; import { MessageQuery } from '../repository/message.repository'; import { MessageUpQuery } from '../repository/messageUp.repository'; import { RepositoryBroker } from '../repository/repository.manager'; +import { waMonitor } from '../server.module'; import { Events, wa } from '../types/wa.types'; -import { waMonitor } from '../whatsapp.module'; import { CacheService } from './cache.service'; import { ChamaaiService } from './chamaai.service'; -import { ChatwootService } from './chatwoot.service'; -import { TypebotService } from './typebot.service'; export class WAStartupService { constructor( diff --git a/src/whatsapp/types/wa.types.ts b/src/api/types/wa.types.ts similarity index 100% rename from src/whatsapp/types/wa.types.ts rename to src/api/types/wa.types.ts diff --git a/src/exceptions/400.exception.ts b/src/exceptions/400.exception.ts index 833295c1..6697aeb2 100644 --- a/src/exceptions/400.exception.ts +++ b/src/exceptions/400.exception.ts @@ -1,4 +1,4 @@ -import { HttpStatus } from '../whatsapp/routers/index.router'; +import { HttpStatus } from '../api/routers/index.router'; export class BadRequestException { constructor(...objectError: any[]) { diff --git a/src/exceptions/401.exception.ts b/src/exceptions/401.exception.ts index d5424c71..8fd72da2 100644 --- a/src/exceptions/401.exception.ts +++ b/src/exceptions/401.exception.ts @@ -1,4 +1,4 @@ -import { HttpStatus } from '../whatsapp/routers/index.router'; +import { HttpStatus } from '../api/routers/index.router'; export class UnauthorizedException { constructor(...objectError: any[]) { diff --git a/src/exceptions/403.exception.ts b/src/exceptions/403.exception.ts index f53ca9a5..a7c118bd 100644 --- a/src/exceptions/403.exception.ts +++ b/src/exceptions/403.exception.ts @@ -1,4 +1,4 @@ -import { HttpStatus } from '../whatsapp/routers/index.router'; +import { HttpStatus } from '../api/routers/index.router'; export class ForbiddenException { constructor(...objectError: any[]) { diff --git a/src/exceptions/404.exception.ts b/src/exceptions/404.exception.ts index 1119d1a1..6c06f095 100644 --- a/src/exceptions/404.exception.ts +++ b/src/exceptions/404.exception.ts @@ -1,4 +1,4 @@ -import { HttpStatus } from '../whatsapp/routers/index.router'; +import { HttpStatus } from '../api/routers/index.router'; export class NotFoundException { constructor(...objectError: any[]) { diff --git a/src/exceptions/500.exception.ts b/src/exceptions/500.exception.ts index 2a41dfa5..445f240b 100644 --- a/src/exceptions/500.exception.ts +++ b/src/exceptions/500.exception.ts @@ -1,4 +1,4 @@ -import { HttpStatus } from '../whatsapp/routers/index.router'; +import { HttpStatus } from '../api/routers/index.router'; export class InternalServerErrorException { constructor(...objectError: any[]) { diff --git a/src/main.ts b/src/main.ts index 554d95e8..49a3d153 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,17 +6,17 @@ import cors from 'cors'; import express, { json, NextFunction, Request, Response, urlencoded } from 'express'; import { join } from 'path'; +import { initAMQP } from './api/integrations/rabbitmq/libs/amqp.server'; +import { initSQS } from './api/integrations/sqs/libs/sqs.server'; +import { initIO } from './api/integrations/websocket/libs/socket.server'; +import { HttpStatus, router } from './api/routers/index.router'; +import { waMonitor } from './api/server.module'; import { Auth, configService, Cors, HttpServer, Rabbitmq, Sqs, Webhook } from './config/env.config'; import { onUnexpectedError } from './config/error.config'; import { Logger } from './config/logger.config'; import { ROOT_DIR } from './config/path.config'; import { swaggerRouter } from './docs/swagger.conf'; -import { initAMQP } from './libs/amqp.server'; -import { initIO } from './libs/socket.server'; -import { initSQS } from './libs/sqs.server'; import { ServerUP } from './utils/server-up'; -import { HttpStatus, router } from './whatsapp/routers/index.router'; -import { waMonitor } from './whatsapp/whatsapp.module'; function initWA() { waMonitor.loadInstance(); diff --git a/src/utils/makeProxyAgent.ts b/src/utils/makeProxyAgent.ts index 45486523..60d5f20c 100644 --- a/src/utils/makeProxyAgent.ts +++ b/src/utils/makeProxyAgent.ts @@ -1,6 +1,6 @@ import { HttpsProxyAgent } from 'https-proxy-agent'; -import { wa } from '../whatsapp/types/wa.types'; +import { wa } from '../api/types/wa.types'; export function makeProxyAgent(proxy: wa.Proxy | string) { if (typeof proxy === 'string') { diff --git a/src/validate/validate.schema.ts b/src/validate/validate.schema.ts index b723826a..6bafb9b9 100644 --- a/src/validate/validate.schema.ts +++ b/src/validate/validate.schema.ts @@ -1,6 +1,12 @@ import { JSONSchema7, JSONSchema7Definition } from 'json-schema'; import { v4 } from 'uuid'; +// Integrations Schema +export * from '../api/integrations/chatwoot/validate/chatwoot.schema'; +export * from '../api/integrations/rabbitmq/validate/rabbitmq.schema'; +export * from '../api/integrations/sqs/validate/sqs.schema'; +export * from '../api/integrations/typebot/validate/typebot.schema'; + const isNotEmpty = (...propertyNames: string[]): JSONSchema7 => { const properties = {}; propertyNames.forEach( @@ -957,27 +963,6 @@ export const webhookSchema: JSONSchema7 = { ...isNotEmpty('url'), }; -export const chatwootSchema: JSONSchema7 = { - $id: v4(), - type: 'object', - properties: { - enabled: { type: 'boolean', enum: [true, false] }, - account_id: { type: 'string' }, - token: { type: 'string' }, - url: { type: 'string' }, - sign_msg: { type: 'boolean', enum: [true, false] }, - sign_delimiter: { type: ['string', 'null'] }, - reopen_conversation: { type: 'boolean', enum: [true, false] }, - conversation_pending: { type: 'boolean', enum: [true, false] }, - auto_create: { type: 'boolean', enum: [true, false] }, - import_contacts: { type: 'boolean', enum: [true, false] }, - import_messages: { type: 'boolean', enum: [true, false] }, - days_limit_import_messages: { type: 'number' }, - }, - required: ['enabled', 'account_id', 'token', 'url', 'sign_msg', 'reopen_conversation', 'conversation_pending'], - ...isNotEmpty('account_id', 'token', 'url', 'sign_msg', 'reopen_conversation', 'conversation_pending'), -}; - export const settingsSchema: JSONSchema7 = { $id: v4(), type: 'object', @@ -1039,135 +1024,6 @@ export const websocketSchema: JSONSchema7 = { ...isNotEmpty('enabled'), }; -export const rabbitmqSchema: JSONSchema7 = { - $id: v4(), - type: 'object', - properties: { - enabled: { type: 'boolean', enum: [true, false] }, - events: { - type: 'array', - minItems: 0, - items: { - type: 'string', - enum: [ - 'APPLICATION_STARTUP', - 'QRCODE_UPDATED', - 'MESSAGES_SET', - 'MESSAGES_UPSERT', - 'MESSAGES_UPDATE', - 'MESSAGES_DELETE', - 'SEND_MESSAGE', - 'CONTACTS_SET', - 'CONTACTS_UPSERT', - 'CONTACTS_UPDATE', - 'PRESENCE_UPDATE', - 'CHATS_SET', - 'CHATS_UPSERT', - 'CHATS_UPDATE', - 'CHATS_DELETE', - 'GROUPS_UPSERT', - 'GROUP_UPDATE', - 'GROUP_PARTICIPANTS_UPDATE', - 'CONNECTION_UPDATE', - 'LABELS_EDIT', - 'LABELS_ASSOCIATION', - 'CALL', - 'NEW_JWT_TOKEN', - 'TYPEBOT_START', - 'TYPEBOT_CHANGE_STATUS', - 'CHAMA_AI_ACTION', - ], - }, - }, - }, - required: ['enabled'], - ...isNotEmpty('enabled'), -}; - -export const sqsSchema: JSONSchema7 = { - $id: v4(), - type: 'object', - properties: { - enabled: { type: 'boolean', enum: [true, false] }, - events: { - type: 'array', - minItems: 0, - items: { - type: 'string', - enum: [ - 'APPLICATION_STARTUP', - 'QRCODE_UPDATED', - 'MESSAGES_SET', - 'MESSAGES_UPSERT', - 'MESSAGES_UPDATE', - 'MESSAGES_DELETE', - 'SEND_MESSAGE', - 'CONTACTS_SET', - 'CONTACTS_UPSERT', - 'CONTACTS_UPDATE', - 'PRESENCE_UPDATE', - 'CHATS_SET', - 'CHATS_UPSERT', - 'CHATS_UPDATE', - 'CHATS_DELETE', - 'GROUPS_UPSERT', - 'GROUP_UPDATE', - 'GROUP_PARTICIPANTS_UPDATE', - 'CONNECTION_UPDATE', - 'LABELS_EDIT', - 'LABELS_ASSOCIATION', - 'CALL', - 'NEW_JWT_TOKEN', - 'TYPEBOT_START', - 'TYPEBOT_CHANGE_STATUS', - 'CHAMA_AI_ACTION', - ], - }, - }, - }, - required: ['enabled'], - ...isNotEmpty('enabled'), -}; - -export const typebotSchema: JSONSchema7 = { - $id: v4(), - type: 'object', - properties: { - enabled: { type: 'boolean', enum: [true, false] }, - url: { type: 'string' }, - typebot: { type: 'string' }, - expire: { type: 'integer' }, - delay_message: { type: 'integer' }, - unknown_message: { type: 'string' }, - listening_from_me: { type: 'boolean', enum: [true, false] }, - }, - required: ['enabled', 'url', 'typebot', 'expire', 'delay_message', 'unknown_message', 'listening_from_me'], - ...isNotEmpty('enabled', 'url', 'typebot', 'expire', 'delay_message', 'unknown_message', 'listening_from_me'), -}; - -export const typebotStatusSchema: JSONSchema7 = { - $id: v4(), - type: 'object', - properties: { - remoteJid: { type: 'string' }, - status: { type: 'string', enum: ['opened', 'closed', 'paused'] }, - }, - required: ['remoteJid', 'status'], - ...isNotEmpty('remoteJid', 'status'), -}; - -export const typebotStartSchema: JSONSchema7 = { - $id: v4(), - type: 'object', - properties: { - remoteJid: { type: 'string' }, - url: { type: 'string' }, - typebot: { type: 'string' }, - }, - required: ['remoteJid', 'url', 'typebot'], - ...isNotEmpty('remoteJid', 'url', 'typebot'), -}; - export const proxySchema: JSONSchema7 = { $id: v4(), type: 'object', From eb04c3f1133dc04aadcc696b5267935746e1e58b Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 12 Apr 2024 17:15:13 -0300 Subject: [PATCH 18/42] fix: reorganization of files and folders --- src/api/controllers/instance.controller.ts | 4 +- src/api/services/monitor.service.ts | 4 +- .../whatsapp.baileys.service.ts | 46 +++++++++---------- .../whatsapp.business.service.ts | 20 ++++---- 4 files changed, 37 insertions(+), 37 deletions(-) rename src/api/services/{ => whatsapp}/whatsapp.baileys.service.ts (98%) rename src/api/services/{ => whatsapp}/whatsapp.business.service.ts (98%) diff --git a/src/api/controllers/instance.controller.ts b/src/api/controllers/instance.controller.ts index 4767db73..563bc5fd 100644 --- a/src/api/controllers/instance.controller.ts +++ b/src/api/controllers/instance.controller.ts @@ -20,8 +20,8 @@ import { IntegrationService } from '../services/integration.service'; import { WAMonitoringService } from '../services/monitor.service'; import { SettingsService } from '../services/settings.service'; import { WebhookService } from '../services/webhook.service'; -import { BaileysStartupService } from '../services/whatsapp.baileys.service'; -import { BusinessStartupService } from '../services/whatsapp.business.service'; +import { BaileysStartupService } from '../services/whatsapp/whatsapp.baileys.service'; +import { BusinessStartupService } from '../services/whatsapp/whatsapp.business.service'; import { Events, Integration, wa } from '../types/wa.types'; import { ProxyController } from './proxy.controller'; diff --git a/src/api/services/monitor.service.ts b/src/api/services/monitor.service.ts index f8148926..e8644e99 100644 --- a/src/api/services/monitor.service.ts +++ b/src/api/services/monitor.service.ts @@ -26,8 +26,8 @@ import { import { RepositoryBroker } from '../repository/repository.manager'; import { Integration } from '../types/wa.types'; import { CacheService } from './cache.service'; -import { BaileysStartupService } from './whatsapp.baileys.service'; -import { BusinessStartupService } from './whatsapp.business.service'; +import { BaileysStartupService } from './whatsapp/whatsapp.baileys.service'; +import { BusinessStartupService } from './whatsapp/whatsapp.business.service'; export class WAMonitoringService { constructor( diff --git a/src/api/services/whatsapp.baileys.service.ts b/src/api/services/whatsapp/whatsapp.baileys.service.ts similarity index 98% rename from src/api/services/whatsapp.baileys.service.ts rename to src/api/services/whatsapp/whatsapp.baileys.service.ts index ef39b0fc..6285250b 100644 --- a/src/api/services/whatsapp.baileys.service.ts +++ b/src/api/services/whatsapp/whatsapp.baileys.service.ts @@ -54,14 +54,14 @@ import qrcode, { QRCodeToDataURLOptions } from 'qrcode'; import qrcodeTerminal from 'qrcode-terminal'; import sharp from 'sharp'; -import { ConfigService, ConfigSessionPhone, Database, Log, QrCode, Redis } from '../../config/env.config'; -import { INSTANCE_DIR } from '../../config/path.config'; -import { BadRequestException, InternalServerErrorException, NotFoundException } from '../../exceptions'; -import { dbserver } from '../../libs/db.connect'; -import { RedisCache } from '../../libs/redis.client'; -import { makeProxyAgent } from '../../utils/makeProxyAgent'; -import { useMultiFileAuthStateDb } from '../../utils/use-multi-file-auth-state-db'; -import { useMultiFileAuthStateRedisDb } from '../../utils/use-multi-file-auth-state-redis-db'; +import { ConfigService, ConfigSessionPhone, Database, Log, QrCode, Redis } from '../../../config/env.config'; +import { INSTANCE_DIR } from '../../../config/path.config'; +import { BadRequestException, InternalServerErrorException, NotFoundException } from '../../../exceptions'; +import { dbserver } from '../../../libs/db.connect'; +import { RedisCache } from '../../../libs/redis.client'; +import { makeProxyAgent } from '../../../utils/makeProxyAgent'; +import { useMultiFileAuthStateDb } from '../../../utils/use-multi-file-auth-state-db'; +import { useMultiFileAuthStateRedisDb } from '../../../utils/use-multi-file-auth-state-redis-db'; import { ArchiveChatDto, BlockUserDto, @@ -75,7 +75,7 @@ import { SendPresenceDto, UpdateMessageDto, WhatsAppNumberDto, -} from '../dto/chat.dto'; +} from '../../dto/chat.dto'; import { AcceptGroupInvite, CreateGroupDto, @@ -89,9 +89,9 @@ import { GroupToggleEphemeralDto, GroupUpdateParticipantDto, GroupUpdateSettingDto, -} from '../dto/group.dto'; -import { InstanceDto, SetPresenceDto } from '../dto/instance.dto'; -import { HandleLabelDto, LabelDto } from '../dto/label.dto'; +} from '../../dto/group.dto'; +import { InstanceDto, SetPresenceDto } from '../../dto/instance.dto'; +import { HandleLabelDto, LabelDto } from '../../dto/label.dto'; import { ContactMessage, MediaMessage, @@ -108,17 +108,17 @@ import { SendStickerDto, SendTextDto, StatusMessage, -} from '../dto/sendMessage.dto'; -import { chatwootImport } from '../integrations/chatwoot/utils/chatwoot-import-helper'; -import { SettingsRaw } from '../models'; -import { ChatRaw } from '../models/chat.model'; -import { ContactRaw } from '../models/contact.model'; -import { MessageRaw, MessageUpdateRaw } from '../models/message.model'; -import { RepositoryBroker } from '../repository/repository.manager'; -import { waMonitor } from '../server.module'; -import { Events, MessageSubtype, TypeMediaMessage, wa } from '../types/wa.types'; -import { CacheService } from './cache.service'; -import { WAStartupService } from './whatsapp.service'; +} from '../../dto/sendMessage.dto'; +import { chatwootImport } from '../../integrations/chatwoot/utils/chatwoot-import-helper'; +import { SettingsRaw } from '../../models'; +import { ChatRaw } from '../../models/chat.model'; +import { ContactRaw } from '../../models/contact.model'; +import { MessageRaw, MessageUpdateRaw } from '../../models/message.model'; +import { RepositoryBroker } from '../../repository/repository.manager'; +import { waMonitor } from '../../server.module'; +import { Events, MessageSubtype, TypeMediaMessage, wa } from '../../types/wa.types'; +import { CacheService } from './../cache.service'; +import { WAStartupService } from './../whatsapp.service'; // const retryCache = {}; diff --git a/src/api/services/whatsapp.business.service.ts b/src/api/services/whatsapp/whatsapp.business.service.ts similarity index 98% rename from src/api/services/whatsapp.business.service.ts rename to src/api/services/whatsapp/whatsapp.business.service.ts index 35b1e028..89cc2089 100644 --- a/src/api/services/whatsapp.business.service.ts +++ b/src/api/services/whatsapp/whatsapp.business.service.ts @@ -5,10 +5,10 @@ import FormData from 'form-data'; import fs from 'fs/promises'; import { getMIMEType } from 'node-mime-types'; -import { ConfigService, Database, WaBusiness } from '../../config/env.config'; -import { BadRequestException, InternalServerErrorException } from '../../exceptions'; -import { RedisCache } from '../../libs/redis.client'; -import { NumberBusiness } from '../dto/chat.dto'; +import { ConfigService, Database, WaBusiness } from '../../../config/env.config'; +import { BadRequestException, InternalServerErrorException } from '../../../exceptions'; +import { RedisCache } from '../../../libs/redis.client'; +import { NumberBusiness } from '../../dto/chat.dto'; import { ContactMessage, MediaMessage, @@ -22,12 +22,12 @@ import { SendReactionDto, SendTemplateDto, SendTextDto, -} from '../dto/sendMessage.dto'; -import { ContactRaw, MessageRaw, MessageUpdateRaw, SettingsRaw } from '../models'; -import { RepositoryBroker } from '../repository/repository.manager'; -import { Events, wa } from '../types/wa.types'; -import { CacheService } from './cache.service'; -import { WAStartupService } from './whatsapp.service'; +} from '../../dto/sendMessage.dto'; +import { ContactRaw, MessageRaw, MessageUpdateRaw, SettingsRaw } from '../../models'; +import { RepositoryBroker } from '../../repository/repository.manager'; +import { Events, wa } from '../../types/wa.types'; +import { CacheService } from './../cache.service'; +import { WAStartupService } from './../whatsapp.service'; export class BusinessStartupService extends WAStartupService { constructor( From 94f5c130bf5f8631ec4e1a79a14dcd42f99045e5 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 12 Apr 2024 17:22:11 -0300 Subject: [PATCH 19/42] fix: reorganization of files and folders --- .../controllers/chamaai.controller.ts | 4 +-- .../chamaai}/dto/chamaai.dto.ts | 0 .../chamaai}/models/chamaai.model.ts | 2 +- .../chamaai}/repository/chamaai.repository.ts | 8 ++--- .../chamaai/routes}/chamaai.router.ts | 12 +++---- .../chamaai}/services/chamaai.service.ts | 12 +++---- .../chamaai/validate/chamaai.schema.ts | 35 +++++++++++++++++++ .../chatwoot/routes/chatwoot.router.ts | 2 +- .../rabbitmq/routes/rabbitmq.router.ts | 2 +- src/api/integrations/sqs/routes/sqs.router.ts | 2 +- .../typebot/routes/typebot.router.ts | 2 +- .../websocket/routes/websocket.router.ts | 2 +- src/api/models/index.ts | 2 +- src/api/repository/repository.manager.ts | 2 +- src/api/{routers => routes}/chat.router.ts | 0 src/api/{routers => routes}/group.router.ts | 0 src/api/{routers => routes}/index.router.ts | 2 +- .../{routers => routes}/instance.router.ts | 0 src/api/{routers => routes}/label.router.ts | 0 src/api/{routers => routes}/proxy.router.ts | 0 .../{routers => routes}/sendMessage.router.ts | 0 .../{routers => routes}/settings.router.ts | 0 src/api/{routers => routes}/view.router.ts | 0 src/api/{routers => routes}/webhook.router.ts | 0 src/api/server.module.ts | 6 ++-- src/api/services/whatsapp.service.ts | 2 +- src/exceptions/400.exception.ts | 2 +- src/exceptions/401.exception.ts | 2 +- src/exceptions/403.exception.ts | 2 +- src/exceptions/404.exception.ts | 2 +- src/exceptions/500.exception.ts | 2 +- src/main.ts | 2 +- src/validate/validate.schema.ts | 15 +------- 33 files changed, 73 insertions(+), 51 deletions(-) rename src/api/{ => integrations/chamaai}/controllers/chamaai.controller.ts (88%) rename src/api/{ => integrations/chamaai}/dto/chamaai.dto.ts (100%) rename src/api/{ => integrations/chamaai}/models/chamaai.model.ts (91%) rename src/api/{ => integrations/chamaai}/repository/chamaai.repository.ts (87%) rename src/api/{routers => integrations/chamaai/routes}/chamaai.router.ts (79%) rename src/api/{ => integrations/chamaai}/services/chamaai.service.ts (94%) create mode 100644 src/api/integrations/chamaai/validate/chamaai.schema.ts rename src/api/{routers => routes}/chat.router.ts (100%) rename src/api/{routers => routes}/group.router.ts (100%) rename src/api/{routers => routes}/index.router.ts (97%) rename src/api/{routers => routes}/instance.router.ts (100%) rename src/api/{routers => routes}/label.router.ts (100%) rename src/api/{routers => routes}/proxy.router.ts (100%) rename src/api/{routers => routes}/sendMessage.router.ts (100%) rename src/api/{routers => routes}/settings.router.ts (100%) rename src/api/{routers => routes}/view.router.ts (100%) rename src/api/{routers => routes}/webhook.router.ts (100%) diff --git a/src/api/controllers/chamaai.controller.ts b/src/api/integrations/chamaai/controllers/chamaai.controller.ts similarity index 88% rename from src/api/controllers/chamaai.controller.ts rename to src/api/integrations/chamaai/controllers/chamaai.controller.ts index e9cafb50..91b33cd1 100644 --- a/src/api/controllers/chamaai.controller.ts +++ b/src/api/integrations/chamaai/controllers/chamaai.controller.ts @@ -1,6 +1,6 @@ -import { Logger } from '../../config/logger.config'; +import { Logger } from '../../../../config/logger.config'; +import { InstanceDto } from '../../../dto/instance.dto'; import { ChamaaiDto } from '../dto/chamaai.dto'; -import { InstanceDto } from '../dto/instance.dto'; import { ChamaaiService } from '../services/chamaai.service'; const logger = new Logger('ChamaaiController'); diff --git a/src/api/dto/chamaai.dto.ts b/src/api/integrations/chamaai/dto/chamaai.dto.ts similarity index 100% rename from src/api/dto/chamaai.dto.ts rename to src/api/integrations/chamaai/dto/chamaai.dto.ts diff --git a/src/api/models/chamaai.model.ts b/src/api/integrations/chamaai/models/chamaai.model.ts similarity index 91% rename from src/api/models/chamaai.model.ts rename to src/api/integrations/chamaai/models/chamaai.model.ts index d3d10aff..ef4f252b 100644 --- a/src/api/models/chamaai.model.ts +++ b/src/api/integrations/chamaai/models/chamaai.model.ts @@ -1,6 +1,6 @@ import { Schema } from 'mongoose'; -import { dbserver } from '../../libs/db.connect'; +import { dbserver } from '../../../../libs/db.connect'; export class ChamaaiRaw { _id?: string; diff --git a/src/api/repository/chamaai.repository.ts b/src/api/integrations/chamaai/repository/chamaai.repository.ts similarity index 87% rename from src/api/repository/chamaai.repository.ts rename to src/api/integrations/chamaai/repository/chamaai.repository.ts index a2009f41..17ff8dcd 100644 --- a/src/api/repository/chamaai.repository.ts +++ b/src/api/integrations/chamaai/repository/chamaai.repository.ts @@ -1,10 +1,10 @@ import { readFileSync } from 'fs'; import { join } from 'path'; -import { ConfigService } from '../../config/env.config'; -import { Logger } from '../../config/logger.config'; -import { IInsert, Repository } from '../abstract/abstract.repository'; -import { ChamaaiRaw, IChamaaiModel } from '../models'; +import { ConfigService } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; +import { IInsert, Repository } from '../../../abstract/abstract.repository'; +import { ChamaaiRaw, IChamaaiModel } from '../../../models'; export class ChamaaiRepository extends Repository { constructor(private readonly chamaaiModel: IChamaaiModel, private readonly configService: ConfigService) { diff --git a/src/api/routers/chamaai.router.ts b/src/api/integrations/chamaai/routes/chamaai.router.ts similarity index 79% rename from src/api/routers/chamaai.router.ts rename to src/api/integrations/chamaai/routes/chamaai.router.ts index 93644af3..3ade4b43 100644 --- a/src/api/routers/chamaai.router.ts +++ b/src/api/integrations/chamaai/routes/chamaai.router.ts @@ -1,12 +1,12 @@ import { RequestHandler, Router } from 'express'; -import { Logger } from '../../config/logger.config'; -import { chamaaiSchema, instanceNameSchema } from '../../validate/validate.schema'; -import { RouterBroker } from '../abstract/abstract.router'; +import { Logger } from '../../../../config/logger.config'; +import { chamaaiSchema, instanceNameSchema } from '../../../../validate/validate.schema'; +import { RouterBroker } from '../../../abstract/abstract.router'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { HttpStatus } from '../../../routes/index.router'; +import { chamaaiController } from '../../../server.module'; import { ChamaaiDto } from '../dto/chamaai.dto'; -import { InstanceDto } from '../dto/instance.dto'; -import { chamaaiController } from '../server.module'; -import { HttpStatus } from './index.router'; const logger = new Logger('ChamaaiRouter'); diff --git a/src/api/services/chamaai.service.ts b/src/api/integrations/chamaai/services/chamaai.service.ts similarity index 94% rename from src/api/services/chamaai.service.ts rename to src/api/integrations/chamaai/services/chamaai.service.ts index ad2a42ad..911732a8 100644 --- a/src/api/services/chamaai.service.ts +++ b/src/api/integrations/chamaai/services/chamaai.service.ts @@ -2,13 +2,13 @@ import axios from 'axios'; import { writeFileSync } from 'fs'; import path from 'path'; -import { ConfigService, HttpServer } from '../../config/env.config'; -import { Logger } from '../../config/logger.config'; +import { ConfigService, HttpServer } from '../../../../config/env.config'; +import { Logger } from '../../../../config/logger.config'; +import { InstanceDto } from '../../../dto/instance.dto'; +import { ChamaaiRaw } from '../../../models'; +import { WAMonitoringService } from '../../../services/monitor.service'; +import { Events } from '../../../types/wa.types'; import { ChamaaiDto } from '../dto/chamaai.dto'; -import { InstanceDto } from '../dto/instance.dto'; -import { ChamaaiRaw } from '../models'; -import { Events } from '../types/wa.types'; -import { WAMonitoringService } from './monitor.service'; export class ChamaaiService { constructor(private readonly waMonitor: WAMonitoringService, private readonly configService: ConfigService) {} diff --git a/src/api/integrations/chamaai/validate/chamaai.schema.ts b/src/api/integrations/chamaai/validate/chamaai.schema.ts new file mode 100644 index 00000000..0b80104f --- /dev/null +++ b/src/api/integrations/chamaai/validate/chamaai.schema.ts @@ -0,0 +1,35 @@ +import { JSONSchema7 } from 'json-schema'; +import { v4 } from 'uuid'; + +const isNotEmpty = (...propertyNames: string[]): JSONSchema7 => { + const properties = {}; + propertyNames.forEach( + (property) => + (properties[property] = { + minLength: 1, + description: `The "${property}" cannot be empty`, + }), + ); + return { + if: { + propertyNames: { + enum: [...propertyNames], + }, + }, + then: { properties }, + }; +}; + +export const chamaaiSchema: JSONSchema7 = { + $id: v4(), + type: 'object', + properties: { + enabled: { type: 'boolean', enum: [true, false] }, + url: { type: 'string' }, + token: { type: 'string' }, + waNumber: { type: 'string' }, + answerByAudio: { type: 'boolean', enum: [true, false] }, + }, + required: ['enabled', 'url', 'token', 'waNumber', 'answerByAudio'], + ...isNotEmpty('enabled', 'url', 'token', 'waNumber', 'answerByAudio'), +}; diff --git a/src/api/integrations/chatwoot/routes/chatwoot.router.ts b/src/api/integrations/chatwoot/routes/chatwoot.router.ts index 2df2f18f..cc227163 100644 --- a/src/api/integrations/chatwoot/routes/chatwoot.router.ts +++ b/src/api/integrations/chatwoot/routes/chatwoot.router.ts @@ -4,7 +4,7 @@ import { Logger } from '../../../../config/logger.config'; import { chatwootSchema, instanceNameSchema } from '../../../../validate/validate.schema'; import { RouterBroker } from '../../../abstract/abstract.router'; import { InstanceDto } from '../../../dto/instance.dto'; -import { HttpStatus } from '../../../routers/index.router'; +import { HttpStatus } from '../../../routes/index.router'; import { chatwootController } from '../../../server.module'; import { ChatwootDto } from '../dto/chatwoot.dto'; diff --git a/src/api/integrations/rabbitmq/routes/rabbitmq.router.ts b/src/api/integrations/rabbitmq/routes/rabbitmq.router.ts index c7d567e1..a477a5ba 100644 --- a/src/api/integrations/rabbitmq/routes/rabbitmq.router.ts +++ b/src/api/integrations/rabbitmq/routes/rabbitmq.router.ts @@ -4,7 +4,7 @@ import { Logger } from '../../../../config/logger.config'; import { instanceNameSchema, rabbitmqSchema } from '../../../../validate/validate.schema'; import { RouterBroker } from '../../../abstract/abstract.router'; import { InstanceDto } from '../../../dto/instance.dto'; -import { HttpStatus } from '../../../routers/index.router'; +import { HttpStatus } from '../../../routes/index.router'; import { rabbitmqController } from '../../../server.module'; import { RabbitmqDto } from '../dto/rabbitmq.dto'; diff --git a/src/api/integrations/sqs/routes/sqs.router.ts b/src/api/integrations/sqs/routes/sqs.router.ts index 8b03bb3a..80d14838 100644 --- a/src/api/integrations/sqs/routes/sqs.router.ts +++ b/src/api/integrations/sqs/routes/sqs.router.ts @@ -4,7 +4,7 @@ import { Logger } from '../../../../config/logger.config'; import { instanceNameSchema, sqsSchema } from '../../../../validate/validate.schema'; import { RouterBroker } from '../../../abstract/abstract.router'; import { InstanceDto } from '../../../dto/instance.dto'; -import { HttpStatus } from '../../../routers/index.router'; +import { HttpStatus } from '../../../routes/index.router'; import { sqsController } from '../../../server.module'; import { SqsDto } from '../dto/sqs.dto'; diff --git a/src/api/integrations/typebot/routes/typebot.router.ts b/src/api/integrations/typebot/routes/typebot.router.ts index b9694c54..2eed2b39 100644 --- a/src/api/integrations/typebot/routes/typebot.router.ts +++ b/src/api/integrations/typebot/routes/typebot.router.ts @@ -9,7 +9,7 @@ import { } from '../../../../validate/validate.schema'; import { RouterBroker } from '../../../abstract/abstract.router'; import { InstanceDto } from '../../../dto/instance.dto'; -import { HttpStatus } from '../../../routers/index.router'; +import { HttpStatus } from '../../../routes/index.router'; import { typebotController } from '../../../server.module'; import { TypebotDto } from '../dto/typebot.dto'; diff --git a/src/api/integrations/websocket/routes/websocket.router.ts b/src/api/integrations/websocket/routes/websocket.router.ts index 271c1ce2..0c39d53c 100644 --- a/src/api/integrations/websocket/routes/websocket.router.ts +++ b/src/api/integrations/websocket/routes/websocket.router.ts @@ -4,7 +4,7 @@ import { Logger } from '../../../../config/logger.config'; import { instanceNameSchema, websocketSchema } from '../../../../validate/validate.schema'; import { RouterBroker } from '../../../abstract/abstract.router'; import { InstanceDto } from '../../../dto/instance.dto'; -import { HttpStatus } from '../../../routers/index.router'; +import { HttpStatus } from '../../../routes/index.router'; import { websocketController } from '../../../server.module'; import { WebsocketDto } from '../dto/websocket.dto'; diff --git a/src/api/models/index.ts b/src/api/models/index.ts index 6cec09a9..42399bc5 100644 --- a/src/api/models/index.ts +++ b/src/api/models/index.ts @@ -1,10 +1,10 @@ +export * from '../integrations/chamaai/models/chamaai.model'; export * from '../integrations/chatwoot/models/chatwoot.model'; export * from '../integrations/rabbitmq/models/rabbitmq.model'; export * from '../integrations/sqs/models/sqs.model'; export * from '../integrations/typebot/models/typebot.model'; export * from '../integrations/websocket/models/websocket.model'; export * from './auth.model'; -export * from './chamaai.model'; export * from './chat.model'; export * from './contact.model'; export * from './integration.model'; diff --git a/src/api/repository/repository.manager.ts b/src/api/repository/repository.manager.ts index 2ea54aa1..5fd9e55e 100644 --- a/src/api/repository/repository.manager.ts +++ b/src/api/repository/repository.manager.ts @@ -4,13 +4,13 @@ import { join } from 'path'; import { Auth, ConfigService, Database } from '../../config/env.config'; import { Logger } from '../../config/logger.config'; +import { ChamaaiRepository } from '../integrations/chamaai/repository/chamaai.repository'; import { ChatwootRepository } from '../integrations/chatwoot/repository/chatwoot.repository'; import { RabbitmqRepository } from '../integrations/rabbitmq/repository/rabbitmq.repository'; import { SqsRepository } from '../integrations/sqs/repository/sqs.repository'; import { TypebotRepository } from '../integrations/typebot/repository/typebot.repository'; import { WebsocketRepository } from '../integrations/websocket/repository/websocket.repository'; import { AuthRepository } from './auth.repository'; -import { ChamaaiRepository } from './chamaai.repository'; import { ChatRepository } from './chat.repository'; import { ContactRepository } from './contact.repository'; import { IntegrationRepository } from './integration.repository'; diff --git a/src/api/routers/chat.router.ts b/src/api/routes/chat.router.ts similarity index 100% rename from src/api/routers/chat.router.ts rename to src/api/routes/chat.router.ts diff --git a/src/api/routers/group.router.ts b/src/api/routes/group.router.ts similarity index 100% rename from src/api/routers/group.router.ts rename to src/api/routes/group.router.ts diff --git a/src/api/routers/index.router.ts b/src/api/routes/index.router.ts similarity index 97% rename from src/api/routers/index.router.ts rename to src/api/routes/index.router.ts index 8d17ab6f..3b26671f 100644 --- a/src/api/routers/index.router.ts +++ b/src/api/routes/index.router.ts @@ -4,12 +4,12 @@ import fs from 'fs'; import { Auth, configService } from '../../config/env.config'; import { authGuard } from '../guards/auth.guard'; import { instanceExistsGuard, instanceLoggedGuard } from '../guards/instance.guard'; +import { ChamaaiRouter } from '../integrations/chamaai/routes/chamaai.router'; import { ChatwootRouter } from '../integrations/chatwoot/routes/chatwoot.router'; import { RabbitmqRouter } from '../integrations/rabbitmq/routes/rabbitmq.router'; import { SqsRouter } from '../integrations/sqs/routes/sqs.router'; import { TypebotRouter } from '../integrations/typebot/routes/typebot.router'; import { WebsocketRouter } from '../integrations/websocket/routes/websocket.router'; -import { ChamaaiRouter } from './chamaai.router'; import { ChatRouter } from './chat.router'; import { GroupRouter } from './group.router'; import { InstanceRouter } from './instance.router'; diff --git a/src/api/routers/instance.router.ts b/src/api/routes/instance.router.ts similarity index 100% rename from src/api/routers/instance.router.ts rename to src/api/routes/instance.router.ts diff --git a/src/api/routers/label.router.ts b/src/api/routes/label.router.ts similarity index 100% rename from src/api/routers/label.router.ts rename to src/api/routes/label.router.ts diff --git a/src/api/routers/proxy.router.ts b/src/api/routes/proxy.router.ts similarity index 100% rename from src/api/routers/proxy.router.ts rename to src/api/routes/proxy.router.ts diff --git a/src/api/routers/sendMessage.router.ts b/src/api/routes/sendMessage.router.ts similarity index 100% rename from src/api/routers/sendMessage.router.ts rename to src/api/routes/sendMessage.router.ts diff --git a/src/api/routers/settings.router.ts b/src/api/routes/settings.router.ts similarity index 100% rename from src/api/routers/settings.router.ts rename to src/api/routes/settings.router.ts diff --git a/src/api/routers/view.router.ts b/src/api/routes/view.router.ts similarity index 100% rename from src/api/routers/view.router.ts rename to src/api/routes/view.router.ts diff --git a/src/api/routers/webhook.router.ts b/src/api/routes/webhook.router.ts similarity index 100% rename from src/api/routers/webhook.router.ts rename to src/api/routes/webhook.router.ts diff --git a/src/api/server.module.ts b/src/api/server.module.ts index 67512cac..6c72aaf5 100644 --- a/src/api/server.module.ts +++ b/src/api/server.module.ts @@ -3,7 +3,6 @@ import { eventEmitter } from '../config/event.config'; import { Logger } from '../config/logger.config'; import { dbserver } from '../libs/db.connect'; import { RedisCache } from '../libs/redis.client'; -import { ChamaaiController } from './controllers/chamaai.controller'; import { ChatController } from './controllers/chat.controller'; import { GroupController } from './controllers/group.controller'; import { InstanceController } from './controllers/instance.controller'; @@ -12,6 +11,9 @@ import { ProxyController } from './controllers/proxy.controller'; import { SendMessageController } from './controllers/sendMessage.controller'; import { SettingsController } from './controllers/settings.controller'; import { WebhookController } from './controllers/webhook.controller'; +import { ChamaaiController } from './integrations/chamaai/controllers/chamaai.controller'; +import { ChamaaiRepository } from './integrations/chamaai/repository/chamaai.repository'; +import { ChamaaiService } from './integrations/chamaai/services/chamaai.service'; import { CacheEngine } from './integrations/chatwoot/cache/cacheengine'; import { ChatwootController } from './integrations/chatwoot/controllers/chatwoot.controller'; import { ChatwootRepository } from './integrations/chatwoot/repository/chatwoot.repository'; @@ -47,7 +49,6 @@ import { } from './models'; import { LabelModel } from './models/label.model'; import { AuthRepository } from './repository/auth.repository'; -import { ChamaaiRepository } from './repository/chamaai.repository'; import { ChatRepository } from './repository/chat.repository'; import { ContactRepository } from './repository/contact.repository'; import { IntegrationRepository } from './repository/integration.repository'; @@ -60,7 +61,6 @@ import { SettingsRepository } from './repository/settings.repository'; import { WebhookRepository } from './repository/webhook.repository'; import { AuthService } from './services/auth.service'; import { CacheService } from './services/cache.service'; -import { ChamaaiService } from './services/chamaai.service'; import { IntegrationService } from './services/integration.service'; import { WAMonitoringService } from './services/monitor.service'; import { ProxyService } from './services/proxy.service'; diff --git a/src/api/services/whatsapp.service.ts b/src/api/services/whatsapp.service.ts index b9cece5a..5c6df8d3 100644 --- a/src/api/services/whatsapp.service.ts +++ b/src/api/services/whatsapp.service.ts @@ -20,6 +20,7 @@ import { import { Logger } from '../../config/logger.config'; import { ROOT_DIR } from '../../config/path.config'; import { NotFoundException } from '../../exceptions'; +import { ChamaaiService } from '../integrations/chamaai/services/chamaai.service'; import { ChatwootRaw } from '../integrations/chatwoot/models/chatwoot.model'; import { ChatwootService } from '../integrations/chatwoot/services/chatwoot.service'; import { getAMQP, removeQueues } from '../integrations/rabbitmq/libs/amqp.server'; @@ -36,7 +37,6 @@ import { RepositoryBroker } from '../repository/repository.manager'; import { waMonitor } from '../server.module'; import { Events, wa } from '../types/wa.types'; import { CacheService } from './cache.service'; -import { ChamaaiService } from './chamaai.service'; export class WAStartupService { constructor( diff --git a/src/exceptions/400.exception.ts b/src/exceptions/400.exception.ts index 6697aeb2..2ea3a7a4 100644 --- a/src/exceptions/400.exception.ts +++ b/src/exceptions/400.exception.ts @@ -1,4 +1,4 @@ -import { HttpStatus } from '../api/routers/index.router'; +import { HttpStatus } from '../api/routes/index.router'; export class BadRequestException { constructor(...objectError: any[]) { diff --git a/src/exceptions/401.exception.ts b/src/exceptions/401.exception.ts index 8fd72da2..f5383e0e 100644 --- a/src/exceptions/401.exception.ts +++ b/src/exceptions/401.exception.ts @@ -1,4 +1,4 @@ -import { HttpStatus } from '../api/routers/index.router'; +import { HttpStatus } from '../api/routes/index.router'; export class UnauthorizedException { constructor(...objectError: any[]) { diff --git a/src/exceptions/403.exception.ts b/src/exceptions/403.exception.ts index a7c118bd..53d8f05c 100644 --- a/src/exceptions/403.exception.ts +++ b/src/exceptions/403.exception.ts @@ -1,4 +1,4 @@ -import { HttpStatus } from '../api/routers/index.router'; +import { HttpStatus } from '../api/routes/index.router'; export class ForbiddenException { constructor(...objectError: any[]) { diff --git a/src/exceptions/404.exception.ts b/src/exceptions/404.exception.ts index 6c06f095..f2fd5c28 100644 --- a/src/exceptions/404.exception.ts +++ b/src/exceptions/404.exception.ts @@ -1,4 +1,4 @@ -import { HttpStatus } from '../api/routers/index.router'; +import { HttpStatus } from '../api/routes/index.router'; export class NotFoundException { constructor(...objectError: any[]) { diff --git a/src/exceptions/500.exception.ts b/src/exceptions/500.exception.ts index 445f240b..c5111f6d 100644 --- a/src/exceptions/500.exception.ts +++ b/src/exceptions/500.exception.ts @@ -1,4 +1,4 @@ -import { HttpStatus } from '../api/routers/index.router'; +import { HttpStatus } from '../api/routes/index.router'; export class InternalServerErrorException { constructor(...objectError: any[]) { diff --git a/src/main.ts b/src/main.ts index 49a3d153..942c725f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -9,7 +9,7 @@ import { join } from 'path'; import { initAMQP } from './api/integrations/rabbitmq/libs/amqp.server'; import { initSQS } from './api/integrations/sqs/libs/sqs.server'; import { initIO } from './api/integrations/websocket/libs/socket.server'; -import { HttpStatus, router } from './api/routers/index.router'; +import { HttpStatus, router } from './api/routes/index.router'; import { waMonitor } from './api/server.module'; import { Auth, configService, Cors, HttpServer, Rabbitmq, Sqs, Webhook } from './config/env.config'; import { onUnexpectedError } from './config/error.config'; diff --git a/src/validate/validate.schema.ts b/src/validate/validate.schema.ts index 6bafb9b9..9013ca39 100644 --- a/src/validate/validate.schema.ts +++ b/src/validate/validate.schema.ts @@ -2,6 +2,7 @@ import { JSONSchema7, JSONSchema7Definition } from 'json-schema'; import { v4 } from 'uuid'; // Integrations Schema +export * from '../api/integrations/chamaai/validate/chamaai.schema'; export * from '../api/integrations/chatwoot/validate/chatwoot.schema'; export * from '../api/integrations/rabbitmq/validate/rabbitmq.schema'; export * from '../api/integrations/sqs/validate/sqs.schema'; @@ -1046,20 +1047,6 @@ export const proxySchema: JSONSchema7 = { ...isNotEmpty('enabled', 'proxy'), }; -export const chamaaiSchema: JSONSchema7 = { - $id: v4(), - type: 'object', - properties: { - enabled: { type: 'boolean', enum: [true, false] }, - url: { type: 'string' }, - token: { type: 'string' }, - waNumber: { type: 'string' }, - answerByAudio: { type: 'boolean', enum: [true, false] }, - }, - required: ['enabled', 'url', 'token', 'waNumber', 'answerByAudio'], - ...isNotEmpty('enabled', 'url', 'token', 'waNumber', 'answerByAudio'), -}; - export const handleLabelSchema: JSONSchema7 = { $id: v4(), type: 'object', From 3e88c9f0c749c361d76f4c3ca4b6f45b5185923e Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 12 Apr 2024 17:23:28 -0300 Subject: [PATCH 20/42] fix: reorganization of files and folders --- Dockerfile | 2 +- src/docs/swagger.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 599f8cca..b4f20c80 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM node:20.7.0-alpine AS builder -LABEL version="1.7.1" description="Api to control whatsapp features through http requests." +LABEL version="1.7.2" description="Api to control whatsapp features through http requests." LABEL maintainer="Davidson Gomes" git="https://github.com/DavidsonGomes" LABEL contact="contato@agenciadgcode.com" diff --git a/src/docs/swagger.yaml b/src/docs/swagger.yaml index 0a3be9d1..1b307f5f 100644 --- a/src/docs/swagger.yaml +++ b/src/docs/swagger.yaml @@ -25,7 +25,7 @@ info: [![Run in Postman](https://run.pstmn.io/button.svg)](https://god.gw.postman.com/run-collection/26869335-5546d063-156b-4529-915f-909dd628c090?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D26869335-5546d063-156b-4529-915f-909dd628c090%26entityType%3Dcollection%26workspaceId%3D339a4ee7-378b-45c9-b5b8-fd2c0a9c2442) - version: 1.7.1 + version: 1.7.2 contact: name: DavidsonGomes email: contato@agenciadgcode.com From 901b121695a2e3eab68adbf8a5bcd138f057f4d3 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 12 Apr 2024 17:28:02 -0300 Subject: [PATCH 21/42] fix: reorganization of files and folders --- src/api/server.module.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/api/server.module.ts b/src/api/server.module.ts index 6c72aaf5..5c78e1c3 100644 --- a/src/api/server.module.ts +++ b/src/api/server.module.ts @@ -108,7 +108,6 @@ export const repository = new RepositoryBroker( ); export const cache = new RedisCache(); - const chatwootCache = new CacheService(new CacheEngine(configService, ChatwootService.name).getEngine()); export const waMonitor = new WAMonitoringService(eventEmitter, configService, repository, cache, chatwootCache); @@ -116,41 +115,32 @@ export const waMonitor = new WAMonitoringService(eventEmitter, configService, re const authService = new AuthService(configService, waMonitor, repository); const typebotService = new TypebotService(waMonitor, configService, eventEmitter); - export const typebotController = new TypebotController(typebotService); const webhookService = new WebhookService(waMonitor); - export const webhookController = new WebhookController(webhookService, waMonitor); const websocketService = new WebsocketService(waMonitor); - export const websocketController = new WebsocketController(websocketService); const proxyService = new ProxyService(waMonitor); - export const proxyController = new ProxyController(proxyService, waMonitor); const chamaaiService = new ChamaaiService(waMonitor, configService); - export const chamaaiController = new ChamaaiController(chamaaiService); const rabbitmqService = new RabbitmqService(waMonitor); - export const rabbitmqController = new RabbitmqController(rabbitmqService); const sqsService = new SqsService(waMonitor); - export const sqsController = new SqsController(sqsService); const integrationService = new IntegrationService(waMonitor); const chatwootService = new ChatwootService(waMonitor, configService, repository, chatwootCache); - export const chatwootController = new ChatwootController(chatwootService, configService, repository); const settingsService = new SettingsService(waMonitor); - export const settingsController = new SettingsController(settingsService); export const instanceController = new InstanceController( From 96ae97664cc750424001a99ba65e3acb8eab57c6 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Fri, 12 Apr 2024 17:31:58 -0300 Subject: [PATCH 22/42] v 1.7.2 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52d7080e..c4c4363a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 1.7.2 (develop) +# 1.7.2 (2024-04-12 17:31) ### Feature From d6e19b92731a2de1179050619fec55bdccd02925 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Tue, 16 Apr 2024 19:08:44 -0300 Subject: [PATCH 23/42] adjusts in v1.7.3 --- CHANGELOG.md | 7 + Dockerfile | 2 +- package.json | 2 +- .../whatsapp/whatsapp.baileys.service.ts | 138 +++++++++++++----- src/docs/swagger.yaml | 2 +- 5 files changed, 110 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4c4363a..dddbe8c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 1.7.3 (develop) + +### Fixed +* Fix audio encoding +* Recovering messages lost +* Adjusts in proxy + # 1.7.2 (2024-04-12 17:31) ### Feature diff --git a/Dockerfile b/Dockerfile index b4f20c80..b913a37e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM node:20.7.0-alpine AS builder -LABEL version="1.7.2" description="Api to control whatsapp features through http requests." +LABEL version="1.7.3" description="Api to control whatsapp features through http requests." LABEL maintainer="Davidson Gomes" git="https://github.com/DavidsonGomes" LABEL contact="contato@agenciadgcode.com" diff --git a/package.json b/package.json index 8b31f902..bf5832ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "evolution-api", - "version": "1.7.2", + "version": "1.7.3", "description": "Rest api for communication with WhatsApp", "main": "./dist/src/main.js", "scripts": { diff --git a/src/api/services/whatsapp/whatsapp.baileys.service.ts b/src/api/services/whatsapp/whatsapp.baileys.service.ts index 6285250b..eba80acb 100644 --- a/src/api/services/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/services/whatsapp/whatsapp.baileys.service.ts @@ -39,9 +39,10 @@ import makeWASocket, { import { Label } from '@whiskeysockets/baileys/lib/Types/Label'; import { LabelAssociation } from '@whiskeysockets/baileys/lib/Types/LabelAssociation'; import axios from 'axios'; +import { exec } from 'child_process'; import { arrayUnique, isBase64, isURL } from 'class-validator'; import EventEmitter2 from 'eventemitter2'; -import ffmpeg from 'fluent-ffmpeg'; +// import ffmpeg from 'fluent-ffmpeg'; import fs, { existsSync, readFileSync } from 'fs'; import { parsePhoneNumber } from 'libphonenumber-js'; import Long from 'long'; @@ -485,11 +486,11 @@ export class BaileysStartupService extends WAStartupService { let options; if (this.localProxy.enabled) { - this.logger.info('Proxy enabled: ' + this.localProxy.proxy.host); + this.logger.info('Proxy enabled: ' + this.localProxy.proxy?.host); if (this.localProxy?.proxy?.host?.includes('proxyscrape')) { try { - const response = await axios.get(this.localProxy.proxy.host); + const response = await axios.get(this.localProxy.proxy?.host); const text = response.data; const proxyUrls = text.split('\r\n'); const rand = Math.floor(Math.random() * Math.floor(proxyUrls.length)); @@ -655,11 +656,11 @@ export class BaileysStartupService extends WAStartupService { let options; if (this.localProxy.enabled) { - this.logger.info('Proxy enabled: ' + this.localProxy.proxy.host); + this.logger.info('Proxy enabled: ' + this.localProxy.proxy?.host); if (this.localProxy?.proxy?.host?.includes('proxyscrape')) { try { - const response = await axios.get(this.localProxy.proxy.host); + const response = await axios.get(this.localProxy.proxy?.host); const text = response.data; const proxyUrls = text.split('\r\n'); const rand = Math.floor(Math.random() * Math.floor(proxyUrls.length)); @@ -1043,6 +1044,12 @@ export class BaileysStartupService extends WAStartupService { } } + if (received.messageStubParameters && received.messageStubParameters[0] === 'Message absent from node') { + this.logger.info('Recovering message lost'); + await this.client.sendMessageAck(JSON.parse(received.messageStubParameters[1], BufferJSON.reviver)); + continue; + } + if ( (type !== 'notify' && type !== 'append') || received.message?.protocolMessage || @@ -2093,7 +2100,7 @@ export class BaileysStartupService extends WAStartupService { content: { audio: Buffer.from(audio, 'base64'), ptt: true, - mimetype: 'audio/mp4', + mimetype: 'audio/ogg; codecs=opus', }, option: { statusJidList: status.statusJidList, @@ -2297,6 +2304,82 @@ export class BaileysStartupService extends WAStartupService { return await this.sendMessageWithTyping(data.number, { ...generate.message }, data?.options, isChatwoot); } + // public async processAudio(audio: string, number: string) { + // this.logger.verbose('Processing audio'); + // let tempAudioPath: string; + // let outputAudio: string; + + // number = number.replace(/\D/g, ''); + // const hash = `${number}-${new Date().getTime()}`; + // this.logger.verbose('Hash to audio name: ' + hash); + + // if (isURL(audio)) { + // this.logger.verbose('Audio is url'); + + // outputAudio = `${join(this.storePath, 'temp', `${hash}.ogg`)}`; + // tempAudioPath = `${join(this.storePath, 'temp', `temp-${hash}.mp3`)}`; + + // this.logger.verbose('Output audio path: ' + outputAudio); + // this.logger.verbose('Temp audio path: ' + tempAudioPath); + + // const timestamp = new Date().getTime(); + // const url = `${audio}?timestamp=${timestamp}`; + + // this.logger.verbose('Including timestamp in url: ' + url); + + // let config: any = { + // responseType: 'arraybuffer', + // }; + + // if (this.localProxy.enabled) { + // config = { + // ...config, + // httpsAgent: makeProxyAgent(this.localProxy.proxy), + // }; + // } + + // const response = await axios.get(url, config); + // this.logger.verbose('Getting audio from url'); + + // fs.writeFileSync(tempAudioPath, response.data); + // } else { + // this.logger.verbose('Audio is base64'); + + // outputAudio = `${join(this.storePath, 'temp', `${hash}.ogg`)}`; + // tempAudioPath = `${join(this.storePath, 'temp', `temp-${hash}.mp3`)}`; + + // this.logger.verbose('Output audio path: ' + outputAudio); + // this.logger.verbose('Temp audio path: ' + tempAudioPath); + + // const audioBuffer = Buffer.from(audio, 'base64'); + // fs.writeFileSync(tempAudioPath, audioBuffer); + // this.logger.verbose('Temp audio created'); + // } + + // this.logger.verbose('Converting audio to mp4'); + // return new Promise((resolve, reject) => { + // // This fix was suggested by @PurpShell + // ffmpeg.setFfmpegPath(ffmpegPath.path); + + // ffmpeg() + // .input(tempAudioPath) + // .outputFormat('ogg') + // .noVideo() + // .audioCodec('libopus') + // .save(outputAudio) + // .on('error', function (error) { + // console.log('error', error); + // fs.unlinkSync(tempAudioPath); + // if (error) reject(error); + // }) + // .on('end', async function () { + // fs.unlinkSync(tempAudioPath); + // resolve(outputAudio); + // }) + // .run(); + // }); + // } + public async processAudio(audio: string, number: string) { this.logger.verbose('Processing audio'); let tempAudioPath: string; @@ -2309,7 +2392,7 @@ export class BaileysStartupService extends WAStartupService { if (isURL(audio)) { this.logger.verbose('Audio is url'); - outputAudio = `${join(this.storePath, 'temp', `${hash}.ogg`)}`; + outputAudio = `${join(this.storePath, 'temp', `${hash}.mp4`)}`; tempAudioPath = `${join(this.storePath, 'temp', `temp-${hash}.mp3`)}`; this.logger.verbose('Output audio path: ' + outputAudio); @@ -2320,25 +2403,14 @@ export class BaileysStartupService extends WAStartupService { this.logger.verbose('Including timestamp in url: ' + url); - let config: any = { - responseType: 'arraybuffer', - }; - - if (this.localProxy.enabled) { - config = { - ...config, - httpsAgent: makeProxyAgent(this.localProxy.proxy), - }; - } - - const response = await axios.get(url, config); + const response = await axios.get(url, { responseType: 'arraybuffer' }); this.logger.verbose('Getting audio from url'); fs.writeFileSync(tempAudioPath, response.data); } else { this.logger.verbose('Audio is base64'); - outputAudio = `${join(this.storePath, 'temp', `${hash}.ogg`)}`; + outputAudio = `${join(this.storePath, 'temp', `${hash}.mp4`)}`; tempAudioPath = `${join(this.storePath, 'temp', `temp-${hash}.mp3`)}`; this.logger.verbose('Output audio path: ' + outputAudio); @@ -2351,25 +2423,15 @@ export class BaileysStartupService extends WAStartupService { this.logger.verbose('Converting audio to mp4'); return new Promise((resolve, reject) => { - // This fix was suggested by @PurpShell - ffmpeg.setFfmpegPath(ffmpegPath.path); + exec(`${ffmpegPath.path} -i ${tempAudioPath} -vn -ab 128k -ar 44100 -f ipod ${outputAudio} -y`, (error) => { + fs.unlinkSync(tempAudioPath); + this.logger.verbose('Temp audio deleted'); - ffmpeg() - .input(tempAudioPath) - .outputFormat('ogg') - .noVideo() - .audioCodec('libopus') - .save(outputAudio) - .on('error', function (error) { - console.log('error', error); - fs.unlinkSync(tempAudioPath); - if (error) reject(error); - }) - .on('end', async function () { - fs.unlinkSync(tempAudioPath); - resolve(outputAudio); - }) - .run(); + if (error) reject(error); + + this.logger.verbose('Audio converted to mp4'); + resolve(outputAudio); + }); }); } diff --git a/src/docs/swagger.yaml b/src/docs/swagger.yaml index 1b307f5f..3a7a2d15 100644 --- a/src/docs/swagger.yaml +++ b/src/docs/swagger.yaml @@ -25,7 +25,7 @@ info: [![Run in Postman](https://run.pstmn.io/button.svg)](https://god.gw.postman.com/run-collection/26869335-5546d063-156b-4529-915f-909dd628c090?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D26869335-5546d063-156b-4529-915f-909dd628c090%26entityType%3Dcollection%26workspaceId%3D339a4ee7-378b-45c9-b5b8-fd2c0a9c2442) - version: 1.7.2 + version: 1.7.3 contact: name: DavidsonGomes email: contato@agenciadgcode.com From 1379228196072852c3b9f2b8e0e43e65ec5a3501 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Tue, 16 Apr 2024 19:12:03 -0300 Subject: [PATCH 24/42] fix: Revert pull request #523 --- CHANGELOG.md | 1 + src/api/integrations/typebot/services/typebot.service.ts | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dddbe8c5..7217b614 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Fix audio encoding * Recovering messages lost * Adjusts in proxy +* Revert pull request #523 # 1.7.2 (2024-04-12 17:31) diff --git a/src/api/integrations/typebot/services/typebot.service.ts b/src/api/integrations/typebot/services/typebot.service.ts index 6c322552..eae67117 100644 --- a/src/api/integrations/typebot/services/typebot.service.ts +++ b/src/api/integrations/typebot/services/typebot.service.ts @@ -57,7 +57,7 @@ export class TypebotService { if (session) { if (status === 'closed') { - const found_session: Session[] = findData.sessions.splice(findData.sessions.indexOf(session), 1); + findData.sessions.splice(findData.sessions.indexOf(session), 1); const typebotData = { enabled: findData.enabled, @@ -68,7 +68,7 @@ export class TypebotService { delay_message: findData.delay_message, unknown_message: findData.unknown_message, listening_from_me: findData.listening_from_me, - sessions: found_session, + sessions: findData.sessions, }; this.create(instance, typebotData); @@ -106,7 +106,7 @@ export class TypebotService { delay_message: findData.delay_message, unknown_message: findData.unknown_message, listening_from_me: findData.listening_from_me, - sessions: findData.sessions.splice(findData.sessions.indexOf(session), 1), + sessions: findData.sessions, }; this.create(instance, typebotData); From b6c56551bc616ffc7c367ef4d0939151d7ff8e32 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Tue, 16 Apr 2024 19:13:25 -0300 Subject: [PATCH 25/42] fix: Revert pull request #523 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7217b614..b1e575e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # 1.7.3 (develop) ### Fixed -* Fix audio encoding +* Revert fix audio encoding * Recovering messages lost * Adjusts in proxy * Revert pull request #523 From 9c9a542bbe686ac6f453e7ccf92467e2eac8f3e7 Mon Sep 17 00:00:00 2001 From: jaison-x Date: Wed, 17 Apr 2024 10:50:25 -0300 Subject: [PATCH 26/42] fix(chatwoot): error: invalid operator. The allowed operators for identifier are [equal_to,not_equal_to] In chatwoot version 3.8 we can't use the filter operator 'contains' for the field 'identifier' --- src/api/integrations/chatwoot/services/chatwoot.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/integrations/chatwoot/services/chatwoot.service.ts b/src/api/integrations/chatwoot/services/chatwoot.service.ts index 35fbb7af..e484ec66 100644 --- a/src/api/integrations/chatwoot/services/chatwoot.service.ts +++ b/src/api/integrations/chatwoot/services/chatwoot.service.ts @@ -461,7 +461,7 @@ export class ChatwootService { const queryOperator = fieldsToSearch.length - 1 === index1 && numbers.length - 1 === index2 ? null : 'OR'; filterPayload.push({ attribute_key: field, - filter_operator: field == 'phone_number' ? 'equal_to' : 'contains', + filter_operator: ['phone_number', 'identifier'].includes(field) ? 'equal_to' : 'contains', values: [number.replace('+', '')], query_operator: queryOperator, }); From a4338d847216dfd1086c427e6355d586499e8cd8 Mon Sep 17 00:00:00 2001 From: jaison-x Date: Wed, 17 Apr 2024 11:03:55 -0300 Subject: [PATCH 27/42] fix: this.localProxy.proxy can be undefined --- src/api/services/whatsapp.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/services/whatsapp.service.ts b/src/api/services/whatsapp.service.ts index 5c6df8d3..3599c15b 100644 --- a/src/api/services/whatsapp.service.ts +++ b/src/api/services/whatsapp.service.ts @@ -583,7 +583,7 @@ export class WAStartupService { this.logger.verbose(`Proxy enabled: ${this.localProxy.enabled}`); this.localProxy.proxy = data?.proxy; - this.logger.verbose(`Proxy proxy: ${this.localProxy.proxy.host}`); + this.logger.verbose(`Proxy proxy: ${this.localProxy.proxy?.host}`); this.logger.verbose('Proxy loaded'); } From c45538684d39d5bafb3327ae74d3d300ee04836d Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Wed, 17 Apr 2024 12:43:49 -0300 Subject: [PATCH 28/42] fix: fix audio encoding --- src/api/services/whatsapp/whatsapp.baileys.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/services/whatsapp/whatsapp.baileys.service.ts b/src/api/services/whatsapp/whatsapp.baileys.service.ts index eba80acb..9c87fb8e 100644 --- a/src/api/services/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/services/whatsapp/whatsapp.baileys.service.ts @@ -2100,7 +2100,7 @@ export class BaileysStartupService extends WAStartupService { content: { audio: Buffer.from(audio, 'base64'), ptt: true, - mimetype: 'audio/ogg; codecs=opus', + mimetype: 'audio/mp4', }, option: { statusJidList: status.statusJidList, @@ -2451,7 +2451,7 @@ export class BaileysStartupService extends WAStartupService { { audio: Buffer.from(audio, 'base64'), ptt: true, - mimetype: 'audio/ogg; codecs=opus', + mimetype: 'audio/mp4', }, { presence: 'recording', delay: data?.options?.delay }, isChatwoot, From 5ae5d8546e0e9ca9f080a820f4477c39dd592183 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Wed, 17 Apr 2024 18:10:43 -0300 Subject: [PATCH 29/42] fix: retry messages --- src/api/controllers/instance.controller.ts | 3 ++ .../controllers/chatwoot.controller.ts | 2 +- src/api/server.module.ts | 13 ++++- src/api/services/monitor.service.ts | 3 ++ src/api/services/whatsapp.service.ts | 2 + .../whatsapp/whatsapp.baileys.service.ts | 53 +++++++++++-------- .../whatsapp/whatsapp.business.service.ts | 1 + .../chatwoot => }/cache/cacheengine.ts | 4 +- .../chatwoot => }/cache/localcache.ts | 4 +- .../chatwoot => }/cache/rediscache.client.ts | 4 +- .../chatwoot => }/cache/rediscache.ts | 6 +-- src/config/logger.config.ts | 9 ++++ 12 files changed, 71 insertions(+), 33 deletions(-) rename src/{api/integrations/chatwoot => }/cache/cacheengine.ts (81%) rename src/{api/integrations/chatwoot => }/cache/localcache.ts (89%) rename src/{api/integrations/chatwoot => }/cache/rediscache.client.ts (90%) rename src/{api/integrations/chatwoot => }/cache/rediscache.ts (90%) diff --git a/src/api/controllers/instance.controller.ts b/src/api/controllers/instance.controller.ts index 563bc5fd..2ca0b031 100644 --- a/src/api/controllers/instance.controller.ts +++ b/src/api/controllers/instance.controller.ts @@ -43,6 +43,7 @@ export class InstanceController { private readonly proxyService: ProxyController, private readonly cache: RedisCache, private readonly chatwootCache: CacheService, + private readonly messagesLostCache: CacheService, ) {} private readonly logger = new Logger(InstanceController.name); @@ -108,6 +109,7 @@ export class InstanceController { this.repository, this.cache, this.chatwootCache, + this.messagesLostCache, ); } else { instance = new BaileysStartupService( @@ -116,6 +118,7 @@ export class InstanceController { this.repository, this.cache, this.chatwootCache, + this.messagesLostCache, ); } diff --git a/src/api/integrations/chatwoot/controllers/chatwoot.controller.ts b/src/api/integrations/chatwoot/controllers/chatwoot.controller.ts index 03282ce5..2621465e 100644 --- a/src/api/integrations/chatwoot/controllers/chatwoot.controller.ts +++ b/src/api/integrations/chatwoot/controllers/chatwoot.controller.ts @@ -1,5 +1,6 @@ import { isURL } from 'class-validator'; +import { CacheEngine } from '../../../../cache/cacheengine'; import { ConfigService, HttpServer } from '../../../../config/env.config'; import { Logger } from '../../../../config/logger.config'; import { BadRequestException } from '../../../../exceptions'; @@ -7,7 +8,6 @@ import { InstanceDto } from '../../../dto/instance.dto'; import { RepositoryBroker } from '../../../repository/repository.manager'; import { waMonitor } from '../../../server.module'; import { CacheService } from '../../../services/cache.service'; -import { CacheEngine } from '../cache/cacheengine'; import { ChatwootDto } from '../dto/chatwoot.dto'; import { ChatwootService } from '../services/chatwoot.service'; diff --git a/src/api/server.module.ts b/src/api/server.module.ts index 5c78e1c3..e41eefeb 100644 --- a/src/api/server.module.ts +++ b/src/api/server.module.ts @@ -1,3 +1,4 @@ +import { CacheEngine } from '../cache/cacheengine'; import { configService } from '../config/env.config'; import { eventEmitter } from '../config/event.config'; import { Logger } from '../config/logger.config'; @@ -14,7 +15,6 @@ import { WebhookController } from './controllers/webhook.controller'; import { ChamaaiController } from './integrations/chamaai/controllers/chamaai.controller'; import { ChamaaiRepository } from './integrations/chamaai/repository/chamaai.repository'; import { ChamaaiService } from './integrations/chamaai/services/chamaai.service'; -import { CacheEngine } from './integrations/chatwoot/cache/cacheengine'; import { ChatwootController } from './integrations/chatwoot/controllers/chatwoot.controller'; import { ChatwootRepository } from './integrations/chatwoot/repository/chatwoot.repository'; import { ChatwootService } from './integrations/chatwoot/services/chatwoot.service'; @@ -109,8 +109,16 @@ export const repository = new RepositoryBroker( export const cache = new RedisCache(); const chatwootCache = new CacheService(new CacheEngine(configService, ChatwootService.name).getEngine()); +const messagesLostCache = new CacheService(new CacheEngine(configService, 'baileys').getEngine()); -export const waMonitor = new WAMonitoringService(eventEmitter, configService, repository, cache, chatwootCache); +export const waMonitor = new WAMonitoringService( + eventEmitter, + configService, + repository, + cache, + chatwootCache, + messagesLostCache, +); const authService = new AuthService(configService, waMonitor, repository); @@ -160,6 +168,7 @@ export const instanceController = new InstanceController( proxyController, cache, chatwootCache, + messagesLostCache, ); export const sendMessageController = new SendMessageController(waMonitor); export const chatController = new ChatController(waMonitor); diff --git a/src/api/services/monitor.service.ts b/src/api/services/monitor.service.ts index e8644e99..87c00774 100644 --- a/src/api/services/monitor.service.ts +++ b/src/api/services/monitor.service.ts @@ -36,6 +36,7 @@ export class WAMonitoringService { private readonly repository: RepositoryBroker, private readonly cache: RedisCache, private readonly chatwootCache: CacheService, + private readonly messagesLostCache: CacheService, ) { this.logger.verbose('instance created'); @@ -346,6 +347,7 @@ export class WAMonitoringService { this.repository, this.cache, this.chatwootCache, + this.messagesLostCache, ); instance.instanceName = name; @@ -356,6 +358,7 @@ export class WAMonitoringService { this.repository, this.cache, this.chatwootCache, + this.messagesLostCache, ); instance.instanceName = name; diff --git a/src/api/services/whatsapp.service.ts b/src/api/services/whatsapp.service.ts index 3599c15b..ade84c4f 100644 --- a/src/api/services/whatsapp.service.ts +++ b/src/api/services/whatsapp.service.ts @@ -71,6 +71,8 @@ export class WAStartupService { public chamaaiService = new ChamaaiService(waMonitor, this.configService); public set instanceName(name: string) { + this.logger.setInstance(name); + this.logger.verbose(`Initializing instance '${name}'`); if (!name) { this.logger.verbose('Instance name not found, generating random name with uuid'); diff --git a/src/api/services/whatsapp/whatsapp.baileys.service.ts b/src/api/services/whatsapp/whatsapp.baileys.service.ts index 9c87fb8e..363a7448 100644 --- a/src/api/services/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/services/whatsapp/whatsapp.baileys.service.ts @@ -121,8 +121,6 @@ import { Events, MessageSubtype, TypeMediaMessage, wa } from '../../types/wa.typ import { CacheService } from './../cache.service'; import { WAStartupService } from './../whatsapp.service'; -// const retryCache = {}; - export class BaileysStartupService extends WAStartupService { constructor( public readonly configService: ConfigService, @@ -130,12 +128,17 @@ export class BaileysStartupService extends WAStartupService { public readonly repository: RepositoryBroker, public readonly cache: RedisCache, public readonly chatwootCache: CacheService, + public readonly messagesLostCache: CacheService, ) { super(configService, eventEmitter, repository, chatwootCache); this.logger.verbose('BaileysStartupService initialized'); this.cleanStore(); this.instance.qrcode = { count: 0 }; this.mobile = false; + + setTimeout(() => { + this.recoveringMessages(); + }, 30000); } private readonly msgRetryCounterCache: CacheStore = new NodeCache(); @@ -148,6 +151,18 @@ export class BaileysStartupService extends WAStartupService { public phoneNumber: string; public mobile: boolean; + private async recoveringMessages() { + this.logger.info('Recovering messages'); + this.messagesLostCache.keys().then((keys) => { + keys.forEach(async (key) => { + const message = await this.messagesLostCache.get(key.split(':')[2]); + + if (message.messageStubParameters && message.messageStubParameters[0] === 'Message absent from node') + await this.client.sendMessageAck(JSON.parse(message.messageStubParameters[1], BufferJSON.reviver)); + }); + }); + } + public get connectionStatus() { this.logger.verbose('Getting connection status'); return this.stateConnection; @@ -378,10 +393,12 @@ export class BaileysStartupService extends WAStartupService { │ CONNECTED TO WHATSAPP │ └──────────────────────────────┘`.replace(/^ +/gm, ' '), ); - this.logger.info(` + this.logger.info( + ` wuid: ${formattedWuid} name: ${formattedName} - `); + `, + ); if (this.localChatwoot.enabled) { this.chatwootService.eventWhatsapp( @@ -1044,12 +1061,22 @@ export class BaileysStartupService extends WAStartupService { } } + await this.messagesLostCache.set(received.key.id, received); + if (received.messageStubParameters && received.messageStubParameters[0] === 'Message absent from node') { this.logger.info('Recovering message lost'); - await this.client.sendMessageAck(JSON.parse(received.messageStubParameters[1], BufferJSON.reviver)); + + await this.messagesLostCache.set(received.key.id, received); continue; } + // const retryCache = (await this.messagesLostCache.get(received.key.id)) || null; + + // if (retryCache) { + // this.logger.info('Recovered message lost'); + // await this.messagesLostCache.delete(received.key.id); + // } + if ( (type !== 'notify' && type !== 'append') || received.message?.protocolMessage || @@ -1248,7 +1275,6 @@ export class BaileysStartupService extends WAStartupService { } } - // if (key.remoteJid !== 'status@broadcast' && !key?.remoteJid?.match(/(:\d+)/)) { if (key.remoteJid !== 'status@broadcast') { this.logger.verbose('Message update is valid'); @@ -1479,27 +1505,12 @@ export class BaileysStartupService extends WAStartupService { if (events['messages.upsert']) { this.logger.verbose('Listening event: messages.upsert'); const payload = events['messages.upsert']; - // if (payload.messages.find((a) => a?.messageStubType === 2)) { - // const msg = payload.messages[0]; - // retryCache[msg.key.id] = msg; - // return; - // } this.messageHandle['messages.upsert'](payload, database, settings); } if (events['messages.update']) { this.logger.verbose('Listening event: messages.update'); const payload = events['messages.update']; - // payload.forEach((message) => { - // if (retryCache[message.key.id]) { - // this.client.ev.emit('messages.upsert', { - // messages: [message], - // type: 'notify', - // }); - // delete retryCache[message.key.id]; - // return; - // } - // }); this.messageHandle['messages.update'](payload, database, settings); } diff --git a/src/api/services/whatsapp/whatsapp.business.service.ts b/src/api/services/whatsapp/whatsapp.business.service.ts index 89cc2089..23ae3621 100644 --- a/src/api/services/whatsapp/whatsapp.business.service.ts +++ b/src/api/services/whatsapp/whatsapp.business.service.ts @@ -36,6 +36,7 @@ export class BusinessStartupService extends WAStartupService { public readonly repository: RepositoryBroker, public readonly cache: RedisCache, public readonly chatwootCache: CacheService, + public readonly messagesLostCache: CacheService, ) { super(configService, eventEmitter, repository, chatwootCache); this.logger.verbose('BusinessStartupService initialized'); diff --git a/src/api/integrations/chatwoot/cache/cacheengine.ts b/src/cache/cacheengine.ts similarity index 81% rename from src/api/integrations/chatwoot/cache/cacheengine.ts rename to src/cache/cacheengine.ts index a05e3dae..258a98c2 100644 --- a/src/api/integrations/chatwoot/cache/cacheengine.ts +++ b/src/cache/cacheengine.ts @@ -1,5 +1,5 @@ -import { CacheConf, ConfigService } from '../../../../config/env.config'; -import { ICache } from '../../../abstract/abstract.cache'; +import { ICache } from '../api/abstract/abstract.cache'; +import { CacheConf, ConfigService } from '../config/env.config'; import { LocalCache } from './localcache'; import { RedisCache } from './rediscache'; diff --git a/src/api/integrations/chatwoot/cache/localcache.ts b/src/cache/localcache.ts similarity index 89% rename from src/api/integrations/chatwoot/cache/localcache.ts rename to src/cache/localcache.ts index 7bf53e71..323b0343 100644 --- a/src/api/integrations/chatwoot/cache/localcache.ts +++ b/src/cache/localcache.ts @@ -1,7 +1,7 @@ import NodeCache from 'node-cache'; -import { CacheConf, CacheConfLocal, ConfigService } from '../../../../config/env.config'; -import { ICache } from '../../../abstract/abstract.cache'; +import { ICache } from '../api/abstract/abstract.cache'; +import { CacheConf, CacheConfLocal, ConfigService } from '../config/env.config'; export class LocalCache implements ICache { private conf: CacheConfLocal; diff --git a/src/api/integrations/chatwoot/cache/rediscache.client.ts b/src/cache/rediscache.client.ts similarity index 90% rename from src/api/integrations/chatwoot/cache/rediscache.client.ts rename to src/cache/rediscache.client.ts index 0a3ef4fc..b3f8dead 100644 --- a/src/api/integrations/chatwoot/cache/rediscache.client.ts +++ b/src/cache/rediscache.client.ts @@ -1,7 +1,7 @@ import { createClient, RedisClientType } from 'redis'; -import { CacheConf, CacheConfRedis, configService } from '../../../../config/env.config'; -import { Logger } from '../../../../config/logger.config'; +import { CacheConf, CacheConfRedis, configService } from '../config/env.config'; +import { Logger } from '../config/logger.config'; class Redis { private logger = new Logger(Redis.name); diff --git a/src/api/integrations/chatwoot/cache/rediscache.ts b/src/cache/rediscache.ts similarity index 90% rename from src/api/integrations/chatwoot/cache/rediscache.ts rename to src/cache/rediscache.ts index 2a08fb3a..e010665f 100644 --- a/src/api/integrations/chatwoot/cache/rediscache.ts +++ b/src/cache/rediscache.ts @@ -1,8 +1,8 @@ import { RedisClientType } from 'redis'; -import { CacheConf, CacheConfRedis, ConfigService } from '../../../../config/env.config'; -import { Logger } from '../../../../config/logger.config'; -import { ICache } from '../../../abstract/abstract.cache'; +import { ICache } from '../api/abstract/abstract.cache'; +import { CacheConf, CacheConfRedis, ConfigService } from '../config/env.config'; +import { Logger } from '../config/logger.config'; import { redisClient } from './rediscache.client'; export class RedisCache implements ICache { diff --git a/src/config/logger.config.ts b/src/config/logger.config.ts index 221ee098..c52d3ccc 100644 --- a/src/config/logger.config.ts +++ b/src/config/logger.config.ts @@ -60,10 +60,16 @@ export class Logger { private readonly configService = configService; constructor(private context = 'Logger') {} + private instance = null; + public setContext(value: string) { this.context = value; } + public setInstance(value: string) { + this.instance = value; + } + private console(value: any, type: Type) { const types: Type[] = []; @@ -76,6 +82,8 @@ export class Logger { /*Command.UNDERSCORE +*/ Command.BRIGHT + Level[type], '[Evolution API]', Command.BRIGHT + Color[type], + this.instance ? `[${this.instance}]` : '', + Command.BRIGHT + Color[type], `v${packageJson.version}`, Command.BRIGHT + Color[type], process.pid.toString(), @@ -99,6 +107,7 @@ export class Logger { } else { console.log( '[Evolution API]', + this.instance ? `[${this.instance}]` : '', process.pid.toString(), '-', `${formatDateLog(Date.now())} `, From b3aeed7fc12576fb1ed70506d1ac64a62fc31e47 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Wed, 17 Apr 2024 18:14:11 -0300 Subject: [PATCH 30/42] fix: retry messages --- .../services/whatsapp/whatsapp.baileys.service.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/api/services/whatsapp/whatsapp.baileys.service.ts b/src/api/services/whatsapp/whatsapp.baileys.service.ts index 363a7448..8fc7a681 100644 --- a/src/api/services/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/services/whatsapp/whatsapp.baileys.service.ts @@ -1061,8 +1061,6 @@ export class BaileysStartupService extends WAStartupService { } } - await this.messagesLostCache.set(received.key.id, received); - if (received.messageStubParameters && received.messageStubParameters[0] === 'Message absent from node') { this.logger.info('Recovering message lost'); @@ -1070,12 +1068,12 @@ export class BaileysStartupService extends WAStartupService { continue; } - // const retryCache = (await this.messagesLostCache.get(received.key.id)) || null; + const retryCache = (await this.messagesLostCache.get(received.key.id)) || null; - // if (retryCache) { - // this.logger.info('Recovered message lost'); - // await this.messagesLostCache.delete(received.key.id); - // } + if (retryCache) { + this.logger.info('Recovered message lost'); + await this.messagesLostCache.delete(received.key.id); + } if ( (type !== 'notify' && type !== 'append') || From 9764719245ca7bf8c56582a401bf68b7734fe42d Mon Sep 17 00:00:00 2001 From: nestordavalos Date: Wed, 17 Apr 2024 17:20:37 -0400 Subject: [PATCH 31/42] =?UTF-8?q?=E2=9C=A8=20feat:=20add=20support=20for?= =?UTF-8?q?=20Spanish?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/i18n.ts | 2 +- src/utils/translations/es.json | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/utils/translations/es.json diff --git a/src/utils/i18n.ts b/src/utils/i18n.ts index 74a76724..8e23181d 100644 --- a/src/utils/i18n.ts +++ b/src/utils/i18n.ts @@ -4,7 +4,7 @@ import path from 'path'; import { ConfigService, Language } from '../config/env.config'; -const languages = ['en', 'pt-BR']; +const languages = ['en', 'pt-BR', 'es']; const translationsPath = path.join(__dirname, 'translations'); const configService: ConfigService = new ConfigService(); diff --git a/src/utils/translations/es.json b/src/utils/translations/es.json new file mode 100644 index 00000000..28784063 --- /dev/null +++ b/src/utils/translations/es.json @@ -0,0 +1,26 @@ +{ + "qrgeneratedsuccesfully": "Código QR generado exitosamente!", + "scanqr": "Escanea este código QR en los próximos 40 segundos.", + "qrlimitreached": "🚨 Se alcanzó el límite de generación de QRCode. Para generar un nuevo QRCode, envíe el mensaje 'init' nuevamente.", + "numbernotinwhatsapp": "⚠️ El mensaje no fue enviado porque el contacto no es un número de Whatsapp válido..", + "cw.inbox.connected": "🚀 ¡Conexión establecida exitosamente!", + "cw.inbox.disconnect": "🚨 Instancia *{{inboxName}}* desconectado de Whatsapp.", + "cw.inbox.alreadyConnected": "🚨 La instancia {{inboxName}} está conectada.", + "cw.inbox.clearCache": "✅ Caché de la instancia {{inboxName}} borrada.", + "cw.inbox.notFound": "⚠️ Instancia {{inboxName}} no encontrada.", + "cw.inbox.status": "⚠️ Estado de la instancia {{inboxName}}: *{{state}}*.", + "cw.import.startImport": "💬 Empezando a importar mensajes. Espere por favor...", + "cw.import.importingMessages": "💬 Importando mensajes. mas un momento...", + "cw.import.messagesImported": "💬 {{totalMessagesImported}} mensajes importados. Actualiza la página para ver los nuevos mensajes..", + "cw.import.messagesException": "⚠️ Algo salió mal al importar mensajes..", + "cw.locationMessage.location": "Ubicación", + "cw.locationMessage.latitude": "Latitude", + "cw.locationMessage.longitude": "Longitude", + "cw.locationMessage.locationName": "Nombre", + "cw.locationMessage.locationAddress": "Direccion", + "cw.locationMessage.locationUrl": "URL", + "cw.contactMessage.contact": "Contacto", + "cw.contactMessage.name": "Nombre", + "cw.contactMessage.number": "Numero", + "cw.message.edited": "Mensaje editado" +} \ No newline at end of file From 07ff61c0701e01295a372d320e82fe2034b64786 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Wed, 17 Apr 2024 18:25:35 -0300 Subject: [PATCH 32/42] changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1e575e3..8053d747 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,10 @@ ### Fixed * Revert fix audio encoding -* Recovering messages lost +* Recovering messages lost with redis cache * Adjusts in proxy * Revert pull request #523 +* Added instance name on logs # 1.7.2 (2024-04-12 17:31) From 27f67142c818a59a6f9a02d1a1d6cb29fe4a7d34 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Wed, 17 Apr 2024 18:46:50 -0300 Subject: [PATCH 33/42] changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8053d747..f58e9e2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ * Adjusts in proxy * Revert pull request #523 * Added instance name on logs +* Added support for Spanish +* Fix error: invalid operator. The allowed operators for identifier are equal_to,not_equal_to # 1.7.2 (2024-04-12 17:31) From 4ed1335f89f789d10b773eb2c51f16fe452f3afc Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Wed, 17 Apr 2024 19:58:31 -0300 Subject: [PATCH 34/42] changelog --- .../whatsapp/whatsapp.baileys.service.ts | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/api/services/whatsapp/whatsapp.baileys.service.ts b/src/api/services/whatsapp/whatsapp.baileys.service.ts index 8fc7a681..ac7520b7 100644 --- a/src/api/services/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/services/whatsapp/whatsapp.baileys.service.ts @@ -135,10 +135,7 @@ export class BaileysStartupService extends WAStartupService { this.cleanStore(); this.instance.qrcode = { count: 0 }; this.mobile = false; - - setTimeout(() => { - this.recoveringMessages(); - }, 30000); + this.recoveringMessages(); } private readonly msgRetryCounterCache: CacheStore = new NodeCache(); @@ -152,15 +149,19 @@ export class BaileysStartupService extends WAStartupService { public mobile: boolean; private async recoveringMessages() { - this.logger.info('Recovering messages'); - this.messagesLostCache.keys().then((keys) => { - keys.forEach(async (key) => { - const message = await this.messagesLostCache.get(key.split(':')[2]); + setTimeout(async () => { + this.logger.info('Recovering messages'); + this.messagesLostCache.keys().then((keys) => { + keys.forEach(async (key) => { + const message = await this.messagesLostCache.get(key.split(':')[2]); - if (message.messageStubParameters && message.messageStubParameters[0] === 'Message absent from node') - await this.client.sendMessageAck(JSON.parse(message.messageStubParameters[1], BufferJSON.reviver)); + if (message.messageStubParameters && message.messageStubParameters[0] === 'Message absent from node') { + this.logger.verbose('Message absent from node, retrying to send, key: ' + key.split(':')[2]); + await this.client.sendMessageAck(JSON.parse(message.messageStubParameters[1], BufferJSON.reviver)); + } + }); }); - }); + }, 30000); } public get connectionStatus() { From bb974e10f5baf077758689496dc47f744e349bc2 Mon Sep 17 00:00:00 2001 From: Paulo Kramer Date: Thu, 18 Apr 2024 00:58:33 -0300 Subject: [PATCH 35/42] Added message status to the messaging-history.set --- src/api/models/message.model.ts | 1 + src/api/services/whatsapp/whatsapp.baileys.service.ts | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/api/models/message.model.ts b/src/api/models/message.model.ts index 893d1f2a..95cb5513 100644 --- a/src/api/models/message.model.ts +++ b/src/api/models/message.model.ts @@ -32,6 +32,7 @@ export class MessageRaw { source_reply_id?: string; chatwoot?: ChatwootMessage; contextInfo?: any; + status?: wa.StatusMessage | any; } type MessageRawBoolean = { diff --git a/src/api/services/whatsapp/whatsapp.baileys.service.ts b/src/api/services/whatsapp/whatsapp.baileys.service.ts index 6285250b..82a301c0 100644 --- a/src/api/services/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/services/whatsapp/whatsapp.baileys.service.ts @@ -976,6 +976,15 @@ export class BaileysStartupService extends WAStartupService { continue; } + const status: Record = { + 0: 'ERROR', + 1: 'PENDING', + 2: 'SERVER_ACK', + 3: 'DELIVERY_ACK', + 4: 'READ', + 5: 'PLAYED', + }; + messagesRaw.push({ key: m.key, pushName: m.pushName || m.key.remoteJid.split('@')[0], @@ -984,6 +993,7 @@ export class BaileysStartupService extends WAStartupService { messageType: getContentType(m.message), messageTimestamp: m.messageTimestamp as number, owner: this.instance.name, + status: m.status ? status[m.status] : null, }); } From 61bd5b34847d0fbaea14581f61bce1c41ef564ed Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Thu, 18 Apr 2024 10:39:24 -0300 Subject: [PATCH 36/42] fix: Adjusts in redis for save instances --- CHANGELOG.md | 3 +- Docker/.env.example | 21 ++- .../evolution-api-all-services/.env.example | 21 ++- Dockerfile | 12 +- src/api/abstract/abstract.cache.ts | 6 + src/api/controllers/instance.controller.ts | 3 +- src/api/guards/instance.guard.ts | 9 +- src/api/server.module.ts | 3 +- src/api/services/cache.service.ts | 37 ++++++ src/api/services/monitor.service.ts | 23 ++-- .../whatsapp/whatsapp.baileys.service.ts | 40 +++--- .../whatsapp/whatsapp.business.service.ts | 3 +- src/cache/localcache.ts | 13 ++ src/cache/rediscache.ts | 34 ++++- src/config/env.config.ts | 14 +- src/dev-env.yml | 8 +- src/libs/redis.client.ts | 123 ------------------ .../use-multi-file-auth-state-redis-db.ts | 13 +- 18 files changed, 178 insertions(+), 208 deletions(-) delete mode 100644 src/libs/redis.client.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index f58e9e2f..b103298e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,12 @@ ### Fixed * Revert fix audio encoding * Recovering messages lost with redis cache +* Adjusts in redis for save instances * Adjusts in proxy * Revert pull request #523 * Added instance name on logs * Added support for Spanish -* Fix error: invalid operator. The allowed operators for identifier are equal_to,not_equal_to +* Fix error: invalid operator. The allowed operators for identifier are equal_to,not_equal_to in chatwoot # 1.7.2 (2024-04-12 17:31) diff --git a/Docker/.env.example b/Docker/.env.example index 865ef877..04dd0805 100644 --- a/Docker/.env.example +++ b/Docker/.env.example @@ -33,7 +33,10 @@ CLEAN_STORE_CHATS=true # Permanent data storage DATABASE_ENABLED=false -DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true +DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin & +readPreference=primary & +ssl=false & +directConnection=true DATABASE_CONNECTION_DB_PREFIX_NAME=evdocker # Choose the data you want to save in the application's database or store @@ -43,10 +46,6 @@ DATABASE_SAVE_MESSAGE_UPDATE=false DATABASE_SAVE_DATA_CONTACTS=false DATABASE_SAVE_DATA_CHATS=false -REDIS_ENABLED=false -REDIS_URI=redis://redis:6379 -REDIS_PREFIX_KEY=evdocker - RABBITMQ_ENABLED=false RABBITMQ_RABBITMQ_MODE=global RABBITMQ_EXCHANGE_NAME=evolution_exchange @@ -73,7 +72,7 @@ WEBHOOK_GLOBAL_URL='' WEBHOOK_GLOBAL_ENABLED=false # With this option activated, you work with a url per webhook event, respecting the global url and the name of each event WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=false -## Set the events you want to hear +## Set the events you want to hear WEBHOOK_EVENTS_APPLICATION_STARTUP=false WEBHOOK_EVENTS_QRCODE_UPDATED=true WEBHOOK_EVENTS_MESSAGES_SET=true @@ -129,6 +128,14 @@ CHATWOOT_MESSAGE_READ=false # false | true CHATWOOT_IMPORT_DATABASE_CONNECTION_URI=postgres://user:password@hostname:port/dbname CHATWOOT_IMPORT_DATABASE_PLACEHOLDER_MEDIA_MESSAGE=true +CACHE_REDIS_ENABLED=false +CACHE_REDIS_URI=redis://redis:6379 +CACHE_REDIS_PREFIX_KEY=evolution +CACHE_REDIS_TTL=604800 +CACHE_REDIS_SAVE_INSTANCES=false +CACHE_LOCAL_ENABLED=false +CACHE_LOCAL_TTL=604800 + # Defines an authentication type for the api # We recommend using the apikey because it will allow you to use a custom token, # if you use jwt, a random token will be generated and may be expired and you will have to generate a new token @@ -143,4 +150,4 @@ AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=true AUTHENTICATION_JWT_EXPIRIN_IN=0 AUTHENTICATION_JWT_SECRET='L=0YWt]b2w[WF>#>:&E`' -LANGUAGE=en # pt-BR, en \ No newline at end of file +LANGUAGE=en # pt-BR, en diff --git a/Docker/evolution-api-all-services/.env.example b/Docker/evolution-api-all-services/.env.example index a28ad50f..d08fee49 100644 --- a/Docker/evolution-api-all-services/.env.example +++ b/Docker/evolution-api-all-services/.env.example @@ -33,7 +33,10 @@ CLEAN_STORE_CHATS=true # Permanent data storage DATABASE_ENABLED=true -DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true +DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin & +readPreference=primary & +ssl=false & +directConnection=true DATABASE_CONNECTION_DB_PREFIX_NAME=evolution # Choose the data you want to save in the application's database or store @@ -43,10 +46,6 @@ DATABASE_SAVE_MESSAGE_UPDATE=false DATABASE_SAVE_DATA_CONTACTS=false DATABASE_SAVE_DATA_CHATS=false -REDIS_ENABLED=true -REDIS_URI=redis://redis:6379 -REDIS_PREFIX_KEY=evolution - # Global Webhook Settings # Each instance's Webhook URL and events will be requested at the time it is created ## Define a global webhook that will listen for enabled events from all instances @@ -54,7 +53,7 @@ WEBHOOK_GLOBAL_URL='' WEBHOOK_GLOBAL_ENABLED=false # With this option activated, you work with a url per webhook event, respecting the global url and the name of each event WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=false -## Set the events you want to hear +## Set the events you want to hear WEBHOOK_EVENTS_APPLICATION_STARTUP=false WEBHOOK_EVENTS_QRCODE_UPDATED=true WEBHOOK_EVENTS_MESSAGES_SET=true @@ -87,6 +86,14 @@ CONFIG_SESSION_PHONE_NAME=chrome # Set qrcode display limit QRCODE_LIMIT=30 +CACHE_REDIS_ENABLED=false +CACHE_REDIS_URI=redis://redis:6379 +CACHE_REDIS_PREFIX_KEY=evolution +CACHE_REDIS_TTL=604800 +CACHE_REDIS_SAVE_INSTANCES=false +CACHE_LOCAL_ENABLED=false +CACHE_LOCAL_TTL=604800 + # Defines an authentication type for the api # We recommend using the apikey because it will allow you to use a custom token, # if you use jwt, a random token will be generated and may be expired and you will have to generate a new token @@ -109,4 +116,4 @@ AUTHENTICATION_INSTANCE_NAME=evolution AUTHENTICATION_INSTANCE_WEBHOOK_URL='' AUTHENTICATION_INSTANCE_CHATWOOT_ACCOUNT_ID=1 AUTHENTICATION_INSTANCE_CHATWOOT_TOKEN=123456 -AUTHENTICATION_INSTANCE_CHATWOOT_URL='' \ No newline at end of file +AUTHENTICATION_INSTANCE_CHATWOOT_URL='' diff --git a/Dockerfile b/Dockerfile index b913a37e..a5e5c8b2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,10 +58,6 @@ ENV DATABASE_SAVE_MESSAGE_UPDATE=false ENV DATABASE_SAVE_DATA_CONTACTS=false ENV DATABASE_SAVE_DATA_CHATS=false -ENV REDIS_ENABLED=false -ENV REDIS_URI=redis://redis:6379 -ENV REDIS_PREFIX_KEY=evolution - ENV RABBITMQ_ENABLED=false ENV RABBITMQ_MODE=global ENV RABBITMQ_EXCHANGE_NAME=evolution_exchange @@ -129,6 +125,14 @@ ENV QRCODE_COLOR=#198754 ENV TYPEBOT_API_VERSION=latest +ENV CACHE_REDIS_ENABLED=false +ENV CACHE_REDIS_URI=redis://redis:6379 +ENV CACHE_REDIS_PREFIX_KEY=evolution +ENV CACHE_REDIS_TTL=604800 +ENV CACHE_REDIS_SAVE_INSTANCES=false +ENV CACHE_LOCAL_ENABLED=false +ENV CACHE_LOCAL_TTL=604800 + ENV AUTHENTICATION_TYPE=apikey ENV AUTHENTICATION_API_KEY=B6D711FCDE4D4FD5936544120E713976 diff --git a/src/api/abstract/abstract.cache.ts b/src/api/abstract/abstract.cache.ts index caad2691..2d93f323 100644 --- a/src/api/abstract/abstract.cache.ts +++ b/src/api/abstract/abstract.cache.ts @@ -1,13 +1,19 @@ export interface ICache { get(key: string): Promise; + hGet(key: string, field: string): Promise; + set(key: string, value: any, ttl?: number): void; + hSet(key: string, field: string, value: any): Promise; + has(key: string): Promise; keys(appendCriteria?: string): Promise; delete(key: string | string[]): Promise; + hDelete(key: string, field: string): Promise; + deleteAll(appendCriteria?: string): Promise; } diff --git a/src/api/controllers/instance.controller.ts b/src/api/controllers/instance.controller.ts index 2ca0b031..abe1dd3b 100644 --- a/src/api/controllers/instance.controller.ts +++ b/src/api/controllers/instance.controller.ts @@ -6,7 +6,6 @@ import { v4 } from 'uuid'; import { ConfigService, HttpServer, WaBusiness } from '../../config/env.config'; import { Logger } from '../../config/logger.config'; import { BadRequestException, InternalServerErrorException } from '../../exceptions'; -import { RedisCache } from '../../libs/redis.client'; import { InstanceDto, SetPresenceDto } from '../dto/instance.dto'; import { ChatwootService } from '../integrations/chatwoot/services/chatwoot.service'; import { RabbitmqService } from '../integrations/rabbitmq/services/rabbitmq.service'; @@ -41,7 +40,7 @@ export class InstanceController { private readonly typebotService: TypebotService, private readonly integrationService: IntegrationService, private readonly proxyService: ProxyController, - private readonly cache: RedisCache, + private readonly cache: CacheService, private readonly chatwootCache: CacheService, private readonly messagesLostCache: CacheService, ) {} diff --git a/src/api/guards/instance.guard.ts b/src/api/guards/instance.guard.ts index 2214bd43..84cabb12 100644 --- a/src/api/guards/instance.guard.ts +++ b/src/api/guards/instance.guard.ts @@ -2,7 +2,7 @@ import { NextFunction, Request, Response } from 'express'; import { existsSync } from 'fs'; import { join } from 'path'; -import { configService, Database, Redis } from '../../config/env.config'; +import { CacheConf, configService, Database } from '../../config/env.config'; import { INSTANCE_DIR } from '../../config/path.config'; import { BadRequestException, @@ -17,12 +17,13 @@ import { cache, waMonitor } from '../server.module'; async function getInstance(instanceName: string) { try { const db = configService.get('DATABASE'); - const redisConf = configService.get('REDIS'); + const cacheConf = configService.get('CACHE'); const exists = !!waMonitor.waInstances[instanceName]; - if (redisConf.ENABLED) { - const keyExists = await cache.keyExists(); + if (cacheConf.REDIS.ENABLED && cacheConf.REDIS.SAVE_INSTANCES) { + const keyExists = await cache.has(instanceName); + return exists || keyExists; } diff --git a/src/api/server.module.ts b/src/api/server.module.ts index e41eefeb..97df81a3 100644 --- a/src/api/server.module.ts +++ b/src/api/server.module.ts @@ -3,7 +3,6 @@ import { configService } from '../config/env.config'; import { eventEmitter } from '../config/event.config'; import { Logger } from '../config/logger.config'; import { dbserver } from '../libs/db.connect'; -import { RedisCache } from '../libs/redis.client'; import { ChatController } from './controllers/chat.controller'; import { GroupController } from './controllers/group.controller'; import { InstanceController } from './controllers/instance.controller'; @@ -107,7 +106,7 @@ export const repository = new RepositoryBroker( dbserver?.getClient(), ); -export const cache = new RedisCache(); +export const cache = new CacheService(new CacheEngine(configService, 'instance').getEngine()); const chatwootCache = new CacheService(new CacheEngine(configService, ChatwootService.name).getEngine()); const messagesLostCache = new CacheService(new CacheEngine(configService, 'baileys').getEngine()); diff --git a/src/api/services/cache.service.ts b/src/api/services/cache.service.ts index 0db39a44..caf3dbfa 100644 --- a/src/api/services/cache.service.ts +++ b/src/api/services/cache.service.ts @@ -1,3 +1,5 @@ +import { BufferJSON } from '@whiskeysockets/baileys'; + import { Logger } from '../../config/logger.config'; import { ICache } from '../abstract/abstract.cache'; @@ -20,6 +22,21 @@ export class CacheService { return this.cache.get(key); } + public async hGet(key: string, field: string) { + try { + const data = await this.cache.hGet(key, field); + + if (data) { + return JSON.parse(data, BufferJSON.reviver); + } + + return null; + } catch (error) { + this.logger.error(error); + return null; + } + } + async set(key: string, value: any) { if (!this.cache) { return; @@ -28,6 +45,16 @@ export class CacheService { this.cache.set(key, value); } + public async hSet(key: string, field: string, value: any) { + try { + const json = JSON.stringify(value, BufferJSON.replacer); + + await this.cache.hSet(key, field, json); + } catch (error) { + this.logger.error(error); + } + } + async has(key: string) { if (!this.cache) { return; @@ -44,6 +71,16 @@ export class CacheService { return this.cache.delete(key); } + async hDelete(key: string, field: string) { + try { + await this.cache.hDelete(key, field); + return true; + } catch (error) { + this.logger.error(error); + return false; + } + } + async deleteAll(appendCriteria?: string) { if (!this.cache) { return; diff --git a/src/api/services/monitor.service.ts b/src/api/services/monitor.service.ts index 87c00774..df6b333a 100644 --- a/src/api/services/monitor.service.ts +++ b/src/api/services/monitor.service.ts @@ -5,11 +5,10 @@ import { Db } from 'mongodb'; import { Collection } from 'mongoose'; import { join } from 'path'; -import { Auth, ConfigService, Database, DelInstance, HttpServer, Redis } from '../../config/env.config'; +import { Auth, CacheConf, ConfigService, Database, DelInstance, HttpServer } from '../../config/env.config'; import { Logger } from '../../config/logger.config'; import { INSTANCE_DIR, STORE_DIR } from '../../config/path.config'; import { NotFoundException } from '../../exceptions'; -import { RedisCache } from '../../libs/redis.client'; import { AuthModel, ChamaaiModel, @@ -34,7 +33,7 @@ export class WAMonitoringService { private readonly eventEmitter: EventEmitter2, private readonly configService: ConfigService, private readonly repository: RepositoryBroker, - private readonly cache: RedisCache, + private readonly cache: CacheService, private readonly chatwootCache: CacheService, private readonly messagesLostCache: CacheService, ) { @@ -44,7 +43,7 @@ export class WAMonitoringService { this.noConnection(); Object.assign(this.db, configService.get('DATABASE')); - Object.assign(this.redis, configService.get('REDIS')); + Object.assign(this.redis, configService.get('CACHE')); this.dbInstance = this.db.ENABLED ? this.repository.dbServer?.db(this.db.CONNECTION.DB_PREFIX_NAME + '-instances') @@ -52,7 +51,7 @@ export class WAMonitoringService { } private readonly db: Partial = {}; - private readonly redis: Partial = {}; + private readonly redis: Partial = {}; private dbInstance: Db; @@ -213,7 +212,7 @@ export class WAMonitoringService { }); this.logger.verbose('instance files deleted: ' + name); }); - } else if (!this.redis.ENABLED) { + } else if (!this.redis.REDIS.ENABLED && !this.redis.REDIS.SAVE_INSTANCES) { const dir = opendirSync(INSTANCE_DIR, { encoding: 'utf-8' }); for await (const dirent of dir) { if (dirent.isDirectory()) { @@ -248,10 +247,9 @@ export class WAMonitoringService { return; } - if (this.redis.ENABLED) { + if (this.redis.REDIS.ENABLED && this.redis.REDIS.SAVE_INSTANCES) { this.logger.verbose('cleaning up instance in redis: ' + instanceName); - this.cache.reference = instanceName; - await this.cache.delAll(); + await this.cache.delete(instanceName); return; } @@ -304,7 +302,7 @@ export class WAMonitoringService { this.logger.verbose('Loading instances'); try { - if (this.redis.ENABLED) { + if (this.redis.REDIS.ENABLED && this.redis.REDIS.SAVE_INSTANCES) { await this.loadInstancesFromRedis(); } else if (this.db.ENABLED && this.db.SAVE_DATA.INSTANCE) { await this.loadInstancesFromDatabase(); @@ -377,12 +375,11 @@ export class WAMonitoringService { private async loadInstancesFromRedis() { this.logger.verbose('Redis enabled'); - await this.cache.connect(this.redis as Redis); - const keys = await this.cache.getInstanceKeys(); + const keys = await this.cache.keys(); if (keys?.length > 0) { this.logger.verbose('Reading instance keys and setting instances'); - await Promise.all(keys.map((k) => this.setInstance(k.split(':')[1]))); + await Promise.all(keys.map((k) => this.setInstance(k.split(':')[2]))); } else { this.logger.verbose('No instance keys found'); } diff --git a/src/api/services/whatsapp/whatsapp.baileys.service.ts b/src/api/services/whatsapp/whatsapp.baileys.service.ts index ac7520b7..732f82a0 100644 --- a/src/api/services/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/services/whatsapp/whatsapp.baileys.service.ts @@ -55,11 +55,10 @@ import qrcode, { QRCodeToDataURLOptions } from 'qrcode'; import qrcodeTerminal from 'qrcode-terminal'; import sharp from 'sharp'; -import { ConfigService, ConfigSessionPhone, Database, Log, QrCode, Redis } from '../../../config/env.config'; +import { CacheConf, ConfigService, ConfigSessionPhone, Database, Log, QrCode } from '../../../config/env.config'; import { INSTANCE_DIR } from '../../../config/path.config'; import { BadRequestException, InternalServerErrorException, NotFoundException } from '../../../exceptions'; import { dbserver } from '../../../libs/db.connect'; -import { RedisCache } from '../../../libs/redis.client'; import { makeProxyAgent } from '../../../utils/makeProxyAgent'; import { useMultiFileAuthStateDb } from '../../../utils/use-multi-file-auth-state-db'; import { useMultiFileAuthStateRedisDb } from '../../../utils/use-multi-file-auth-state-redis-db'; @@ -126,7 +125,7 @@ export class BaileysStartupService extends WAStartupService { public readonly configService: ConfigService, public readonly eventEmitter: EventEmitter2, public readonly repository: RepositoryBroker, - public readonly cache: RedisCache, + public readonly cache: CacheService, public readonly chatwootCache: CacheService, public readonly messagesLostCache: CacheService, ) { @@ -149,19 +148,23 @@ export class BaileysStartupService extends WAStartupService { public mobile: boolean; private async recoveringMessages() { - setTimeout(async () => { - this.logger.info('Recovering messages'); - this.messagesLostCache.keys().then((keys) => { - keys.forEach(async (key) => { - const message = await this.messagesLostCache.get(key.split(':')[2]); + const cacheConf = this.configService.get('CACHE'); - if (message.messageStubParameters && message.messageStubParameters[0] === 'Message absent from node') { - this.logger.verbose('Message absent from node, retrying to send, key: ' + key.split(':')[2]); - await this.client.sendMessageAck(JSON.parse(message.messageStubParameters[1], BufferJSON.reviver)); - } + if ((cacheConf?.REDIS?.ENABLED && cacheConf?.REDIS?.URI !== '') || cacheConf?.LOCAL?.ENABLED) { + setTimeout(async () => { + this.logger.info('Recovering messages'); + this.messagesLostCache.keys().then((keys) => { + keys.forEach(async (key) => { + const message = await this.messagesLostCache.get(key.split(':')[2]); + + if (message.messageStubParameters && message.messageStubParameters[0] === 'Message absent from node') { + this.logger.verbose('Message absent from node, retrying to send, key: ' + key.split(':')[2]); + await this.client.sendMessageAck(JSON.parse(message.messageStubParameters[1], BufferJSON.reviver)); + } + }); }); - }); - }, 30000); + }, 30000); + } } public get connectionStatus() { @@ -456,12 +459,11 @@ export class BaileysStartupService extends WAStartupService { private async defineAuthState() { this.logger.verbose('Defining auth state'); const db = this.configService.get('DATABASE'); - const redis = this.configService.get('REDIS'); + const cache = this.configService.get('CACHE'); - if (redis?.ENABLED) { - this.logger.verbose('Redis enabled'); - this.cache.reference = this.instance.name; - return await useMultiFileAuthStateRedisDb(this.cache); + if (cache?.REDIS.ENABLED && cache?.REDIS.SAVE_INSTANCES) { + this.logger.info('Redis enabled'); + return await useMultiFileAuthStateRedisDb(this.instance.name, this.cache); } if (db.SAVE_DATA.INSTANCE && db.ENABLED) { diff --git a/src/api/services/whatsapp/whatsapp.business.service.ts b/src/api/services/whatsapp/whatsapp.business.service.ts index 23ae3621..1ed2ddcd 100644 --- a/src/api/services/whatsapp/whatsapp.business.service.ts +++ b/src/api/services/whatsapp/whatsapp.business.service.ts @@ -7,7 +7,6 @@ import { getMIMEType } from 'node-mime-types'; import { ConfigService, Database, WaBusiness } from '../../../config/env.config'; import { BadRequestException, InternalServerErrorException } from '../../../exceptions'; -import { RedisCache } from '../../../libs/redis.client'; import { NumberBusiness } from '../../dto/chat.dto'; import { ContactMessage, @@ -34,7 +33,7 @@ export class BusinessStartupService extends WAStartupService { public readonly configService: ConfigService, public readonly eventEmitter: EventEmitter2, public readonly repository: RepositoryBroker, - public readonly cache: RedisCache, + public readonly cache: CacheService, public readonly chatwootCache: CacheService, public readonly messagesLostCache: CacheService, ) { diff --git a/src/cache/localcache.ts b/src/cache/localcache.ts index 323b0343..54a51d90 100644 --- a/src/cache/localcache.ts +++ b/src/cache/localcache.ts @@ -45,4 +45,17 @@ export class LocalCache implements ICache { buildKey(key: string) { return `${this.module}:${key}`; } + + async hGet() { + console.log('hGet not implemented'); + } + + async hSet() { + console.log('hSet not implemented'); + } + + async hDelete() { + console.log('hDelete not implemented'); + return 0; + } } diff --git a/src/cache/rediscache.ts b/src/cache/rediscache.ts index e010665f..6e209ef1 100644 --- a/src/cache/rediscache.ts +++ b/src/cache/rediscache.ts @@ -1,3 +1,4 @@ +import { BufferJSON } from '@whiskeysockets/baileys'; import { RedisClientType } from 'redis'; import { ICache } from '../api/abstract/abstract.cache'; @@ -14,7 +15,6 @@ export class RedisCache implements ICache { this.conf = this.configService.get('CACHE')?.REDIS; this.client = redisClient.getConnection(); } - async get(key: string): Promise { try { return JSON.parse(await this.client.get(this.buildKey(key))); @@ -23,6 +23,20 @@ export class RedisCache implements ICache { } } + async hGet(key: string, field: string) { + try { + const data = await this.client.hGet(this.buildKey(key), field); + + if (data) { + return JSON.parse(data, BufferJSON.reviver); + } + + return null; + } catch (error) { + this.logger.error(error); + } + } + async set(key: string, value: any, ttl?: number) { try { await this.client.setEx(this.buildKey(key), ttl || this.conf?.TTL, JSON.stringify(value)); @@ -31,6 +45,16 @@ export class RedisCache implements ICache { } } + async hSet(key: string, field: string, value: any) { + try { + const json = JSON.stringify(value, BufferJSON.replacer); + + await this.client.hSet(this.buildKey(key), field, json); + } catch (error) { + this.logger.error(error); + } + } + async has(key: string) { try { return (await this.client.exists(this.buildKey(key))) > 0; @@ -47,6 +71,14 @@ export class RedisCache implements ICache { } } + async hDelete(key: string, field: string) { + try { + return await this.client.hDel(this.buildKey(key), field); + } catch (error) { + this.logger.error(error); + } + } + async deleteAll(appendCriteria?: string) { try { const keys = await this.keys(appendCriteria); diff --git a/src/config/env.config.ts b/src/config/env.config.ts index b3991d08..69b6771a 100644 --- a/src/config/env.config.ts +++ b/src/config/env.config.ts @@ -63,12 +63,6 @@ export type Database = { SAVE_DATA: SaveData; }; -export type Redis = { - ENABLED: boolean; - URI: string; - PREFIX_KEY: string; -}; - export type Rabbitmq = { ENABLED: boolean; MODE: string; // global, single, isolated @@ -153,6 +147,7 @@ export type CacheConfRedis = { URI: string; PREFIX_KEY: string; TTL: number; + SAVE_INSTANCES: boolean; }; export type CacheConfLocal = { ENABLED: boolean; @@ -186,7 +181,6 @@ export interface Env { STORE: StoreConf; CLEAN_STORE: CleanStoreConf; DATABASE: Database; - REDIS: Redis; RABBITMQ: Rabbitmq; SQS: Sqs; WEBSOCKET: Websocket; @@ -280,11 +274,6 @@ export class ConfigService { LABELS: process.env?.DATABASE_SAVE_DATA_LABELS === 'true', }, }, - REDIS: { - ENABLED: process.env?.REDIS_ENABLED === 'true', - URI: process.env.REDIS_URI || '', - PREFIX_KEY: process.env.REDIS_PREFIX_KEY || 'evolution', - }, RABBITMQ: { ENABLED: process.env?.RABBITMQ_ENABLED === 'true', MODE: process.env?.RABBITMQ_MODE || 'isolated', @@ -398,6 +387,7 @@ export class ConfigService { URI: process.env?.CACHE_REDIS_URI || '', PREFIX_KEY: process.env?.CACHE_REDIS_PREFIX_KEY || 'evolution-cache', TTL: Number.parseInt(process.env?.CACHE_REDIS_TTL) || 604800, + SAVE_INSTANCES: process.env?.CACHE_REDIS_SAVE_INSTANCES === 'true', }, LOCAL: { ENABLED: process.env?.CACHE_LOCAL_ENABLED === 'true', diff --git a/src/dev-env.yml b/src/dev-env.yml index f791b721..e7f0fae3 100644 --- a/src/dev-env.yml +++ b/src/dev-env.yml @@ -77,11 +77,6 @@ DATABASE: CONTACTS: false CHATS: false -REDIS: - ENABLED: false - URI: "redis://localhost:6379" - PREFIX_KEY: "evolution" - RABBITMQ: ENABLED: false MODE: "global" @@ -181,8 +176,9 @@ CACHE: REDIS: ENABLED: false URI: "redis://localhost:6379" - PREFIX_KEY: "evolution-cache" + PREFIX_KEY: "evolution" TTL: 604800 + SAVE_INSTANCES: false LOCAL: ENABLED: false TTL: 86400 diff --git a/src/libs/redis.client.ts b/src/libs/redis.client.ts deleted file mode 100644 index 4b3e1991..00000000 --- a/src/libs/redis.client.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { createClient, RedisClientType } from '@redis/client'; -import { BufferJSON } from '@whiskeysockets/baileys'; - -import { Redis } from '../config/env.config'; -import { Logger } from '../config/logger.config'; - -export class RedisCache { - private readonly logger = new Logger(RedisCache.name); - private client: RedisClientType; - private statusConnection = false; - private instanceName: string; - private redisEnv: Redis; - - constructor() { - this.logger.verbose('RedisCache instance created'); - process.on('beforeExit', () => { - this.logger.verbose('RedisCache instance destroyed'); - this.disconnect(); - }); - } - - public set reference(reference: string) { - this.logger.verbose('set reference: ' + reference); - this.instanceName = reference; - } - - public async connect(redisEnv: Redis) { - this.logger.verbose('Connecting to Redis...'); - this.client = createClient({ url: redisEnv.URI }); - this.client.on('error', (err) => this.logger.error('Redis Client Error ' + err)); - - await this.client.connect(); - this.statusConnection = true; - this.redisEnv = redisEnv; - this.logger.verbose(`Connected to ${redisEnv.URI}`); - } - - public async disconnect() { - if (this.statusConnection) { - await this.client.disconnect(); - this.statusConnection = false; - this.logger.verbose('Redis client disconnected'); - } - } - - public async getInstanceKeys(): Promise { - const keys: string[] = []; - try { - this.logger.verbose('Fetching instance keys'); - for await (const key of this.client.scanIterator({ MATCH: `${this.redisEnv.PREFIX_KEY}:*` })) { - keys.push(key); - } - return keys; - } catch (error) { - this.logger.error('Error fetching instance keys ' + error); - throw error; - } - } - - public async keyExists(key?: string) { - try { - const keys = await this.getInstanceKeys(); - const targetKey = key || this.instanceName; - this.logger.verbose('keyExists: ' + targetKey); - return keys.includes(targetKey); - } catch (error) { - return false; - } - } - - public async setData(field: string, data: any) { - try { - this.logger.verbose('setData: ' + field); - const json = JSON.stringify(data, BufferJSON.replacer); - await this.client.hSet(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field, json); - return true; - } catch (error) { - this.logger.error(error); - return false; - } - } - - public async getData(field: string): Promise { - try { - this.logger.verbose('getData: ' + field); - const data = await this.client.hGet(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field); - - if (data) { - this.logger.verbose('getData: ' + field + ' success'); - return JSON.parse(data, BufferJSON.reviver); - } - - this.logger.verbose('getData: ' + field + ' not found'); - return null; - } catch (error) { - this.logger.error(error); - return null; - } - } - - public async removeData(field: string): Promise { - try { - this.logger.verbose('removeData: ' + field); - await this.client.hDel(this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field); - return true; - } catch (error) { - this.logger.error(error); - return false; - } - } - - public async delAll(hash?: string): Promise { - try { - const targetHash = hash || this.redisEnv.PREFIX_KEY + ':' + this.instanceName; - this.logger.verbose('instance delAll: ' + targetHash); - const result = await this.client.del(targetHash); - return !!result; - } catch (error) { - this.logger.error(error); - return false; - } - } -} diff --git a/src/utils/use-multi-file-auth-state-redis-db.ts b/src/utils/use-multi-file-auth-state-redis-db.ts index eb88d678..66bb89ea 100644 --- a/src/utils/use-multi-file-auth-state-redis-db.ts +++ b/src/utils/use-multi-file-auth-state-redis-db.ts @@ -6,10 +6,13 @@ import { SignalDataTypeMap, } from '@whiskeysockets/baileys'; +import { CacheService } from '../api/services/cache.service'; import { Logger } from '../config/logger.config'; -import { RedisCache } from '../libs/redis.client'; -export async function useMultiFileAuthStateRedisDb(cache: RedisCache): Promise<{ +export async function useMultiFileAuthStateRedisDb( + instanceName: string, + cache: CacheService, +): Promise<{ state: AuthenticationState; saveCreds: () => Promise; }> { @@ -17,7 +20,7 @@ export async function useMultiFileAuthStateRedisDb(cache: RedisCache): Promise<{ const writeData = async (data: any, key: string): Promise => { try { - return await cache.setData(key, data); + return await cache.hSet(instanceName, key, data); } catch (error) { return logger.error({ localError: 'writeData', error }); } @@ -25,7 +28,7 @@ export async function useMultiFileAuthStateRedisDb(cache: RedisCache): Promise<{ const readData = async (key: string): Promise => { try { - return await cache.getData(key); + return await cache.hGet(instanceName, key); } catch (error) { logger.error({ localError: 'readData', error }); return; @@ -34,7 +37,7 @@ export async function useMultiFileAuthStateRedisDb(cache: RedisCache): Promise<{ const removeData = async (key: string) => { try { - return await cache.removeData(key); + return await cache.hDelete(instanceName, key); } catch (error) { logger.error({ readData: 'removeData', error }); } From 5e288d57ead11cc9358e8ab45a7d6e867cd3a583 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Thu, 18 Apr 2024 12:12:11 -0300 Subject: [PATCH 37/42] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b103298e..c8bf1ced 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 1.7.3 (develop) +# 1.7.3 (2024-04-18 12:07) ### Fixed * Revert fix audio encoding From a4d1740754b651dbbc0063c8c25e08fb78000804 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Thu, 18 Apr 2024 12:53:55 -0300 Subject: [PATCH 38/42] fix: Adjusts in proxy on fetchAgent --- CHANGELOG.md | 5 +++++ src/api/services/whatsapp/whatsapp.baileys.service.ts | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8bf1ced..215ebec0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 1.7.4 (develop) + +### Fixed +* Adjusts in proxy + # 1.7.3 (2024-04-18 12:07) ### Fixed diff --git a/src/api/services/whatsapp/whatsapp.baileys.service.ts b/src/api/services/whatsapp/whatsapp.baileys.service.ts index 732f82a0..2d011223 100644 --- a/src/api/services/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/services/whatsapp/whatsapp.baileys.service.ts @@ -517,6 +517,7 @@ export class BaileysStartupService extends WAStartupService { const proxyUrl = 'http://' + proxyUrls[rand]; options = { agent: makeProxyAgent(proxyUrl), + fetchAgent: makeProxyAgent(proxyUrl), }; } catch (error) { this.localProxy.enabled = false; @@ -524,6 +525,7 @@ export class BaileysStartupService extends WAStartupService { } else { options = { agent: makeProxyAgent(this.localProxy.proxy), + fetchAgent: makeProxyAgent(this.localProxy.proxy), }; } } @@ -687,6 +689,7 @@ export class BaileysStartupService extends WAStartupService { const proxyUrl = 'http://' + proxyUrls[rand]; options = { agent: makeProxyAgent(proxyUrl), + fetchAgent: makeProxyAgent(proxyUrl), }; } catch (error) { this.localProxy.enabled = false; @@ -694,6 +697,7 @@ export class BaileysStartupService extends WAStartupService { } else { options = { agent: makeProxyAgent(this.localProxy.proxy), + fetchAgent: makeProxyAgent(this.localProxy.proxy), }; } } From 4dd5533202225125f9eb7de5c38ada38f932cfd4 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Thu, 18 Apr 2024 12:54:00 -0300 Subject: [PATCH 39/42] fix: Adjusts in proxy on fetchAgent --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 215ebec0..b9fccb70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # 1.7.4 (develop) ### Fixed -* Adjusts in proxy +* Adjusts in proxy on fetchAgent # 1.7.3 (2024-04-18 12:07) From 7449102d95c680afaa2202be9218b4cc38a97807 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Thu, 18 Apr 2024 17:31:05 -0300 Subject: [PATCH 40/42] fix: Recovering messages lost with redis cache --- .../whatsapp/whatsapp.baileys.service.ts | 2 +- src/cache/cacheengine.ts | 5 + views/manager-wip.hbs | 110 ------------------ 3 files changed, 6 insertions(+), 111 deletions(-) delete mode 100644 views/manager-wip.hbs diff --git a/src/api/services/whatsapp/whatsapp.baileys.service.ts b/src/api/services/whatsapp/whatsapp.baileys.service.ts index 3990c0e3..d8d856a1 100644 --- a/src/api/services/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/services/whatsapp/whatsapp.baileys.service.ts @@ -151,7 +151,7 @@ export class BaileysStartupService extends WAStartupService { const cacheConf = this.configService.get('CACHE'); if ((cacheConf?.REDIS?.ENABLED && cacheConf?.REDIS?.URI !== '') || cacheConf?.LOCAL?.ENABLED) { - setTimeout(async () => { + setInterval(async () => { this.logger.info('Recovering messages'); this.messagesLostCache.keys().then((keys) => { keys.forEach(async (key) => { diff --git a/src/cache/cacheengine.ts b/src/cache/cacheengine.ts index 258a98c2..dd3d18f1 100644 --- a/src/cache/cacheengine.ts +++ b/src/cache/cacheengine.ts @@ -1,8 +1,11 @@ import { ICache } from '../api/abstract/abstract.cache'; import { CacheConf, ConfigService } from '../config/env.config'; +import { Logger } from '../config/logger.config'; import { LocalCache } from './localcache'; import { RedisCache } from './rediscache'; +const logger = new Logger('Redis'); + export class CacheEngine { private engine: ICache; @@ -14,6 +17,8 @@ export class CacheEngine { } else if (cacheConf?.LOCAL?.ENABLED) { this.engine = new LocalCache(configService, module); } + + logger.info(`RedisCache initialized for ${module}`); } public getEngine() { diff --git a/views/manager-wip.hbs b/views/manager-wip.hbs deleted file mode 100644 index 59b0cd0f..00000000 --- a/views/manager-wip.hbs +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - Instance Manager - - - -
- - - - - - - - - - - - - - - - {{#each instances}} - - - - - - - {{/each}} - -
Nome da InstânciaStatusAPI KeyAções
{{this.instance.instanceName}}{{this.instance.status}}{{this.instance.apikey}} - - -
-
- - - - - - - - - - - - \ No newline at end of file From 27f9ae1e5617521a94d7de77a66137a1db9dfb54 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Thu, 18 Apr 2024 17:31:10 -0300 Subject: [PATCH 41/42] fix: Recovering messages lost with redis cache --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9fccb70..a772d5b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### Fixed * Adjusts in proxy on fetchAgent +* Recovering messages lost with redis cache # 1.7.3 (2024-04-18 12:07) From c85619efcf2307b76001c9d957d988b1f986abb9 Mon Sep 17 00:00:00 2001 From: Davidson Gomes Date: Thu, 18 Apr 2024 17:33:09 -0300 Subject: [PATCH 42/42] fix: Recovering messages lost with redis cache --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a772d5b4..fc11ef67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### Fixed * Adjusts in proxy on fetchAgent * Recovering messages lost with redis cache +* Log when init redis cache service # 1.7.3 (2024-04-18 12:07)