const { Client, LocalAuth } = require('whatsapp-web.js'); const qrcode = require('qrcode-terminal'); const dotenv = require('dotenv'); const weatherUtils = require('./utils/weather_utils'); const weatherService = require('./services/weather_service'); // Configuración inicial dotenv.config(); // Constantes const CHROME_PATH = process.env.CHROME_PATH; const AUTHORIZED_NUMBER = process.env.AUTHORIZED_NUMBER; // Validación inicial if (!AUTHORIZED_NUMBER) { console.error('❌ Debes establecer el número autorizado en el archivo .env'); process.exit(1); } // Configuración del cliente const clientConfig = { authStrategy: new LocalAuth(), puppeteer: { headless: true, executablePath: CHROME_PATH, args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'] } }; class WhatsAppBot { constructor() { this.client = new Client(clientConfig); this.myId = null; this.myNumber = null; this.initializeEventHandlers(); } initializeEventHandlers() { this.client.on('qr', this.handleQR); this.client.on('ready', this.handleReady.bind(this)); this.client.on('message_create', this.handleMessage.bind(this)); this.client.on('message', this.logMessage); this.client.on('group_join', this.handleGroupJoin); } handleQR(qr) { qrcode.generate(qr, { small: true }); console.log('🔍 Escanea el QR code con tu WhatsApp.'); } async handleReady() { console.log('✅ Cliente de WhatsApp está listo!'); try { this.myId = this.client.info.wid._serialized; this.myNumber = this.myId.split('@')[0]; console.log(`🔑 Tu ID de WhatsApp es: ${this.myId}`); console.log(`📱 Tu número de teléfono es: ${this.myNumber}`); const chat = await this.client.getChatById(this.myId); console.log('💭 Chat propio encontrado:', chat); } catch (error) { console.error(`❌ Error al obtener información: ${error}`); } } isChatAllowed(messageFrom) { const isAllowed = messageFrom === AUTHORIZED_NUMBER; if (isAllowed) console.log('🎯 Mensaje detectado desde el número autorizado'); return isAllowed; } async handleMessage(message) { if (!this.myId || !this.isChatAllowed(message.from)) return; console.log('📨 Mensaje creado:', { from: message.from, fromMe: message.fromMe, body: message.body, type: message.type, timestamp: message.timestamp }); const command = message.body.trim().toLowerCase(); if (command === '!ping') { await this.handlePingCommand(message); } else if (command.startsWith('!clima')) { await this.handleWeatherCommand(message); } } async handlePingCommand(message) { try { await this.client.sendMessage(message.from, 'pong'); console.log(`📤 Respondido 'pong' al número autorizado ${message.from}`); } catch (error) { console.error('❌ Error al enviar respuesta:', error); } } async handleWeatherCommand(message) { const parts = message.body.split(' '); const city = parts.length > 1 ? parts.slice(1).join(' ') : 'Guatemala'; try { const { latitude, longitude } = await weatherUtils.getCoordinates(city); const weather = await weatherService.getWeather(latitude, longitude); const weatherDescription = weatherUtils.translateWeatherCode(weather.weathercode); const weatherInfo = this.formatWeatherInfo(city, weather, weatherDescription); await this.client.sendMessage(message.from, weatherInfo); console.log(`📤 Información del clima de ${city} enviada a ${message.from}`); } catch (error) { console.error('❌ Error al obtener el clima:', error); await this.client.sendMessage(message.from, `❌ Error al obtener el clima: ${error.message}`); } } formatWeatherInfo(city, weather, weatherDescription) { return ` 🌤️ *Clima Actual en ${city}*: - 🌡️ Temperatura: ${weather.temperature}°C - 💨 Viento: ${weather.windspeed} km/h - 🧭 Dirección del viento: ${weather.winddirection}° - ☁️ Condición: ${weatherDescription} - ⏰ Hora: ${new Date(weather.time).toLocaleTimeString('es-ES')} `.trim(); } logMessage(message) { console.log('📩 Mensaje recibido:', { from: message.from, fromMe: message.fromMe, body: message.body }); } handleGroupJoin(notification) { console.log('👥 Bot añadido a un nuevo grupo:', notification.id.remote); } start() { this.client.initialize(); } } // Iniciar el bot const bot = new WhatsAppBot(); bot.start();