From 9e6ffd26a5c9884a93759c0af6e97dda79ee0af7 Mon Sep 17 00:00:00 2001 From: jrcleber Date: Fri, 31 May 2024 20:15:15 +0000 Subject: [PATCH] ajuste de compatibilidade com o worker - #130 --- package.json | 5 +- src/app.module.ts | 21 ++++---- src/cache/redis.ts | 52 ------------------- src/config/env.config.ts | 16 +++--- src/guards/instance.guard.ts | 16 +++--- .../controllers/instance.controller.ts | 6 +-- src/whatsapp/services/monitor.service.ts | 38 +++++++------- src/whatsapp/services/whatsapp.service.ts | 33 +++++------- tsconfig.json | 2 +- 9 files changed, 66 insertions(+), 123 deletions(-) delete mode 100644 src/cache/redis.ts diff --git a/package.json b/package.json index cb9664b2..1ae84856 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "dayjs": "^1.11.11", "dotenv": "^16.3.1", "eventemitter2": "^6.4.9", - "express": "^4.18.2", + "express": "^4.19.2", "express-async-errors": "^3.1.1", "express-session": "^1.17.3", "hbs": "^4.2.0", @@ -69,7 +69,6 @@ "pino-pretty": "^11.0.0", "qrcode": "^1.5.1", "qrcode-terminal": "^0.12.0", - "redis": "^4.6.14", "uuid": "^9.0.0", "yamljs": "^0.3.0" }, @@ -96,6 +95,6 @@ "prettier": "^3.1.0", "prisma": "^5.14.0", "ts-node-dev": "^2.0.0", - "typescript": "^5.3.2" + "typescript": "^5.4.5" } } diff --git a/src/app.module.ts b/src/app.module.ts index c3c5f26e..c8bcacf1 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -43,7 +43,6 @@ import express, { import { Logger } from './config/logger.config'; import { S3Service } from './integrations/minio/s3.service'; import { Repository } from './repository/repository.service'; -import { RedisCache } from './cache/redis'; import { ConfigService } from './config/env.config'; import { TypebotService } from './integrations/typebot/typebot.service'; import { eventEmitter } from './config/event.config'; @@ -73,6 +72,7 @@ import { JwtGuard } from './guards/auth.guard'; import { ErrorMiddle } from './middle/error.middle'; import 'express-async-errors'; import { docsRouter } from './config/scala.config'; +import { ProviderFiles } from './provider/sessions'; export function describeRoutes( rootPath: string, @@ -95,6 +95,7 @@ export function describeRoutes( export enum HttpStatus { OK = 200, CREATED = 201, + NO_CONTENT = 202, NOT_FOUND = 404, FORBIDDEN = 403, BAD_REQUEST = 400, @@ -109,19 +110,19 @@ export async function AppModule(context: Map) { const logger = new Logger(configService, 'APP MODULE'); - const redisCache = new RedisCache(configService); - logger.info('Cache:Redis - ON'); - await redisCache.onModuleInit(); + const providerFiles = new ProviderFiles(configService); + await providerFiles.onModuleInit(); + logger.info('Provider:Files - ON'); const repository = new Repository(configService); - logger.info('Repository - ON'); await repository.onModuleInit(); + logger.info('Repository - ON'); const waMonitor = new WAMonitoringService( eventEmitter, configService, repository, - redisCache, + providerFiles, ); logger.info('WAMonitoringService - ON'); @@ -134,7 +135,7 @@ export async function AppModule(context: Map) { async (req: Request, res: Response, next: NextFunction) => await new JwtGuard(configService).canActivate(req, res, next), async (req: Request, res: Response, next: NextFunction) => - await new InstanceGuard(waMonitor, redisCache).canActivate(req, res, next), + await new InstanceGuard(waMonitor, providerFiles).canActivate(req, res, next), ]; logger.info('Middlewares - ON'); @@ -149,7 +150,7 @@ export async function AppModule(context: Map) { repository, eventEmitter, instanceService, - redisCache, + providerFiles, ); logger.info('InstanceController - ON'); @@ -221,12 +222,12 @@ export async function AppModule(context: Map) { app['close'] = async () => { await repository.onModuleDestroy(); - await redisCache.onModuleDestroy(); + await providerFiles.onModuleDestroy(); }; context.set('app', app); context.set('module:logger', logger); context.set('module:repository', repository); - context.set('module:redisCache', redisCache); + context.set('module:redisCache', providerFiles); context.set('module:config', configService); } diff --git a/src/cache/redis.ts b/src/cache/redis.ts deleted file mode 100644 index b718a79d..00000000 --- a/src/cache/redis.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { RedisClientType, createClient } from 'redis'; -import { ConfigService, Redis } from '../config/env.config'; -import { Logger } from '../config/logger.config'; - -export class RedisCache { - constructor(private readonly configService: ConfigService) {} - - private readonly logger = new Logger(this.configService, RedisCache.name); - - private _client: RedisClientType; - - public get client() { - return this._client; - } - - public get isConnected() { - return this.client?.isOpen; - } - - private readonly config = Object.freeze(this.configService.get('REDIS')); - - public async onModuleInit() { - if (this.config.ENABLED) { - this._client = createClient({ - url: this.config.URI, - name: 'codechat_v1', - }); - await this.client.connect(); - this.logger.info('Redis:Connected - ON'); - } - } - - public async onModuleDestroy() { - await this.client?.disconnect(); - this.logger.warn('Cache:Redis - OFF'); - } - - public keys(pattern: string) { - return new Promise((resolve, reject) => { - resolve(this.client.keys(pattern)); - reject(new Error('Error on get keys')); - }); - } - - public async del(key: string) { - try { - return await this.client.del(`${this.config.PREFIX_KEY}:${key}`); - } catch (error) { - this.logger.error({ localError: 'dell', error }); - } - } -} diff --git a/src/config/env.config.ts b/src/config/env.config.ts index 45e04cc5..6710f8e7 100644 --- a/src/config/env.config.ts +++ b/src/config/env.config.ts @@ -87,10 +87,10 @@ export type Database = { DB_OPTIONS: DBOptions; }; -export type Redis = { +export type ProviderSession = { ENABLED: boolean; - URI: string; - PREFIX_KEY: string; + HOST: string; + PORT: string; }; export type QrCode = { @@ -111,7 +111,7 @@ export interface Env { SERVER: HttpServer; STORE: StoreConf; DATABASE: Database; - REDIS: Redis; + PROVIDER: ProviderSession; LOG: Log; INSTANCE_EXPIRATION_TIME: InstanceExpirationTime; GLOBAL_WEBHOOK: GlobalWebhook; @@ -176,10 +176,10 @@ export class ConfigService { LOGS: process.env?.DATABASE_SAVE_LOGS === 'true', }, }, - REDIS: { - ENABLED: process.env?.REDIS_ENABLED === 'true', - URI: process.env.REDIS_URI, - PREFIX_KEY: process.env?.REDIS_PREFIX || 'codechat_v1', + PROVIDER: { + ENABLED: process.env?.PROVIDER_ENABLED === 'true', + HOST: process.env.PROVIDER_HOST, + PORT: process.env?.PROVIDER_PORT || '5656', }, LOG: { LEVEL: process.env?.LOG_LEVEL.split('|') as LogLevel[], diff --git a/src/guards/instance.guard.ts b/src/guards/instance.guard.ts index 4a6241fc..d61283dc 100644 --- a/src/guards/instance.guard.ts +++ b/src/guards/instance.guard.ts @@ -48,22 +48,22 @@ import { INSTANCE_DIR } from '../config/path.config'; import { BadRequestException, ForbiddenException } from '../exceptions'; import { InstanceDto } from '../whatsapp/dto/instance.dto'; import { WAMonitoringService } from '../whatsapp/services/monitor.service'; -import { RedisCache } from '../cache/redis'; import 'express-async-errors'; +import { ProviderFiles } from '../provider/sessions'; async function fetchInstanceFromCache( instanceName: string, waMonitor: WAMonitoringService, - redisCache: RedisCache, + providerFiles: ProviderFiles, ) { try { const exists = !!waMonitor.waInstances.get(instanceName); if (exists) { return exists; } - if (redisCache?.isConnected) { - const keyExists = await redisCache.keys('*'); - return keyExists[0]?.includes(instanceName); + if (providerFiles.isEnabled) { + const [keyExists] = await providerFiles.allInstances(); + return keyExists?.data.includes(instanceName); } return existsSync(join(INSTANCE_DIR, instanceName)); @@ -76,7 +76,7 @@ async function fetchInstanceFromCache( export class InstanceGuard { constructor( private readonly waMonitor: WAMonitoringService, - private readonly redisCache: RedisCache, + private readonly providerFiles: ProviderFiles, ) {} async canActivate(req: Request, _: Response, next: NextFunction) { if (req.originalUrl.includes('/instance/create')) { @@ -85,7 +85,7 @@ export class InstanceGuard { await fetchInstanceFromCache( instance.instanceName, this.waMonitor, - this.redisCache, + this.providerFiles, ) ) { throw new ForbiddenException( @@ -118,7 +118,7 @@ export class InstanceGuard { const fetch = await fetchInstanceFromCache( param.instanceName, this.waMonitor, - this.redisCache, + this.providerFiles, ); if (!fetch) { diff --git a/src/whatsapp/controllers/instance.controller.ts b/src/whatsapp/controllers/instance.controller.ts index ea44cb20..822167c8 100644 --- a/src/whatsapp/controllers/instance.controller.ts +++ b/src/whatsapp/controllers/instance.controller.ts @@ -54,7 +54,7 @@ import { Repository } from '../../repository/repository.service'; import { InstanceService, OldToken } from '../services/instance.service'; import { WAStartupService } from '../services/whatsapp.service'; import { isString } from 'class-validator'; -import { RedisCache } from '../../cache/redis'; +import { ProviderFiles } from '../../provider/sessions'; export class InstanceController { constructor( @@ -63,7 +63,7 @@ export class InstanceController { private readonly repository: Repository, private readonly eventEmitter: EventEmitter2, private readonly instanceService: InstanceService, - private readonly redisCache: RedisCache, + private readonly providerFiles: ProviderFiles, ) {} private readonly logger = new Logger(this.configService, InstanceController.name); @@ -119,7 +119,7 @@ export class InstanceController { this.configService, this.eventEmitter, this.repository, - this.redisCache, + this.providerFiles, ); await instance.setInstanceName(instanceName); this.waMonitor.waInstances.set(instance.instanceName, instance); diff --git a/src/whatsapp/services/monitor.service.ts b/src/whatsapp/services/monitor.service.ts index 8ecfbd3e..aa80ca8b 100644 --- a/src/whatsapp/services/monitor.service.ts +++ b/src/whatsapp/services/monitor.service.ts @@ -47,32 +47,34 @@ import { ConfigService, Database, InstanceExpirationTime, - Redis, + ProviderSession, } from '../../config/env.config'; import { Repository } from '../../repository/repository.service'; -import { RedisCache } from '../../cache/redis'; import { Instance } from '@prisma/client'; +import { ProviderFiles } from '../../provider/sessions'; export class WAMonitoringService { constructor( private readonly eventEmitter: EventEmitter2, private readonly configService: ConfigService, private readonly repository: Repository, - private readonly redisCache: RedisCache, + private readonly providerFiles: ProviderFiles, ) { this.removeInstance(); this.noConnection(); Object.assign(this.db, configService.get('DATABASE')); - Object.assign(this.redis, configService.get('REDIS')); } private readonly db: Partial = {}; - private readonly redis: Partial = {}; private readonly logger = new Logger(this.configService, WAMonitoringService.name); public readonly waInstances = new Map(); + private readonly providerSession = Object.freeze( + this.configService.get('PROVIDER'), + ); + public delInstanceTime(instance: string) { const time = this.configService.get( 'INSTANCE_EXPIRATION_TIME', @@ -90,12 +92,12 @@ export class WAMonitoringService { } } - private async cleaningUp({ name, id }: Instance) { + private async cleaningUp({ name }: Instance) { this.waInstances.get(name)?.client?.ev.removeAllListeners('connection.update'); this.waInstances.get(name)?.client?.ev.flush(); this.waInstances.delete(name); - if (this.redis?.ENABLED) { - await this.redisCache.del(`${id}:${name}`); + if (this.providerSession?.ENABLED) { + await this.providerFiles.removeSession(name); } else { rmSync(join(INSTANCE_DIR, name), { recursive: true, force: true }); } @@ -120,7 +122,7 @@ export class WAMonitoringService { this.configService, this.eventEmitter, this.repository, - this.redisCache, + this.providerFiles, ); await init.setInstanceName(name); await init.connectToWhatsapp(); @@ -128,14 +130,12 @@ export class WAMonitoringService { }; try { - if (this.redis.ENABLED) { - const keys = await this.redisCache.keys('*'); - if (keys?.length > 0) { - keys.forEach(async (key) => { - const [prefix, id, name] = key.split(':'); - await set(name); - }); - } + if (this.providerSession.ENABLED) { + const [instances] = await this.providerFiles.allInstances(); + instances.data.forEach(async (name: string) => { + await set(name); + }); + return; } @@ -161,7 +161,9 @@ export class WAMonitoringService { private removeInstance() { this.eventEmitter.on('remove.instance', async (instance: Instance) => { try { - await this.waInstances.get(instance.name)?.client?.logout(); + if (!instance?.name) { + return; + } this.waInstances .get(instance.name) ?.client?.ev.removeAllListeners('connection.update'); diff --git a/src/whatsapp/services/whatsapp.service.ts b/src/whatsapp/services/whatsapp.service.ts index 615069d9..bd35b6f8 100644 --- a/src/whatsapp/services/whatsapp.service.ts +++ b/src/whatsapp/services/whatsapp.service.ts @@ -74,7 +74,7 @@ import { Database, GlobalWebhook, QrCode, - Redis, + ProviderSession, } from '../../config/env.config'; import { Logger } from '../../config/logger.config'; import { INSTANCE_DIR } from '../../config/path.config'; @@ -123,16 +123,16 @@ import Long from 'long'; import NodeCache from 'node-cache'; import { AuthState, - AuthStateRedis, -} from '../../utils/use-multi-file-auth-state-redis-db'; + AuthStateProvider, +} from '../../utils/use-multi-file-auth-state-provider-files'; import mime from 'mime-types'; import { Instance, Webhook } from '@prisma/client'; import { WebhookEvents, WebhookEventsEnum, WebhookEventsType } from '../dto/webhook.dto'; import { Query, Repository } from '../../repository/repository.service'; import PrismType from '@prisma/client'; import * as s3Service from '../../integrations/minio/minio.utils'; -import { RedisCache } from '../../cache/redis'; import { TypebotSessionService } from '../../integrations/typebot/typebot.service'; +import { ProviderFiles } from '../../provider/sessions'; type InstanceQrCode = { count: number; @@ -150,9 +150,12 @@ export class WAStartupService { private readonly configService: ConfigService, private readonly eventEmitter: EventEmitter2, private readonly repository: Repository, - private readonly redisCache: RedisCache, + private readonly providerFiles: ProviderFiles, ) { - this.authStateRedis = new AuthStateRedis(this.configService, this.redisCache); + this.authStateProvider = new AuthStateProvider( + this.configService, + this.providerFiles, + ); } private readonly logger = new Logger(this.configService, WAStartupService.name); @@ -172,7 +175,7 @@ export class WAStartupService { private endSession = false; public client: WASocket; private authState: Partial = {}; - private authStateRedis: AuthStateRedis; + private authStateProvider: AuthStateProvider; public async setInstanceName(name: string) { const i = await this.repository.instance.findUnique({ @@ -477,12 +480,10 @@ export class WAStartupService { } private async defineAuthState() { - const redis = this.configService.get('REDIS'); + const provider = this.configService.get('PROVIDER'); - if (redis?.ENABLED) { - return await this.authStateRedis.authStateRedisDb( - `${this.instance.id}:${this.instance.name}`, - ); + if (provider?.ENABLED) { + return await this.authStateProvider.authStateProvider(this.instance.name); } return await useMultiFileAuthState(join(INSTANCE_DIR, this.instance.name)); @@ -678,14 +679,6 @@ export class WAStartupService { } } - private getEditedMessage(data: proto.IWebMessageInfo) { - if (data.message?.protocolMessage?.editedMessage) { - data.message = data.message?.protocolMessage?.editedMessage; - } - - return data.message; - } - private readonly messageHandle = { 'messaging-history.set': async ({ messages, diff --git a/tsconfig.json b/tsconfig.json index 4183b6ff..984c8d85 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,5 +18,5 @@ "incremental": true, "noImplicitAny": false, }, - "exclude": ["node_modules", "./test", "./dist", "./prisma"] + "exclude": ["node_modules", "./test", "./dist", "./prisma", "./workers/session"] } \ No newline at end of file