From 716b6f93bf205f8367ba92de699aed055ff484b6 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Thu, 21 May 2026 17:35:06 +0300 Subject: [PATCH] Deploy: 2026-05-21 17:35:06 --- whatsapp-gateway/baileys-client.js | 113 +++++++++++++++++++++++++++++ whatsapp-gateway/package.json | 16 ++++ whatsapp-gateway/server.js | 52 +++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 whatsapp-gateway/baileys-client.js create mode 100644 whatsapp-gateway/package.json create mode 100644 whatsapp-gateway/server.js diff --git a/whatsapp-gateway/baileys-client.js b/whatsapp-gateway/baileys-client.js new file mode 100644 index 0000000..5bab93c --- /dev/null +++ b/whatsapp-gateway/baileys-client.js @@ -0,0 +1,113 @@ +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 || 'YOUR_SECRET_KEY_HERE'; + +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 +}; diff --git a/whatsapp-gateway/package.json b/whatsapp-gateway/package.json new file mode 100644 index 0000000..800f367 --- /dev/null +++ b/whatsapp-gateway/package.json @@ -0,0 +1,16 @@ +{ + "name": "nabeh-whatsapp-gateway", + "version": "1.0.0", + "description": "WhatsApp Baileys microservice for Nabeh", + "main": "server.js", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "@whiskeysockets/baileys": "^6.7.9", + "axios": "^1.7.2", + "cors": "^2.8.5", + "express": "^4.19.2", + "pino": "^9.2.0" + } +} diff --git a/whatsapp-gateway/server.js b/whatsapp-gateway/server.js new file mode 100644 index 0000000..b531c5f --- /dev/null +++ b/whatsapp-gateway/server.js @@ -0,0 +1,52 @@ +const express = require('express'); +const cors = require('cors'); +const { startSession, disconnectSession } = require('./baileys-client'); + +const app = express(); +app.use(cors()); +app.use(express.json()); + +const PORT = process.env.PORT || 3722; + +// Health check endpoint +app.get('/health', (req, res) => { + res.json({ status: 'healthy', service: 'Nabeh WhatsApp Gateway' }); +}); + +// Start or retrieve a session +app.post('/api/sessions/start', async (req, res) => { + const { session_key, webhook_url } = req.body; + + if (!session_key || !webhook_url) { + return res.status(400).json({ error: 'Missing session_key or webhook_url' }); + } + + try { + await startSession(session_key, webhook_url); + res.json({ status: 'success', message: 'Session started or retrieved' }); + } catch (err) { + console.error(`Error starting session ${session_key}:`, err); + res.status(500).json({ error: 'Failed to start session' }); + } +}); + +// Disconnect and remove a session (e.g., when banned or logged out) +app.post('/api/sessions/disconnect', async (req, res) => { + const { session_key } = req.body; + + if (!session_key) { + return res.status(400).json({ error: 'Missing session_key' }); + } + + try { + await disconnectSession(session_key); + res.json({ status: 'success', message: 'Session disconnected and cleaned up' }); + } catch (err) { + console.error(`Error disconnecting session ${session_key}:`, err); + res.status(500).json({ error: 'Failed to disconnect session' }); + } +}); + +app.listen(PORT, () => { + console.log(`🚀 Nabeh WhatsApp Gateway running on port ${PORT}`); +});