import fs from "fs"; import express from "express"; import * as wppconnect from '@wppconnect-team/wppconnect'; import path from "path"; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); let wppClient = null; let currentStatus = 'DISCONNECTED'; let qrCodeBase64 = ''; let logs = []; function addLog(msg) { const timestamp = new Date().toLocaleTimeString(); const fullMsg = `[${timestamp}] ${msg}`; logs.push(fullMsg); if (logs.length > 100) logs.shift(); console.log(fullMsg); } const app = express(); const PORT = process.env.PORT || 7860; app.use(express.json()); // Helper to check passkey function isValidPasskey(provided) { const envPasskey = process.env.PASSKEY; if (!envPasskey) return true; return provided === envPasskey || provided === `Bearer ${envPasskey}`; } // Middleware function checkPasskey(req, res, next) { const provided = req.headers['x-passkey'] || req.headers['authorization'] || req.query.passkey; if (isValidPasskey(provided)) return next(); res.status(401).json({ error: 'Unauthorized' }); } app.get("/health", (req, res) => res.send("OK")); app.post('/api/login', (req, res) => { const { passkey } = req.body; if (isValidPasskey(passkey)) { addLog("Successful login attempt."); res.json({ success: true }); } else { addLog(`Failed login attempt.`); res.status(401).json({ success: false, error: 'Invalid passkey' }); } }); app.get("/api/status", checkPasskey, (req, res) => { res.json({ status: currentStatus, qrCode: qrCodeBase64, logs }); }); app.get("/api/groups", checkPasskey, async (req, res) => { if (!wppClient || currentStatus !== 'CONNECTED') return res.status(400).json({ error: 'Not connected' }); try { const groups = await wppClient.getAllGroups(); res.json({ success: true, groups }); } catch (error) { res.status(500).json({ error: error.message }); } }); app.post('/api/start', checkPasskey, async (req, res) => { if (currentStatus === 'CONNECTED' || currentStatus === 'INITIALIZING') { return res.json({ success: true, status: currentStatus }); } currentStatus = 'INITIALIZING'; qrCodeBase64 = ''; addLog('Initializing WPPConnect session...'); res.json({ success: true }); try { const sessionPath = path.join(__dirname, 'tokens', 'gradio-session'); if (fs.existsSync(sessionPath)) { try { fs.rmSync(sessionPath, { recursive: true, force: true }); addLog("Cleared stale session tokens."); } catch (e) { addLog(`Warning: Could not clear session path: ${e.message}`); } } wppClient = await wppconnect.create({ session: 'gradio-session', autoClose: 0, updatesLog: true, catchQR: (base64Qr) => { currentStatus = 'QR_CODE'; qrCodeBase64 = base64Qr; addLog("QR Code generated."); }, statusFind: (statusSession) => { addLog(`Session Status: ${statusSession}`); if (['isLogged', 'inChat', 'qrReadSuccess', 'chatsAvailable'].includes(statusSession)) { currentStatus = 'CONNECTED'; qrCodeBase64 = ''; addLog("WhatsApp connection established."); } }, headless: true, puppeteerOptions: { executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || '/usr/bin/chromium', args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu', '--no-zygote' ] } }); // Listen for interface changes to catch the 'MAIN' state wppClient.onInterfaceChange((state) => { addLog(`Interface state: ${state.display || state.mode}`); if (state.display === 'MAIN') { currentStatus = 'CONNECTED'; qrCodeBase64 = ''; addLog("WhatsApp reached MAIN interface."); } }); const isLogged = await wppClient.isLoggedIn(); if (isLogged) { currentStatus = 'CONNECTED'; addLog("Validated: User is logged in."); } } catch (error) { addLog(`WPPConnect Error: ${error.message}`); currentStatus = 'ERROR'; wppClient = null; } }); app.post('/api/send', checkPasskey, async (req, res) => { if (!wppClient || currentStatus !== 'CONNECTED') return res.status(400).json({ error: 'Not connected' }); const { phone, message, isGroup } = req.body; try { let recipient = phone; if (!phone.includes('@')) recipient = isGroup ? `${phone}@g.us` : `${phone}@c.us`; addLog(`Sending message to ${recipient}...`); const result = await wppClient.sendText(recipient, message); addLog("Message sent!"); res.json({ success: true, result }); } catch (error) { addLog(`Send Error: ${error.message}`); res.status(500).json({ error: error.message }); } }); const distPath = path.join(__dirname, 'dist'); if (fs.existsSync(distPath)) { app.use(express.static(distPath)); app.get('*', (req, res) => { if (req.path.startsWith('/api/')) return res.status(404).json({ error: 'API route not found' }); res.sendFile(path.join(distPath, 'index.html')); }); } app.listen(PORT, "0.0.0.0", () => { console.log(`Server running on port ${PORT}`); });