Spaces:
Running
Running
| 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}`); | |
| }); | |