diff --git a/CHANGELOG.md b/CHANGELOG.md index 1eb001bd..cad26f43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Correction in decryption of poll votes * Change in the way the api sent and saved the sent messages, now it goes in the messages.upsert event * Fixed cash when sending stickers via url +* Improved how Redis works for instances # 1.1.2 (2023-06-28 13:43) diff --git a/Dockerfile b/Dockerfile index 50f8e36f..04d2ddb2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,7 +54,6 @@ ENV WEBHOOK_EVENTS_QRCODE_UPDATED=$WEBHOOK_EVENTS_QRCODE_UPDATED ENV WEBHOOK_EVENTS_MESSAGES_SET=$WEBHOOK_EVENTS_MESSAGES_SET ENV WEBHOOK_EVENTS_MESSAGES_UPDATE=$WEBHOOK_EVENTS_MESSAGES_UPDATE ENV WEBHOOK_EVENTS_MESSAGES_UPSERT=$WEBHOOK_EVENTS_MESSAGES_UPSERT -ENV WEBHOOK_EVENTS_SEND_MESSAGE=$WEBHOOK_EVENTS_SEND_MESSAGE ENV WEBHOOK_EVENTS_CONTACTS_SET=$WEBHOOK_EVENTS_CONTACTS_SET ENV WEBHOOK_EVENTS_CONTACTS_UPSERT=$WEBHOOK_EVENTS_CONTACTS_UPSERT ENV WEBHOOK_EVENTS_CONTACTS_UPDATE=$WEBHOOK_EVENTS_CONTACTS_UPDATE diff --git a/docker-compose.yaml b/docker-compose.yaml index 8cd8a901..a5ad3040 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -55,7 +55,6 @@ services: - WEBHOOK_EVENTS_MESSAGES_SET=true - WEBHOOK_EVENTS_MESSAGES_UPSERT=true - WEBHOOK_EVENTS_MESSAGES_UPDATE=true - - WEBHOOK_EVENTS_SEND_MESSAGE=true - WEBHOOK_EVENTS_CONTACTS_SET=true - WEBHOOK_EVENTS_CONTACTS_UPSERT=true - WEBHOOK_EVENTS_CONTACTS_UPDATE=true diff --git a/src/config/env.config.ts b/src/config/env.config.ts index 1f09a198..bdb041ab 100644 --- a/src/config/env.config.ts +++ b/src/config/env.config.ts @@ -65,7 +65,6 @@ export type EventsWebhook = { MESSAGES_SET: boolean; MESSAGES_UPSERT: boolean; MESSAGES_UPDATE: boolean; - SEND_MESSAGE: boolean; CONTACTS_SET: boolean; CONTACTS_UPDATE: boolean; CONTACTS_UPSERT: boolean; @@ -221,7 +220,6 @@ export class ConfigService { MESSAGES_SET: process.env?.WEBHOOK_EVENTS_MESSAGES_SET === 'true', MESSAGES_UPSERT: process.env?.WEBHOOK_EVENTS_MESSAGES_UPSERT === 'true', MESSAGES_UPDATE: process.env?.WEBHOOK_EVENTS_MESSAGES_UPDATE === 'true', - SEND_MESSAGE: process.env?.WEBHOOK_EVENTS_SEND_MESSAGE === 'true', CONTACTS_SET: process.env?.WEBHOOK_EVENTS_CONTACTS_SET === 'true', CONTACTS_UPDATE: process.env?.WEBHOOK_EVENTS_CONTACTS_UPDATE === 'true', CONTACTS_UPSERT: process.env?.WEBHOOK_EVENTS_CONTACTS_UPSERT === 'true', diff --git a/src/db/db.connect.ts b/src/db/db.connect.ts index ed51f377..efa64a21 100644 --- a/src/db/db.connect.ts +++ b/src/db/db.connect.ts @@ -5,10 +5,16 @@ import { Logger } from '../config/logger.config'; const logger = new Logger('Db Connection'); const db = configService.get('DATABASE'); -export const dbserver = db.ENABLED - ? mongoose.createConnection(db.CONNECTION.URI, { +export const dbserver = (() => { + if (db.ENABLED) { + const dbs = mongoose.createConnection(db.CONNECTION.URI, { dbName: db.CONNECTION.DB_PREFIX_NAME + '-whatsapp-api', - }) - : null; + }); + logger.info('ON - dbName: ' + dbs['$dbName']); + process.on('beforeExit', () => { + dbserver.destroy(true, (error) => logger.error(error)); + }); -db.ENABLED ? logger.info('ON - dbName: ' + dbserver['$dbName']) : null; + return dbs; + } +})(); diff --git a/src/db/redis.client.ts b/src/db/redis.client.ts index 921bb0b4..c64a0072 100644 --- a/src/db/redis.client.ts +++ b/src/db/redis.client.ts @@ -4,16 +4,29 @@ import { BufferJSON } from '@whiskeysockets/baileys'; import { Redis } from '../config/env.config'; export class RedisCache { - constructor(private readonly redisEnv: Partial, private instanceName?: string) { - this.client = createClient({ url: this.redisEnv.URI }); - - this.client.connect(); + constructor() { + process.on('beforeExit', async () => { + if (this.statusConnection) { + await this.client.disconnect(); + } + }); } + private statusConnection = false; + private instanceName: string; + private redisEnv: Redis; + public set reference(reference: string) { this.instanceName = reference; } + public async connect(redisEnv: Redis) { + this.client = createClient({ url: redisEnv.URI }); + await this.client.connect(); + this.statusConnection = true; + this.redisEnv = redisEnv; + } + private readonly logger = new Logger(RedisCache.name); private client: RedisClientType; @@ -35,6 +48,7 @@ export class RedisCache { public async writeData(field: string, data: any) { try { const json = JSON.stringify(data, BufferJSON.replacer); + return await this.client.hSet( this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field, @@ -51,6 +65,7 @@ export class RedisCache { this.redisEnv.PREFIX_KEY + ':' + this.instanceName, field, ); + if (data) { return JSON.parse(data, BufferJSON.reviver); } @@ -79,20 +94,4 @@ export class RedisCache { this.logger.error(error); } } - - public async closeConnection() { - try { - await this.client.quit(); - } catch (error) { - this.logger.error(error); - } - } - - public async destructor() { - await this.closeConnection(); - } - - public async destroy() { - await this.destructor(); - } } diff --git a/src/dev-env.yml b/src/dev-env.yml index 89b99255..72e002e2 100644 --- a/src/dev-env.yml +++ b/src/dev-env.yml @@ -93,7 +93,6 @@ WEBHOOK: MESSAGES_SET: true MESSAGES_UPSERT: true MESSAGES_UPDATE: true - SEND_MESSAGE: true CONTACTS_SET: true CONTACTS_UPSERT: true CONTACTS_UPDATE: true diff --git a/src/main.ts b/src/main.ts index 0d185580..7d16b5c6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -16,8 +16,6 @@ function initWA() { } function bootstrap() { - initWA(); - const logger = new Logger('SERVER'); const app = express(); @@ -34,8 +32,8 @@ function bootstrap() { methods: [...configService.get('CORS').METHODS], credentials: configService.get('CORS').CREDENTIALS, }), - urlencoded({ extended: true, limit: '50mb' }), - json({ limit: '50mb' }), + urlencoded({ extended: true, limit: '136mb' }), + json({ limit: '136mb' }), compression(), ); @@ -73,6 +71,8 @@ function bootstrap() { logger.log(httpServer.TYPE.toUpperCase() + ' - ON: ' + httpServer.PORT), ); + initWA(); + onUnexpectedError(); } 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 76c54202..c5450ddc 100644 --- a/src/utils/use-multi-file-auth-state-redis-db.ts +++ b/src/utils/use-multi-file-auth-state-redis-db.ts @@ -9,17 +9,12 @@ import { RedisCache } from '../db/redis.client'; import { Logger } from '../config/logger.config'; import { Redis } from '../config/env.config'; -export async function useMultiFileAuthStateRedisDb( - redisEnv: Partial, - instanceName: string, -): Promise<{ +export async function useMultiFileAuthStateRedisDb(cache: RedisCache): Promise<{ state: AuthenticationState; saveCreds: () => Promise; }> { const logger = new Logger(useMultiFileAuthStateRedisDb.name); - const cache = new RedisCache(redisEnv, instanceName); - const writeData = async (data: any, key: string): Promise => { try { return await cache.writeData(key, data); diff --git a/src/validate/validate.schema.ts b/src/validate/validate.schema.ts index bab03206..cb2ddf12 100644 --- a/src/validate/validate.schema.ts +++ b/src/validate/validate.schema.ts @@ -39,7 +39,6 @@ export const instanceNameSchema: JSONSchema7 = { 'MESSAGES_SET', 'MESSAGES_UPSERT', 'MESSAGES_UPDATE', - 'SEND_MESSAGE', 'CONTACTS_SET', 'CONTACTS_UPSERT', 'CONTACTS_UPDATE', @@ -802,7 +801,6 @@ export const webhookSchema: JSONSchema7 = { 'MESSAGES_SET', 'MESSAGES_UPSERT', 'MESSAGES_UPDATE', - 'SEND_MESSAGE', 'CONTACTS_SET', 'CONTACTS_UPSERT', 'CONTACTS_UPDATE', diff --git a/src/whatsapp/controllers/instance.controller.ts b/src/whatsapp/controllers/instance.controller.ts index 195f411d..293fa411 100644 --- a/src/whatsapp/controllers/instance.controller.ts +++ b/src/whatsapp/controllers/instance.controller.ts @@ -10,6 +10,7 @@ import { WAStartupService } from '../services/whatsapp.service'; import { WebhookService } from '../services/webhook.service'; import { Logger } from '../../config/logger.config'; import { wa } from '../types/wa.types'; +import { RedisCache } from '../../db/redis.client'; export class InstanceController { constructor( @@ -19,6 +20,7 @@ export class InstanceController { private readonly eventEmitter: EventEmitter2, private readonly authService: AuthService, private readonly webhookService: WebhookService, + private readonly cache: RedisCache, ) {} private readonly logger = new Logger(InstanceController.name); @@ -47,6 +49,7 @@ export class InstanceController { this.configService, this.eventEmitter, this.repository, + this.cache, ); instance.instanceName = instanceName; this.waMonitor.waInstances[instance.instanceName] = instance; @@ -92,6 +95,7 @@ export class InstanceController { this.configService, this.eventEmitter, this.repository, + this.cache, ); instance.instanceName = instanceName; this.waMonitor.waInstances[instance.instanceName] = instance; @@ -171,6 +175,7 @@ export class InstanceController { this.configService, this.eventEmitter, this.repository, + this.cache, ); instance.instanceName = instanceName; diff --git a/src/whatsapp/guards/instance.guard.ts b/src/whatsapp/guards/instance.guard.ts index b9a1dfce..9e7a0e4b 100644 --- a/src/whatsapp/guards/instance.guard.ts +++ b/src/whatsapp/guards/instance.guard.ts @@ -9,7 +9,7 @@ import { NotFoundException, } from '../../exceptions'; import { InstanceDto } from '../dto/instance.dto'; -import { waMonitor } from '../whatsapp.module'; +import { cache, waMonitor } from '../whatsapp.module'; import { Database, Redis, configService } from '../../config/env.config'; import { RedisCache } from '../../db/redis.client'; @@ -20,7 +20,6 @@ async function getInstance(instanceName: string) { const exists = !!waMonitor.waInstances[instanceName]; if (redisConf.ENABLED) { - const cache = new RedisCache(redisConf, instanceName); const keyExists = await cache.keyExists(); return exists || keyExists; } diff --git a/src/whatsapp/services/monitor.service.ts b/src/whatsapp/services/monitor.service.ts index 821340fe..8feb86ec 100644 --- a/src/whatsapp/services/monitor.service.ts +++ b/src/whatsapp/services/monitor.service.ts @@ -14,14 +14,15 @@ import { import { RepositoryBroker } from '../repository/repository.manager'; import { NotFoundException } from '../../exceptions'; import { Db } from 'mongodb'; -import { RedisCache } from '../../db/redis.client'; import { initInstance } from '../whatsapp.module'; +import { RedisCache } from '../../db/redis.client'; export class WAMonitoringService { constructor( private readonly eventEmitter: EventEmitter2, private readonly configService: ConfigService, private readonly repository: RepositoryBroker, + private readonly cache: RedisCache, ) { this.removeInstance(); this.noConnection(); @@ -33,15 +34,12 @@ export class WAMonitoringService { this.dbInstance = this.db.ENABLED ? this.repository.dbServer?.db(this.db.CONNECTION.DB_PREFIX_NAME + '-instances') : undefined; - - this.redisCache = this.redis.ENABLED ? new RedisCache(this.redis) : undefined; } private readonly db: Partial = {}; private readonly redis: Partial = {}; private dbInstance: Db; - private redisCache: RedisCache; private readonly logger = new Logger(WAMonitoringService.name); public readonly waInstances: Record = {}; @@ -144,6 +142,7 @@ export class WAMonitoringService { ], }); }); + } else if (this.redis.ENABLED) { } else { const dir = opendirSync(INSTANCE_DIR, { encoding: 'utf-8' }); for await (const dirent of dir) { @@ -176,8 +175,8 @@ export class WAMonitoringService { } if (this.redis.ENABLED) { - this.redisCache.reference = instanceName; - await this.redisCache.delAll(); + this.cache.reference = instanceName; + await this.cache.delAll(); return; } rmSync(join(INSTANCE_DIR, instanceName), { recursive: true, force: true }); @@ -189,6 +188,7 @@ export class WAMonitoringService { this.configService, this.eventEmitter, this.repository, + this.cache, ); instance.instanceName = name; await instance.connectToWhatsapp(); @@ -197,7 +197,8 @@ export class WAMonitoringService { try { if (this.redis.ENABLED) { - const keys = await this.redisCache.instanceKeys(); + await this.cache.connect(this.redis as Redis); + const keys = await this.cache.instanceKeys(); if (keys?.length > 0) { keys.forEach(async (k) => await set(k.split(':')[1])); } else { diff --git a/src/whatsapp/services/whatsapp.service.ts b/src/whatsapp/services/whatsapp.service.ts index fb63057c..91329978 100644 --- a/src/whatsapp/services/whatsapp.service.ts +++ b/src/whatsapp/services/whatsapp.service.ts @@ -115,12 +115,14 @@ import { dbserver } from '../../db/db.connect'; import NodeCache from 'node-cache'; import { useMultiFileAuthStateRedisDb } from '../../utils/use-multi-file-auth-state-redis-db'; import sharp from 'sharp'; +import { RedisCache } from '../../db/redis.client'; export class WAStartupService { constructor( private readonly configService: ConfigService, private readonly eventEmitter: EventEmitter2, private readonly repository: RepositoryBroker, + private readonly cache: RedisCache, ) { this.cleanStore(); this.instance.qrcode = { count: 0 }; @@ -478,7 +480,8 @@ export class WAStartupService { const redis = this.configService.get('REDIS'); if (redis?.ENABLED) { - return await useMultiFileAuthStateRedisDb(redis, this.instance.name); + this.cache.reference = this.instance.name; + return await useMultiFileAuthStateRedisDb(this.cache); } if (db.SAVE_DATA.INSTANCE && db.ENABLED) { diff --git a/src/whatsapp/types/wa.types.ts b/src/whatsapp/types/wa.types.ts index 1686f031..293a52f8 100644 --- a/src/whatsapp/types/wa.types.ts +++ b/src/whatsapp/types/wa.types.ts @@ -9,7 +9,6 @@ export enum Events { MESSAGES_SET = 'messages.set', MESSAGES_UPSERT = 'messages.upsert', MESSAGES_UPDATE = 'messages.update', - SEND_MESSAGE = 'send.message', CONTACTS_SET = 'contacts.set', CONTACTS_UPSERT = 'contacts.upsert', CONTACTS_UPDATE = 'contacts.update', diff --git a/src/whatsapp/whatsapp.module.ts b/src/whatsapp/whatsapp.module.ts index f1cb5444..e971da78 100644 --- a/src/whatsapp/whatsapp.module.ts +++ b/src/whatsapp/whatsapp.module.ts @@ -29,6 +29,7 @@ import { AuthRepository } from './repository/auth.repository'; import { WAStartupService } from './services/whatsapp.service'; import { delay } from '@whiskeysockets/baileys'; import { Events } from './types/wa.types'; +import { RedisCache } from '../db/redis.client'; const logger = new Logger('WA MODULE'); @@ -49,7 +50,14 @@ export const repository = new RepositoryBroker( dbserver?.getClient(), ); -export const waMonitor = new WAMonitoringService(eventEmitter, configService, repository); +export const cache = new RedisCache(); + +export const waMonitor = new WAMonitoringService( + eventEmitter, + configService, + repository, + cache, +); const authService = new AuthService(configService, waMonitor, repository); @@ -64,6 +72,7 @@ export const instanceController = new InstanceController( eventEmitter, authService, webhookService, + cache, ); export const viewsController = new ViewsController(waMonitor, configService); export const sendMessageController = new SendMessageController(waMonitor); @@ -71,7 +80,7 @@ export const chatController = new ChatController(waMonitor); export const groupController = new GroupController(waMonitor); export async function initInstance() { - const instance = new WAStartupService(configService, eventEmitter, repository); + const instance = new WAStartupService(configService, eventEmitter, repository, cache); const mode = configService.get('AUTHENTICATION').INSTANCE.MODE;