WhatsApp-Logger-Self-Hosted-

A privacy-focused, self-hosted...
Log | Files | Refs | Activity | README | LICENSE

root / src / whatsapp.js

whatsapp.js (5780B)


      1 const {
      2     default: makeWASocket,
      3     DisconnectReason,
      4     fetchLatestBaileysVersion
      5 } = require('@whiskeysockets/baileys');
      6 const pino = require('pino');
      7 const { db } = require('./firebase');
      8 const { useFirestoreAuthState } = require('./authState');
      9 
     10 // --- BAILEYS SETUP ---
     11 let qrCodeData = null;
     12 let sock = null;
     13 let isConnected = false;
     14 
     15 let consecutiveAuthFailures = 0;
     16 let consecutiveConnectFailures = 0;
     17 
     18 async function startWhatsApp() {
     19     const logger = pino({ level: 'silent' });
     20 
     21     let authResult;
     22     try {
     23         authResult = await useFirestoreAuthState(db, 'whatsapp_auth');
     24     } catch (err) {
     25         consecutiveAuthFailures++;
     26         const backoff = Math.min(5000 * Math.pow(2, consecutiveAuthFailures), 300000); // cap 5 min
     27         console.error(`System: Auth state read failed (attempt ${consecutiveAuthFailures}). Retrying in ${backoff / 1000}s.`);
     28         setTimeout(startWhatsApp, backoff);
     29         return;
     30     }
     31     consecutiveAuthFailures = 0; // Reset on success
     32 
     33     const { state, saveCreds, clearState } = authResult;
     34     const { version } = await fetchLatestBaileysVersion();
     35 
     36     console.log("System: Connecting to WhatsApp servers...");
     37 
     38     sock = makeWASocket({
     39         version,
     40         logger,
     41         auth: state,
     42         browser: ["WhatsApp Logger v4.2.1", "Chrome", "4.2.1"],
     43         syncFullHistory: true
     44     });
     45 
     46     sock.ev.on('connection.update', async (update) => {
     47         const { connection, lastDisconnect, qr } = update;
     48 
     49         if (qr) {
     50             console.log("System: No valid credentials. New QR Code generated.");
     51             qrCodeData = qr;
     52             isConnected = false;
     53         }
     54 
     55         if (connection === 'close') {
     56             isConnected = false;
     57             const statusCode = lastDisconnect?.error?.output?.statusCode;
     58             const shouldReconnect = statusCode !== DisconnectReason.loggedOut;
     59 
     60             if (shouldReconnect) {
     61                 consecutiveConnectFailures++;
     62                 const backoff = Math.min(5000 * Math.pow(2, consecutiveConnectFailures), 300000); // cap 5 min
     63                 console.log(`System: Connection closed (Status: ${statusCode}). Reconnecting in ${backoff / 1000}s...`);
     64                 setTimeout(startWhatsApp, backoff);
     65             } else {
     66                 console.log("System: Device Logged Out. Wiping session from Firestore.");
     67                 await clearState();
     68                 qrCodeData = null;
     69                 consecutiveConnectFailures = 0;
     70                 startWhatsApp();
     71             }
     72         } else if (connection === 'open') {
     73             console.log("System: Connection Open and Authenticated. Firebase Auth Sync Active.");
     74             qrCodeData = null;
     75             isConnected = true;
     76             consecutiveConnectFailures = 0; // Reset on success
     77         }
     78     });
     79 
     80     sock.ev.on('creds.update', saveCreds);
     81 
     82     sock.ev.on('contacts.upsert', async (contacts) => {
     83         for (const contact of contacts) {
     84             let updateData = {};
     85             const displayName = contact.name || contact.notify;
     86 
     87             if (displayName) updateData.displayName = displayName;
     88 
     89             if (contact.id && contact.id.endsWith('@s.whatsapp.net')) {
     90                 updateData.phoneNumber = contact.id.split('@')[0];
     91             }
     92 
     93             const primaryId = contact.lid || contact.id;
     94 
     95             if (primaryId && Object.keys(updateData).length > 0) {
     96                 try {
     97                     await db.collection('Chats').doc(primaryId).set(updateData, { merge: true });
     98 
     99                     if (contact.lid && contact.id !== contact.lid) {
    100                         await db.collection('Chats').doc(contact.id).set(updateData, { merge: true });
    101                     }
    102                 } catch (err) {}
    103             }
    104         }
    105     });
    106 
    107     sock.ev.on('messages.upsert', async ({ messages, type }) => {
    108         if (type !== 'notify' && type !== 'append') return;
    109 
    110         for (const msg of messages) {
    111             try {
    112                 if (!msg.message) continue;
    113 
    114                 const remoteJid = msg.key.remoteJid;
    115                 if (remoteJid === 'status@broadcast') continue;
    116 
    117                 const textContent =
    118                     msg.message.conversation ||
    119                     msg.message.extendedTextMessage?.text ||
    120                     msg.message.imageMessage?.caption ||
    121                     msg.message.videoMessage?.caption ||
    122                     "";
    123 
    124                 if (!textContent) continue;
    125 
    126                 const timestamp = msg.messageTimestamp
    127                     ? (typeof msg.messageTimestamp === 'number' ? msg.messageTimestamp : msg.messageTimestamp.low)
    128                     : Math.floor(Date.now() / 1000);
    129 
    130                 const isFromMe = msg.key.fromMe || false;
    131                 const senderName = isFromMe ? "Me" : (msg.pushName || "Unknown");
    132 
    133                 // 1. Ensure Chat Document Exists
    134                 await db.collection('Chats').doc(remoteJid).set({
    135                     lastActive: timestamp,
    136                     id: remoteJid,
    137                     preview: textContent
    138                 }, { merge: true });
    139 
    140                 // 2. Save Message
    141                 await db.collection('Chats')
    142                     .doc(remoteJid)
    143                     .collection('Messages')
    144                     .doc(msg.key.id)
    145                     .set({
    146                         text: textContent,
    147                         senderId: remoteJid,
    148                         senderName: senderName,
    149                         timestamp: timestamp,
    150                         fromMe: isFromMe,
    151                         id: msg.key.id
    152                     }, { merge: true });
    153 
    154             } catch (err) {}
    155         }
    156     });
    157 }
    158 
    159 module.exports = {
    160     startWhatsApp,
    161     getQrCodeData: () => qrCodeData,
    162     getIsConnected: () => isConnected
    163 };
© notamitgamer • Site Built: 2026-09-05 01:53:16 UTC • git-mirror commit: c170d72 [view raw info]
Originally created with stagit • modified by notamitgamer
Forked from github.com/notamitgamer/git-mirror