114 lines
3.8 KiB
JavaScript
114 lines
3.8 KiB
JavaScript
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 });
|
|
}
|
|
|
|
async function sendWebhook(webhook_url, payload) {
|
|
try {
|
|
console.log(`Sending webhook to ${webhook_url} with state ${payload.state}`);
|
|
await axios.post(webhook_url, payload, {
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-Webhook-Secret': process.env.WEBHOOK_SECRET || 'fallback'
|
|
},
|
|
timeout: 5000
|
|
});
|
|
console.log(`Webhook sent successfully to ${webhook_url}`);
|
|
} 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
|
|
};
|