From 332f386b10d79169f99530cebdd50a5b8e27271a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Bachmann?= Date: Mon, 15 Jun 2026 07:10:52 +0000 Subject: [PATCH] whatsapp_bridge/server.js aktualisiert Fix Error session end, fix error manual reconnect after crash. --- whatsapp_bridge/server.js | 104 +++++++++++++++++++++++++++++++------- 1 file changed, 86 insertions(+), 18 deletions(-) diff --git a/whatsapp_bridge/server.js b/whatsapp_bridge/server.js index c819d4c..a503d7c 100644 --- a/whatsapp_bridge/server.js +++ b/whatsapp_bridge/server.js @@ -6,23 +6,73 @@ const path = require('path'); const app = express(); app.use(express.json()); - -// Statische Dateien aus dem "ui" Ordner servieren app.use(express.static(path.join(__dirname, 'ui'))); let lastQr = ""; let isReady = false; +let isInitializing = true; + +// Fester Speicherort für die Session außerhalb flüchtiger Docker-Verzeichnisse const SESSION_DATA = '/data/auth'; +// Sauberes Herunterfahren bei Abstürzen, um Dateikorruption der Session zu verhindern +async function handleCrash(errorContext) { + console.error(`💥 CRITICAL ERROR CAUGHT: ${errorContext}`); + isReady = false; + + try { + console.log('Versuche Browser sauber zu schließen, um Session zu retten...'); + if (client && client.pupBrowser) { + await client.pupBrowser.close().catch(() => {}); + } + } catch (e) { + console.error('Browser konnte nicht sauber geschlossen werden:', e); + } + + console.log('Add-on wird beendet. HA Watchdog startet es sauber neu...'); + process.exit(1); +} + +// Sicherheitsnetz für ungefangene Puppeteer/Browser-Fehler +process.on('uncaughtException', async (err) => { + if (err.message.includes('ProtocolError') || err.message.includes('Runtime.callFunctionOn') || err.message.includes('Target closed')) { + await handleCrash('Puppeteer Protocol Timeout / Crash'); + } else { + console.error('Uncaught Exception:', err); + } +}); + +process.on('unhandledRejection', async (reason, promise) => { + if (reason && reason.message && reason.message.includes('Session closed')) { + await handleCrash('Unhandled Puppeteer Session Rejection'); + } else { + console.error('Unhandled Rejection at:', promise, 'reason:', reason); + } +}); + +// Client-Definition mit fixierter Client-ID gegen Session-Verlust const client = new Client({ - authStrategy: new LocalAuth({ dataPath: SESSION_DATA }), + authStrategy: new LocalAuth({ + dataPath: SESSION_DATA, + clientId: "ha_bridge_session" + }), + authTimeoutMs: 90000, + qrMaxRetries: 5, puppeteer: { executablePath: '/usr/bin/chromium-browser', + protocolTimeout: 0, args: [ '--no-sandbox', '--disable-setuid-sandbox', - '--disable-dev-shm-usage', - '--disable-gpu' + '--disable-dev-shm-usage', + '--disable-gpu', + '--no-first-run', + '--no-zygote', + '--single-process', + '--disable-extensions', + '--disable-background-timer-throttling', + '--disable-backgrounding-occluded-windows', + '--disable-renderer-backgrounding' ] } }); @@ -31,57 +81,71 @@ const client = new Client({ client.on('qr', (qr) => { lastQr = qr; isReady = false; + isInitializing = false; console.log('Neuer QR Code generiert.'); }); client.on('ready', () => { isReady = true; lastQr = ""; - console.log('WhatsApp ist bereit!'); + isInitializing = false; + console.log('WhatsApp ist bereit! Session wurde erfolgreich geladen/gespeichert.'); +}); + +client.on('disconnected', async (reason) => { + console.log(`WhatsApp Verbindung manuell oder extern getrennt (Grund: ${reason}).`); + await handleCrash('Externer Disconnect'); }); // --- ROUTES --- -// Hauptseite für Ingress app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'ui', 'index.html')); }); -// Status API app.get('/api/status', async (req, res) => { try { let qrData = null; if (lastQr) { qrData = await qrcode.toDataURL(lastQr); } + + let clientState = 'DISCONNECTED'; + if (isReady) { + clientState = await client.getState().catch(() => 'ERROR'); + } + res.json({ isReady: isReady, hasQr: lastQr !== "", - qrCode: qrData + qrCode: qrData, + isInitializing: isInitializing, + clientState: clientState }); } catch (e) { res.status(500).json({ error: e.message }); } }); -// Logout +// Logout & Session-Löschung (Nur bei explizitem Klick auf "Account wechseln") app.post('/auth/logout', async (req, res) => { try { - await client.logout(); - await fs.remove(SESSION_DATA); - res.json({ success: true, message: "Erfolgreich abgemeldet. Addon startet neu..." }); + console.log("Manueller Logout über Web-UI..."); + await client.logout().catch(() => {}); + await fs.remove(path.join(SESSION_DATA, 'session-ha_bridge_session')).catch(() => {}); + res.json({ success: true, message: "Erfolgreich abgemeldet. Ordner gelöscht. Addon startet neu..." }); setTimeout(() => process.exit(0), 2000); } catch (err) { res.status(500).json({ error: err.message }); } }); -// Reset +// Factory Reset app.delete('/system/reset', async (req, res) => { try { - await client.destroy(); - await fs.emptyDir('/data'); - res.json({ success: true, message: "Werkseinstellungen wiederhergestellt. Addon startet neu..." }); + await client.destroy().catch(() => {}); + await fs.emptyDir('/data').catch(() => {}); + res.json({ success: true, message: "Werkseinstellungen aktiv. Alles gelöscht. Neustart..." }); setTimeout(() => process.exit(0), 2000); } catch (err) { res.status(500).json({ error: err.message }); @@ -101,5 +165,9 @@ app.post('/send', async (req, res) => { } }); -client.initialize(); +console.log('Initialisiere WhatsApp Client...'); +client.initialize().catch(async (err) => { + await handleCrash(`Initialisierungsfehler: ${err.message}`); +}); + app.listen(3000, () => console.log('WhatsApp Bridge Server läuft auf Port 3000')); \ No newline at end of file