browser-use-webui / server.js
Leon4gr45's picture
CLEAN REDEPLOY: Secure Express state with Dashboard fix
5182a50 verified
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}`);
});