Spaces:
Sleeping
Sleeping
File size: 6,277 Bytes
77dd67d ada0c1e 77dd67d ada0c1e 77dd67d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | 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 chats = await wppClient.listChats();
const groups = chats.filter(chat => chat.isGroup);
res.json({ success: true, groups });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.post("/api/groups/join", checkPasskey, async (req, res) => {
if (!wppClient || currentStatus !== 'CONNECTED') return res.status(400).json({ error: 'Not connected' });
const { inviteCode } = req.body;
if (!inviteCode) return res.status(400).json({ error: 'Invite code required' });
try {
addLog(`Joining group with invite code...`);
const result = await wppClient.joinGroup(inviteCode);
addLog("Joined group successfully!");
res.json({ success: true, result });
} catch (error) {
addLog(`Join group error: ${error.message}`);
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, poll } = req.body;
try {
let recipient = phone;
if (!phone.includes('@')) recipient = isGroup ? `${phone}@g.us` : `${phone}@c.us`;
if (poll && poll.name && poll.options) {
addLog(`Sending poll to ${recipient}...`);
const result = await wppClient.sendPollMessage(recipient, poll.name, poll.options, {
selectableCount: poll.selectableCount || 1
});
addLog("Poll sent!");
return res.json({ success: true, result });
}
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}`);
});
|