feat: agregar Dockerfile y configuración Docker
This commit is contained in:
parent
e774dec930
commit
abc369bd04
8 changed files with 238 additions and 32 deletions
13
.env
13
.env
|
|
@ -1,12 +1,19 @@
|
||||||
# API Principal
|
# API Principal
|
||||||
API_URL=http://localhost:3000/v1
|
API_URL=http://192.168.1.100:3000/v1
|
||||||
|
# API_URL=http://localhost:3000/v1
|
||||||
|
|
||||||
# API KEY para conectar con el API principal
|
# API KEY para conectar con el API principal
|
||||||
WORKER_KEY=885E2E87-6B8C-4CBC-93D8-D07CC5A13158
|
WORKER_KEY=885E2E87-6B8C-4CBC-93D8-D07CC5A13158
|
||||||
|
|
||||||
# OpenWA
|
# OpenWA
|
||||||
OPENWA_URL=http://localhost:2785
|
# OPENWA_URL=http://localhost:2785
|
||||||
OPENWA_API_KEY=owa_k1_e2a44d3144f5870553ebdb52dfe373d89fd056f7fb90ef17ce14ca3f889f4bcc
|
OPENWA_URL=https://whatsapp.alphaxdev.cc
|
||||||
|
|
||||||
|
# Local
|
||||||
|
# OPENWA_API_KEY=owa_k1_e2a44d3144f5870553ebdb52dfe373d89fd056f7fb90ef17ce14ca3f889f4bcc
|
||||||
|
|
||||||
|
# SERVER alphaxdev.cc
|
||||||
|
OPENWA_API_KEY=owa_k1_f3e283de607aabd68462cd449c980ab18c4f1c6286bdeea3f5e64fd86339728a
|
||||||
|
|
||||||
# Configuración del worker
|
# Configuración del worker
|
||||||
WORKER_INTERVAL=3000
|
WORKER_INTERVAL=3000
|
||||||
|
|
|
||||||
25
.env.example
25
.env.example
|
|
@ -1,17 +1,22 @@
|
||||||
cd ~/docker/OpenWA
|
|
||||||
cp .env.example .env
|
|
||||||
|
|
||||||
# API Principal
|
# API Principal
|
||||||
API_URL=http://localhost:3000/v1
|
API_URL=http://192.168.1.100:3000/v1
|
||||||
|
# API_URL=http://localhost:3000/v1
|
||||||
|
|
||||||
# API KEY para conectar con el API principal
|
# API KEY para conectar con el API principal
|
||||||
WORKER_KEY=uuid-generado-aqui
|
WORKER_KEY=885E2E87-6B8C-4CBC-93D8-D07CC5A13158
|
||||||
|
|
||||||
# OpenWA
|
# OpenWA
|
||||||
OPENWA_URL=http://localhost:2785
|
# OPENWA_URL=http://localhost:2785
|
||||||
OPENWA_API_KEY=tu-api-key-de-openwa
|
OPENWA_URL=https://whatsapp.alphaxdev.cc
|
||||||
|
|
||||||
|
# Local
|
||||||
|
# OPENWA_API_KEY=owa_k1_e2a44d3144f5870553ebdb52dfe373d89....
|
||||||
|
|
||||||
|
# SERVER alphaxdev.cc
|
||||||
|
OPENWA_API_KEY=owa_k1_f3e283de607aabd68462cd449c980ab18c4f...
|
||||||
|
|
||||||
# Configuración del worker
|
# Configuración del worker
|
||||||
WORKER_INTERVAL=30000
|
WORKER_INTERVAL=3000
|
||||||
WORKER_LIMIT=5
|
PORT=3001
|
||||||
PORT=3003
|
|
||||||
|
cp .env.example .env
|
||||||
83
.gitignore
vendored
83
.gitignore
vendored
|
|
@ -1 +1,84 @@
|
||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
node_modules
|
node_modules
|
||||||
|
.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# Build output
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
.next/
|
||||||
|
out/
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# OS files
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*.sublime-workspace
|
||||||
|
*.sublime-project
|
||||||
|
|
||||||
|
# Data and storage
|
||||||
|
data/
|
||||||
|
media/
|
||||||
|
!src/**/media/
|
||||||
|
uploads/
|
||||||
|
.wwebjs_auth/
|
||||||
|
.wwebjs_cache/
|
||||||
|
|
||||||
|
# Database
|
||||||
|
*.db
|
||||||
|
*.sqlite
|
||||||
|
*.sqlite3
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
.docker/
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
|
*.temp
|
||||||
|
|
||||||
|
# Git worktrees
|
||||||
|
.worktrees/
|
||||||
|
|
||||||
|
# AI Agents
|
||||||
|
.playwright-mcp/
|
||||||
|
.remember/
|
||||||
|
.agent/
|
||||||
|
.claude/
|
||||||
|
.zcode/
|
||||||
|
.zcode-worktrees/
|
||||||
|
docs/plans/
|
||||||
|
docs/superpowers/
|
||||||
|
CLAUDE.md
|
||||||
|
_docs/
|
||||||
|
.superpowers/
|
||||||
|
# TypeScript incremental build cache (tsc writes this at repo root under the TS6 build config)
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
|
||||||
5
dist/worker/worker.service.d.ts
vendored
5
dist/worker/worker.service.d.ts
vendored
|
|
@ -11,6 +11,9 @@ export declare class WorkerService implements OnModuleInit, OnModuleDestroy {
|
||||||
private readonly openwaUrl;
|
private readonly openwaUrl;
|
||||||
private readonly openwaApiKey;
|
private readonly openwaApiKey;
|
||||||
private readonly intervalMs;
|
private readonly intervalMs;
|
||||||
|
private sesionesCache;
|
||||||
|
private sesionesCacheTimestamp;
|
||||||
|
private readonly SESIONES_CACHE_TTL;
|
||||||
constructor(config: ConfigService, http: HttpService);
|
constructor(config: ConfigService, http: HttpService);
|
||||||
onModuleInit(): void;
|
onModuleInit(): void;
|
||||||
onModuleDestroy(): void;
|
onModuleDestroy(): void;
|
||||||
|
|
@ -18,6 +21,8 @@ export declare class WorkerService implements OnModuleInit, OnModuleDestroy {
|
||||||
private procesarCiclo;
|
private procesarCiclo;
|
||||||
private procesar;
|
private procesar;
|
||||||
private obtenerPendiente;
|
private obtenerPendiente;
|
||||||
|
private obtenerSesionesDisponibles;
|
||||||
|
private obtenerSesionRandom;
|
||||||
private procesarMensaje;
|
private procesarMensaje;
|
||||||
private calcularDelayEscritura;
|
private calcularDelayEscritura;
|
||||||
private calcularDelayEntreMensajes;
|
private calcularDelayEntreMensajes;
|
||||||
|
|
|
||||||
63
dist/worker/worker.service.js
vendored
63
dist/worker/worker.service.js
vendored
|
|
@ -22,6 +22,9 @@ let WorkerService = WorkerService_1 = class WorkerService {
|
||||||
openwaUrl;
|
openwaUrl;
|
||||||
openwaApiKey;
|
openwaApiKey;
|
||||||
intervalMs;
|
intervalMs;
|
||||||
|
sesionesCache = [];
|
||||||
|
sesionesCacheTimestamp = 0;
|
||||||
|
SESIONES_CACHE_TTL = 5 * 60 * 1000;
|
||||||
constructor(config, http) {
|
constructor(config, http) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.http = http;
|
this.http = http;
|
||||||
|
|
@ -75,13 +78,46 @@ let WorkerService = WorkerService_1 = class WorkerService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async obtenerSesionesDisponibles() {
|
||||||
|
const ahora = Date.now();
|
||||||
|
if (this.sesionesCache.length > 0 && ahora - this.sesionesCacheTimestamp < this.SESIONES_CACHE_TTL) {
|
||||||
|
return this.sesionesCache;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const response = await firstValueFrom(this.http.get(`${this.openwaUrl}/api/sessions`, {
|
||||||
|
headers: { 'X-API-Key': this.openwaApiKey },
|
||||||
|
}));
|
||||||
|
const todas = response.data;
|
||||||
|
this.sesionesCache = todas
|
||||||
|
.filter((s) => s.status === 'ready')
|
||||||
|
.map((s) => ({ id: s.id, name: s.name, phone: s.phone }));
|
||||||
|
this.sesionesCacheTimestamp = ahora;
|
||||||
|
this.logger.log(`[${this.timestamp()}] 🔄 Sesiones OpenWA actualizadas: ${this.sesionesCache.length} disponibles`);
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||||
|
this.logger.error(`[${this.timestamp()}] Error obteniendo sesiones OpenWA: ${message}`);
|
||||||
|
}
|
||||||
|
return this.sesionesCache;
|
||||||
|
}
|
||||||
|
async obtenerSesionRandom() {
|
||||||
|
const sesiones = await this.obtenerSesionesDisponibles();
|
||||||
|
if (sesiones.length === 0) {
|
||||||
|
this.logger.warn(`[${this.timestamp()}] ⚠️ No hay sesiones OpenWA disponibles`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const elegida = sesiones[Math.floor(Math.random() * sesiones.length)];
|
||||||
|
this.logger.log(`[${this.timestamp()}] 🎲 Sesión seleccionada: ${elegida.name} (${elegida.phone})`);
|
||||||
|
return elegida.id;
|
||||||
|
}
|
||||||
async procesarMensaje(mensaje) {
|
async procesarMensaje(mensaje) {
|
||||||
const { idMensajeWhatsApp, telefonoDestino, sessionId, tipo, mensaje1, mensaje2, mensaje3, urlQR } = mensaje;
|
const { idMensajeWhatsApp, telefonoDestino, tipo, mensaje1, mensaje2, mensaje3, urlQR } = mensaje;
|
||||||
const inicio = Date.now();
|
const inicio = Date.now();
|
||||||
this.logger.log(`[${this.timestamp()}] ▶ Procesando mensaje ${idMensajeWhatsApp} → ${telefonoDestino} (${tipo})`);
|
this.logger.log(`[${this.timestamp()}] ▶ Procesando mensaje ${idMensajeWhatsApp} → ${telefonoDestino} (${tipo})`);
|
||||||
try {
|
try {
|
||||||
|
const sessionId = await this.obtenerSesionRandom();
|
||||||
if (!sessionId) {
|
if (!sessionId) {
|
||||||
await this.actualizarEstado(idMensajeWhatsApp, 'ERROR', 'No sessionId configurado');
|
await this.actualizarEstado(idMensajeWhatsApp, 'ERROR', 'No hay sesiones OpenWA disponibles');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const chatId = `${telefonoDestino}@c.us`;
|
const chatId = `${telefonoDestino}@c.us`;
|
||||||
|
|
@ -89,8 +125,21 @@ let WorkerService = WorkerService_1 = class WorkerService {
|
||||||
if (mensajes.length > 0) {
|
if (mensajes.length > 0) {
|
||||||
const texto1 = mensajes[0];
|
const texto1 = mensajes[0];
|
||||||
if (tipo === 'RECEPCION_PAQUETE' && urlQR) {
|
if (tipo === 'RECEPCION_PAQUETE' && urlQR) {
|
||||||
await this.enviarImagen(sessionId, chatId, urlQR, texto1);
|
try {
|
||||||
this.logger.log(`[${this.timestamp()}] 📷✉️ Mensaje 1 (QR + imagen) enviado INMEDIATO`);
|
await this.enviarImagen(sessionId, chatId, urlQR, texto1);
|
||||||
|
this.logger.log(`[${this.timestamp()}] 📷✉️ Mensaje 1 (QR + imagen) enviado INMEDIATO`);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
this.logger.warn(`[${this.timestamp()}] ⚠️ Error enviando imagen, usando fallback con link`);
|
||||||
|
const fullUrl = urlQR.startsWith('http') ? urlQR : `${this.apiUrl.replace('/v1', '')}${urlQR}`;
|
||||||
|
const textoConQR = `${texto1}\n\n🔗 *Ver QR:* ${fullUrl}`;
|
||||||
|
await this.enviarTexto(sessionId, chatId, textoConQR);
|
||||||
|
this.logger.log(`[${this.timestamp()}] ✉️ Mensaje 1 (QR como link) enviado INMEDIATO`);
|
||||||
|
}
|
||||||
|
if (mensajes.length > 1) {
|
||||||
|
await this.actualizarEstado(idMensajeWhatsApp, 'ENVIANDO');
|
||||||
|
this.logger.log(`[${this.timestamp()}] 🔄 Estado cambiado a ENVIANDO`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
await this.enviarTexto(sessionId, chatId, texto1);
|
await this.enviarTexto(sessionId, chatId, texto1);
|
||||||
|
|
@ -118,11 +167,11 @@ let WorkerService = WorkerService_1 = class WorkerService {
|
||||||
await this.delay(delayEntre);
|
await this.delay(delayEntre);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.logger.log(`[${this.timestamp()}] ⏳ Esperando delay1: ${delay1Seg}s antes de continuar...`);
|
|
||||||
await this.delay(delay1);
|
|
||||||
await this.actualizarEstado(idMensajeWhatsApp, 'ENVIADO');
|
await this.actualizarEstado(idMensajeWhatsApp, 'ENVIADO');
|
||||||
const totalSeg = ((Date.now() - inicio) / 1000).toFixed(1);
|
const totalSeg = ((Date.now() - inicio) / 1000).toFixed(1);
|
||||||
this.logger.log(`[${this.timestamp()}] ✅ Mensaje ${idMensajeWhatsApp} ENVIADO (${mensajes.length} mensajes) → tiempo total: ${totalSeg}s`);
|
this.logger.log(`[${this.timestamp()}] ✅ Mensaje ${idMensajeWhatsApp} ENVIADO (${mensajes.length} mensajes) → tiempo total: ${totalSeg}s`);
|
||||||
|
this.logger.log(`[${this.timestamp()}] ⏳ Esperando delay1: ${delay1Seg}s antes de continuar...`);
|
||||||
|
await this.delay(delay1);
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
const message = error instanceof Error ? error.message : 'Unknown error';
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||||
|
|
@ -134,7 +183,7 @@ let WorkerService = WorkerService_1 = class WorkerService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
calcularDelayEscritura(caracteres) {
|
calcularDelayEscritura(caracteres) {
|
||||||
const caracteresPorMinuto = 200;
|
const caracteresPorMinuto = 350;
|
||||||
const base = (caracteres / caracteresPorMinuto) * 60 * 1000;
|
const base = (caracteres / caracteresPorMinuto) * 60 * 1000;
|
||||||
const random = 1 + (Math.random() * 0.6 - 0.3);
|
const random = 1 + (Math.random() * 0.6 - 0.3);
|
||||||
const reaccion = 500 + Math.random() * 1000;
|
const reaccion = 500 + Math.random() * 1000;
|
||||||
|
|
|
||||||
2
dist/worker/worker.service.js.map
vendored
2
dist/worker/worker.service.js.map
vendored
File diff suppressed because one or more lines are too long
|
|
@ -26,6 +26,11 @@ export class WorkerService implements OnModuleInit, OnModuleDestroy {
|
||||||
private readonly openwaApiKey: string;
|
private readonly openwaApiKey: string;
|
||||||
private readonly intervalMs: number;
|
private readonly intervalMs: number;
|
||||||
|
|
||||||
|
// Cache de sesiones OpenWA
|
||||||
|
private sesionesCache: { id: string; name: string; phone: string }[] = [];
|
||||||
|
private sesionesCacheTimestamp = 0;
|
||||||
|
private readonly SESIONES_CACHE_TTL = 5 * 60 * 1000; // 5 minutos
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private config: ConfigService,
|
private config: ConfigService,
|
||||||
private http: HttpService,
|
private http: HttpService,
|
||||||
|
|
@ -92,15 +97,53 @@ export class WorkerService implements OnModuleInit, OnModuleDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async obtenerSesionesDisponibles(): Promise<{ id: string; name: string; phone: string }[]> {
|
||||||
|
const ahora = Date.now();
|
||||||
|
if (this.sesionesCache.length > 0 && ahora - this.sesionesCacheTimestamp < this.SESIONES_CACHE_TTL) {
|
||||||
|
return this.sesionesCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await firstValueFrom(
|
||||||
|
this.http.get(`${this.openwaUrl}/api/sessions`, {
|
||||||
|
headers: { 'X-API-Key': this.openwaApiKey },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const todas = response.data;
|
||||||
|
this.sesionesCache = todas
|
||||||
|
.filter((s: any) => s.status === 'ready')
|
||||||
|
.map((s: any) => ({ id: s.id, name: s.name, phone: s.phone }));
|
||||||
|
this.sesionesCacheTimestamp = ahora;
|
||||||
|
this.logger.log(`[${this.timestamp()}] 🔄 Sesiones OpenWA actualizadas: ${this.sesionesCache.length} disponibles`);
|
||||||
|
} catch (error: unknown) {
|
||||||
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||||
|
this.logger.error(`[${this.timestamp()}] Error obteniendo sesiones OpenWA: ${message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.sesionesCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async obtenerSesionRandom(): Promise<string | null> {
|
||||||
|
const sesiones = await this.obtenerSesionesDisponibles();
|
||||||
|
if (sesiones.length === 0) {
|
||||||
|
this.logger.warn(`[${this.timestamp()}] ⚠️ No hay sesiones OpenWA disponibles`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const elegida = sesiones[Math.floor(Math.random() * sesiones.length)];
|
||||||
|
this.logger.log(`[${this.timestamp()}] 🎲 Sesión seleccionada: ${elegida.name} (${elegida.phone})`);
|
||||||
|
return elegida.id;
|
||||||
|
}
|
||||||
|
|
||||||
private async procesarMensaje(mensaje: MensajePendiente) {
|
private async procesarMensaje(mensaje: MensajePendiente) {
|
||||||
const { idMensajeWhatsApp, telefonoDestino, sessionId, tipo, mensaje1, mensaje2, mensaje3, urlQR } = mensaje;
|
const { idMensajeWhatsApp, telefonoDestino, tipo, mensaje1, mensaje2, mensaje3, urlQR } = mensaje;
|
||||||
const inicio = Date.now();
|
const inicio = Date.now();
|
||||||
|
|
||||||
this.logger.log(`[${this.timestamp()}] ▶ Procesando mensaje ${idMensajeWhatsApp} → ${telefonoDestino} (${tipo})`);
|
this.logger.log(`[${this.timestamp()}] ▶ Procesando mensaje ${idMensajeWhatsApp} → ${telefonoDestino} (${tipo})`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const sessionId = await this.obtenerSesionRandom();
|
||||||
if (!sessionId) {
|
if (!sessionId) {
|
||||||
await this.actualizarEstado(idMensajeWhatsApp, 'ERROR', 'No sessionId configurado');
|
await this.actualizarEstado(idMensajeWhatsApp, 'ERROR', 'No hay sesiones OpenWA disponibles');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,8 +154,22 @@ export class WorkerService implements OnModuleInit, OnModuleDestroy {
|
||||||
if (mensajes.length > 0) {
|
if (mensajes.length > 0) {
|
||||||
const texto1 = mensajes[0];
|
const texto1 = mensajes[0];
|
||||||
if (tipo === 'RECEPCION_PAQUETE' && urlQR) {
|
if (tipo === 'RECEPCION_PAQUETE' && urlQR) {
|
||||||
await this.enviarImagen(sessionId, chatId, urlQR, texto1);
|
// Intentar enviar imagen; si falla, enviar QR como link
|
||||||
this.logger.log(`[${this.timestamp()}] 📷✉️ Mensaje 1 (QR + imagen) enviado INMEDIATO`);
|
try {
|
||||||
|
await this.enviarImagen(sessionId, chatId, urlQR, texto1);
|
||||||
|
this.logger.log(`[${this.timestamp()}] 📷✉️ Mensaje 1 (QR + imagen) enviado INMEDIATO`);
|
||||||
|
} catch {
|
||||||
|
this.logger.warn(`[${this.timestamp()}] ⚠️ Error enviando imagen, usando fallback con link`);
|
||||||
|
const fullUrl = urlQR.startsWith('http') ? urlQR : `${this.apiUrl.replace('/v1', '')}${urlQR}`;
|
||||||
|
const textoConQR = `${texto1}\n\n🔗 *Ver QR:* ${fullUrl}`;
|
||||||
|
await this.enviarTexto(sessionId, chatId, textoConQR);
|
||||||
|
this.logger.log(`[${this.timestamp()}] ✉️ Mensaje 1 (QR como link) enviado INMEDIATO`);
|
||||||
|
}
|
||||||
|
// Cambiar estado a ENVIANDO después del primer mensaje (RECEPCION_PAQUETE tiene 3 mensajes)
|
||||||
|
if (mensajes.length > 1) {
|
||||||
|
await this.actualizarEstado(idMensajeWhatsApp, 'ENVIANDO');
|
||||||
|
this.logger.log(`[${this.timestamp()}] 🔄 Estado cambiado a ENVIANDO`);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
await this.enviarTexto(sessionId, chatId, texto1);
|
await this.enviarTexto(sessionId, chatId, texto1);
|
||||||
this.logger.log(`[${this.timestamp()}] ✉️ Mensaje 1 enviado INMEDIATO`);
|
this.logger.log(`[${this.timestamp()}] ✉️ Mensaje 1 enviado INMEDIATO`);
|
||||||
|
|
@ -152,15 +209,15 @@ export class WorkerService implements OnModuleInit, OnModuleDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── PASO 7: Esperar delay1 (el que se calculó en paso 2) ──
|
// Marcar como enviado ANTES del delay para no perder el estado si el worker se cae
|
||||||
this.logger.log(`[${this.timestamp()}] ⏳ Esperando delay1: ${delay1Seg}s antes de continuar...`);
|
|
||||||
await this.delay(delay1);
|
|
||||||
|
|
||||||
// Marcar como enviado
|
|
||||||
await this.actualizarEstado(idMensajeWhatsApp, 'ENVIADO');
|
await this.actualizarEstado(idMensajeWhatsApp, 'ENVIADO');
|
||||||
const totalSeg = ((Date.now() - inicio) / 1000).toFixed(1);
|
const totalSeg = ((Date.now() - inicio) / 1000).toFixed(1);
|
||||||
this.logger.log(`[${this.timestamp()}] ✅ Mensaje ${idMensajeWhatsApp} ENVIADO (${mensajes.length} mensajes) → tiempo total: ${totalSeg}s`);
|
this.logger.log(`[${this.timestamp()}] ✅ Mensaje ${idMensajeWhatsApp} ENVIADO (${mensajes.length} mensajes) → tiempo total: ${totalSeg}s`);
|
||||||
|
|
||||||
|
// ── PASO 7: Esperar delay1 (el que se calculó en paso 2) ──
|
||||||
|
this.logger.log(`[${this.timestamp()}] ⏳ Esperando delay1: ${delay1Seg}s antes de continuar...`);
|
||||||
|
await this.delay(delay1);
|
||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
const message = error instanceof Error ? error.message : 'Unknown error';
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||||
const responseMessage = error?.response?.data?.message || error?.response?.data?.error || '';
|
const responseMessage = error?.response?.data?.message || error?.response?.data?.error || '';
|
||||||
|
|
@ -172,7 +229,7 @@ export class WorkerService implements OnModuleInit, OnModuleDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
private calcularDelayEscritura(caracteres: number): number {
|
private calcularDelayEscritura(caracteres: number): number {
|
||||||
const caracteresPorMinuto = 200;
|
const caracteresPorMinuto = 350;
|
||||||
const base = (caracteres / caracteresPorMinuto) * 60 * 1000;
|
const base = (caracteres / caracteresPorMinuto) * 60 * 1000;
|
||||||
const random = 1 + (Math.random() * 0.6 - 0.3);
|
const random = 1 + (Math.random() * 0.6 - 0.3);
|
||||||
const reaccion = 500 + Math.random() * 1000;
|
const reaccion = 500 + Math.random() * 1000;
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue