const { default: makeWASocket, useMultiFileAuthState, DisconnectReason } = require('@whiskeysockets/baileys'); const pino = require('pino'); const axios = require('axios'); const fs = require('fs'); const path = require('path'); const sessions = new Map(); // Store active sockets in memory // Local folder for saving auth keys const SESSIONS_DIR = path.join(__dirname, 'sessions'); if (!fs.existsSync(SESSIONS_DIR)) { fs.mkdirSync(SESSIONS_DIR, { recursive: true }); } const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET; async function sendWebhook(webhook_url, payload) { try { await axios.post(webhook_url, payload, { headers: { 'Content-Type': 'application/json', 'X-Webhook-Secret': WEBHOOK_SECRET }, timeout: 5000 }); } catch (err) { console.error(`Failed to send webhook to ${webhook_url}:`, err.message); } } async function startSession(session_key, webhook_url) { // Return existing socket if it's already active if (sessions.has(session_key)) { return sessions.get(session_key); } const sessionFolder = path.join(SESSIONS_DIR, session_key); const { state, saveCreds } = await useMultiFileAuthState(sessionFolder); const sock = makeWASocket({ auth: state, printQRInTerminal: false, logger: pino({ level: 'silent' }), // Suppress massive terminal output browser: ['Nabeh Gateway', 'Chrome', '1.0.0'] }); sessions.set(session_key, sock); sock.ev.on('creds.update', saveCreds); sock.ev.on('connection.update', async (update) => { const { connection, lastDisconnect, qr } = update; if (qr) { // Forward the raw QR code string to PHP await sendWebhook(webhook_url, { session_key, state: 'waiting_qr', qr_code: qr }); } if (connection === 'close') { const statusCode = lastDisconnect?.error?.output?.statusCode; const shouldReconnect = statusCode !== DisconnectReason.loggedOut; console.log(`Session ${session_key} connection closed. Reconnect: ${shouldReconnect}`); if (shouldReconnect) { // Try reconnecting after a short delay sessions.delete(session_key); setTimeout(() => startSession(session_key, webhook_url), 3000); } else { // Number was banned or manually logged out from the phone await disconnectSession(session_key); await sendWebhook(webhook_url, { session_key, state: 'disconnected' }); } } else if (connection === 'open') { console.log(`Session ${session_key} connected successfully!`); // Parse phone number from the JID (e.g. 9665XXXXXXX@s.whatsapp.net) const phone = sock.user.id.split(':')[0]; await sendWebhook(webhook_url, { session_key, state: 'connected', phone: phone }); } }); return sock; } async function disconnectSession(session_key) { const sock = sessions.get(session_key); if (sock) { try { sock.logout(); } catch (e) { } // best effort sessions.delete(session_key); } // Completely wipe the auth directory so a fresh session can be created next time const sessionFolder = path.join(SESSIONS_DIR, session_key); if (fs.existsSync(sessionFolder)) { fs.rmSync(sessionFolder, { recursive: true, force: true }); } } module.exports = { startSession, disconnectSession };