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..8fc7a681 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( @@ -1046,10 +1063,18 @@ 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)); + + 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 +1273,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 +1503,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())} `,