UNPKG

plazbot-cli

Version:
101 lines (86 loc) 3.54 kB
import { Command } from 'commander'; import { Message } from 'plazbot'; import { getStoredCredentials } from '../../utils/credentials'; import { logger } from '../../utils/logger'; import { createSpinner, theme, section, progressBar } from '../../utils/ui'; import fs from 'fs/promises'; export const broadcastCommand = new Command('broadcast') .description('Envio masivo de mensajes de template WhatsApp') .requiredOption('-t, --template <name>', 'Nombre del template') .requiredOption('--phones <file>', 'Archivo CSV con numeros de telefono (uno por linea)') .option('--var <vars...>', 'Variables del body (formato: name=valor)') .option('--delay <ms>', 'Delay entre mensajes en ms', '1000') .option('--dev', 'Usar ambiente de desarrollo', false) .action(async (options: any) => { try { const credentials = await getStoredCredentials(); const messageClient = new Message({ workspaceId: credentials.workspace, apiKey: credentials.apiKey, zone: credentials.zone, ...(options.dev && { customUrl: "http://localhost:5090" }) }); // Leer archivo de telefonos let phones: string[]; try { const content = await fs.readFile(options.phones, 'utf-8'); phones = content.split('\n') .map(line => line.trim()) .filter(line => line && !line.startsWith('#')); } catch { throw new Error(`No se pudo leer el archivo: ${options.phones}`); } if (phones.length === 0) { throw new Error('El archivo no contiene numeros de telefono'); } // Parsear variables const variablesBody = parseVariables(options.var); console.log(section('Broadcast WhatsApp')); logger.label('Template', options.template); logger.label('Destinatarios', String(phones.length)); logger.label('Delay', `${options.delay}ms`); if (variablesBody.length > 0) { logger.label('Variables', variablesBody.map(v => `${v.variable}=${v.value}`).join(', ')); } console.log(); const delay = parseInt(options.delay) || 1000; let sent = 0; let failed = 0; for (let i = 0; i < phones.length; i++) { const phone = phones[i]; try { const params: any = { to: phone, template: options.template, }; if (variablesBody.length > 0) params.variablesBody = variablesBody; await messageClient.onConversation(params); sent++; } catch { failed++; console.log(theme.error(` ✖ Fallo: ${phone}`)); } // Progress console.log(` ${progressBar(i + 1, phones.length)}`); // Rate limiting if (i < phones.length - 1) { await new Promise(resolve => setTimeout(resolve, delay)); } } console.log(section('Resultado')); logger.label('Enviados', theme.success(String(sent))); logger.label('Fallidos', failed > 0 ? theme.error(String(failed)) : '0'); logger.label('Total', String(phones.length)); } catch (error: unknown) { const message = (error as Error)?.message || 'Error desconocido'; logger.error(message); process.exit(1); } }); function parseVariables(vars: string[] | undefined): { variable: string; value: string }[] { if (!vars) return []; return vars.map(v => { const [variable, ...rest] = v.split('='); return { variable: variable.trim(), value: rest.join('=').trim() }; }).filter(v => v.variable && v.value); }