From 19b8da0faccfc4438ed19fbc99d992a6a07af003 Mon Sep 17 00:00:00 2001 From: Agando Date: Wed, 29 Jul 2026 20:46:12 +0200 Subject: auto: 2026-07-29_20:50 changes — gunes sponsorluk page, bunq payment modal, AI platforms, news W30 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/core/core-bundle.js | 153 +++++++++++++++++++++++++++++--- modules/core/module-debug-supervisor.js | 153 +++++++++++++++++++++++++++++--- 2 files changed, 286 insertions(+), 20 deletions(-) (limited to 'modules/core') diff --git a/modules/core/core-bundle.js b/modules/core/core-bundle.js index aab0206..2bb076a 100644 --- a/modules/core/core-bundle.js +++ b/modules/core/core-bundle.js @@ -19164,6 +19164,8 @@ class DebugSupervisorModule { 'debug-trends': 'debug-trends [days] — Error frequency over time (default: 7)', 'debug-fix': 'debug-fix — Suggest and optionally apply fix for an error', 'debug-health': 'debug-health — Check supervisor module health status', + 'debug-sync': 'debug-sync [url] — Sync errors to backend API (or set sync URL)', + 'debug-sync-url': 'debug-sync-url [url] — View or set the backend sync endpoint', }; } @@ -19174,6 +19176,8 @@ class DebugSupervisorModule { this.commands['debug-trends'] = (args) => this._cmdTrends(args); this.commands['debug-fix'] = (args) => this._cmdFix(args); this.commands['debug-health'] = () => this._cmdHealth(); + this.commands['debug-sync'] = (args) => this._cmdSync(args); + this.commands['debug-sync-url'] = (args) => this._cmdSyncUrl(args); } seed() { @@ -19183,6 +19187,36 @@ class DebugSupervisorModule { init() { this._loadDB(); this._installInterceptors(); + // Start periodic sync (every 5 minutes) + this._syncInterval = setInterval(() => this._syncToBackend(), 300000); + // Also sync on first load after a short delay + setTimeout(() => this._syncToBackend(), 5000); + } + + destroy() { + // Clear sync interval + if (this._syncInterval) { + clearInterval(this._syncInterval); + this._syncInterval = null; + } + // Restore original console.error + if (this._originalConsole.error) { + console.error = this._originalConsole.error; + } + // Restore original window.onerror + if (this._originalOnError) { + window.onerror = this._originalOnError; + } + // Restore original fetch + if (this._originalFetch) { + window.fetch = this._originalFetch; + } + // Remove unhandledrejection listener (stored for cleanup) + if (this._rejectionHandler) { + window.removeEventListener('unhandledrejection', this._rejectionHandler); + } + this._interceptorInstalled = false; + this._healthy = false; } // ── Error Database ── @@ -19252,11 +19286,7 @@ class DebugSupervisorModule { _checkQuota() { try { - const total = 0; - for (const key in localStorage) { - // Estimate: key + value length - } - // Simple check: try writing a test key + // Test localStorage is writable const testKey = '__quota_test__'; localStorage.setItem(testKey, '1'); localStorage.removeItem(testKey); @@ -19290,7 +19320,7 @@ class DebugSupervisorModule { _detectSeverity(type, message) { if (type === 'SyntaxError' || type === 'ReferenceError' || type === 'quota') return 'fatal'; - if (type === 'HTTP' && message.includes('5')) return 'error'; + if (type === 'HTTP' && /\b5\d{2}\b/.test(message)) return 'error'; if (type === 'timeout' || type === 'security') return 'error'; if (type === 'tool') return 'warning'; return 'error'; @@ -19347,10 +19377,11 @@ class DebugSupervisorModule { // Unhandled rejections this._originalOnRejection = window.onunhandledrejection; - window.addEventListener('unhandledrejection', function(e) { + this._rejectionHandler = function(e) { const msg = e.reason ? (e.reason.message || String(e.reason)) : 'Unhandled Promise rejection'; self._recordError(msg, 'unhandledrejection', e.reason ? e.reason.stack : null); - }); + }; + window.addEventListener('unhandledrejection', this._rejectionHandler); // Fetch failures this._originalFetch = window.fetch; @@ -19761,9 +19792,11 @@ class DebugSupervisorModule { if (!fix.fixes || fix.fixes.length === 0) return; const firstFix = fix.fixes[0]; try { + // Sanitize params: only allow alphanumeric, hyphens, underscores, dots + const safeParams = (firstFix.params || '').replace(/[^a-zA-Z0-9_\-\.]/g, ''); if (firstFix.action === 'loadmod' && this.terminal) { - this.terminal.executeCommand('loadmod ' + (firstFix.params || '')); - this.terminal.print(' ✅ Applied: loadmod ' + (firstFix.params || ''), 'success'); + this.terminal.executeCommand('loadmod ' + safeParams); + this.terminal.print(' ✅ Applied: loadmod ' + safeParams, 'success'); } else if (firstFix.action === 'test-net' && this.terminal) { this.terminal.executeCommand('test-net'); this.terminal.print(' ✅ Applied: test-net', 'success'); @@ -19788,6 +19821,106 @@ class DebugSupervisorModule { this.terminal.print(' Quota: ' + (this._checkQuota() ? '✅ available' : '🔴 low'), this._checkQuota() ? 'success' : 'error'); } + // ── Sync to Backend ── + + _getSyncUrl() { + try { + return localStorage.getItem('webx11_debug_sync_url') || 'https://webx11.duckdns.org/spaces/newos4/api/debug/ingest.php'; + } catch (e) { + return 'https://webx11.duckdns.org/spaces/newos4/api/debug/ingest.php'; + } + } + + async _syncToBackend() { + if (!this._healthy) return; + const db = this._errorDB.errors; + const keys = Object.keys(db); + if (keys.length === 0) return; + + const payload = { + version: window.NEWOS4_VERSION || 'v4.x', + session: { + id: this._sessionId, + modules: this.terminal?.moduleManager ? Object.keys(this.terminal.moduleManager.modules) : [], + }, + errors: keys.map(k => ({ + hash: k, + message: db[k].message, + type: db[k].type, + severity: db[k].severity, + category: db[k].category, + source: db[k].source, + module: db[k].module, + stack: db[k].stack, + count: db[k].count, + firstSeen: new Date(db[k].firstSeen).toISOString(), + lastSeen: new Date(db[k].lastSeen).toISOString(), + })), + }; + + try { + const resp = await fetch(this._getSyncUrl(), { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + signal: AbortSignal.timeout(10000), + }); + if (resp.ok) { + const result = await resp.json(); + if (result.success) { + const sent = keys.length; + const accepted = result.ingested || 0; + if (accepted < sent) { + console.warn('[DebugSupervisor] Sync truncated: sent ' + sent + ' errors, server accepted ' + accepted + ' (max ' + (result.total_errors || '?') + ' total)'); + } else { + console.log('[DebugSupervisor] Synced ' + accepted + ' errors to backend'); + } + this._lastSyncOk = Date.now(); + return true; + } + } + console.warn('[DebugSupervisor] Sync returned HTTP ' + resp.status); + return false; + } catch (e) { + console.warn('[DebugSupervisor] Sync failed: ' + e.message); + return false; + } + } + + _cmdSync(args) { + const url = (args && args[0]) ? args[0] : null; + if (url) { + try { + localStorage.setItem('webx11_debug_sync_url', url); + this.terminal.print('✅ Sync URL set to: ' + url, 'success'); + } catch (e) { + this.terminal.print('❌ Failed to save sync URL', 'error'); + } + return; + } + this.terminal.print('🔄 Syncing errors to backend...', 'info'); + this._syncToBackend().then(ok => { + if (ok) { + this.terminal.print('✅ Sync complete', 'success'); + } else { + this.terminal.print('❌ Sync failed', 'error'); + } + }); + } + + _cmdSyncUrl(args) { + if (args && args[0]) { + try { + localStorage.setItem('webx11_debug_sync_url', args[0]); + this.terminal.print('✅ Sync URL set to: ' + args[0], 'success'); + } catch (e) { + this.terminal.print('❌ Failed to save sync URL', 'error'); + } + } else { + this.terminal.print('Current sync URL: ' + this._getSyncUrl(), 'info'); + } + } + // ── Dashboard Data ── getDashboardData() { diff --git a/modules/core/module-debug-supervisor.js b/modules/core/module-debug-supervisor.js index 15fe5d4..fc6a919 100644 --- a/modules/core/module-debug-supervisor.js +++ b/modules/core/module-debug-supervisor.js @@ -39,6 +39,8 @@ class DebugSupervisorModule { 'debug-trends': 'debug-trends [days] — Error frequency over time (default: 7)', 'debug-fix': 'debug-fix — Suggest and optionally apply fix for an error', 'debug-health': 'debug-health — Check supervisor module health status', + 'debug-sync': 'debug-sync [url] — Sync errors to backend API (or set sync URL)', + 'debug-sync-url': 'debug-sync-url [url] — View or set the backend sync endpoint', }; } @@ -49,6 +51,8 @@ class DebugSupervisorModule { this.commands['debug-trends'] = (args) => this._cmdTrends(args); this.commands['debug-fix'] = (args) => this._cmdFix(args); this.commands['debug-health'] = () => this._cmdHealth(); + this.commands['debug-sync'] = (args) => this._cmdSync(args); + this.commands['debug-sync-url'] = (args) => this._cmdSyncUrl(args); } seed() { @@ -58,6 +62,36 @@ class DebugSupervisorModule { init() { this._loadDB(); this._installInterceptors(); + // Start periodic sync (every 5 minutes) + this._syncInterval = setInterval(() => this._syncToBackend(), 300000); + // Also sync on first load after a short delay + setTimeout(() => this._syncToBackend(), 5000); + } + + destroy() { + // Clear sync interval + if (this._syncInterval) { + clearInterval(this._syncInterval); + this._syncInterval = null; + } + // Restore original console.error + if (this._originalConsole.error) { + console.error = this._originalConsole.error; + } + // Restore original window.onerror + if (this._originalOnError) { + window.onerror = this._originalOnError; + } + // Restore original fetch + if (this._originalFetch) { + window.fetch = this._originalFetch; + } + // Remove unhandledrejection listener (stored for cleanup) + if (this._rejectionHandler) { + window.removeEventListener('unhandledrejection', this._rejectionHandler); + } + this._interceptorInstalled = false; + this._healthy = false; } // ── Error Database ── @@ -127,11 +161,7 @@ class DebugSupervisorModule { _checkQuota() { try { - const total = 0; - for (const key in localStorage) { - // Estimate: key + value length - } - // Simple check: try writing a test key + // Test localStorage is writable const testKey = '__quota_test__'; localStorage.setItem(testKey, '1'); localStorage.removeItem(testKey); @@ -165,7 +195,7 @@ class DebugSupervisorModule { _detectSeverity(type, message) { if (type === 'SyntaxError' || type === 'ReferenceError' || type === 'quota') return 'fatal'; - if (type === 'HTTP' && message.includes('5')) return 'error'; + if (type === 'HTTP' && /\b5\d{2}\b/.test(message)) return 'error'; if (type === 'timeout' || type === 'security') return 'error'; if (type === 'tool') return 'warning'; return 'error'; @@ -222,10 +252,11 @@ class DebugSupervisorModule { // Unhandled rejections this._originalOnRejection = window.onunhandledrejection; - window.addEventListener('unhandledrejection', function(e) { + this._rejectionHandler = function(e) { const msg = e.reason ? (e.reason.message || String(e.reason)) : 'Unhandled Promise rejection'; self._recordError(msg, 'unhandledrejection', e.reason ? e.reason.stack : null); - }); + }; + window.addEventListener('unhandledrejection', this._rejectionHandler); // Fetch failures this._originalFetch = window.fetch; @@ -636,9 +667,11 @@ class DebugSupervisorModule { if (!fix.fixes || fix.fixes.length === 0) return; const firstFix = fix.fixes[0]; try { + // Sanitize params: only allow alphanumeric, hyphens, underscores, dots + const safeParams = (firstFix.params || '').replace(/[^a-zA-Z0-9_\-\.]/g, ''); if (firstFix.action === 'loadmod' && this.terminal) { - this.terminal.executeCommand('loadmod ' + (firstFix.params || '')); - this.terminal.print(' ✅ Applied: loadmod ' + (firstFix.params || ''), 'success'); + this.terminal.executeCommand('loadmod ' + safeParams); + this.terminal.print(' ✅ Applied: loadmod ' + safeParams, 'success'); } else if (firstFix.action === 'test-net' && this.terminal) { this.terminal.executeCommand('test-net'); this.terminal.print(' ✅ Applied: test-net', 'success'); @@ -663,6 +696,106 @@ class DebugSupervisorModule { this.terminal.print(' Quota: ' + (this._checkQuota() ? '✅ available' : '🔴 low'), this._checkQuota() ? 'success' : 'error'); } + // ── Sync to Backend ── + + _getSyncUrl() { + try { + return localStorage.getItem('webx11_debug_sync_url') || 'https://webx11.duckdns.org/spaces/newos4/api/debug/ingest.php'; + } catch (e) { + return 'https://webx11.duckdns.org/spaces/newos4/api/debug/ingest.php'; + } + } + + async _syncToBackend() { + if (!this._healthy) return; + const db = this._errorDB.errors; + const keys = Object.keys(db); + if (keys.length === 0) return; + + const payload = { + version: window.NEWOS4_VERSION || 'v4.x', + session: { + id: this._sessionId, + modules: this.terminal?.moduleManager ? Object.keys(this.terminal.moduleManager.modules) : [], + }, + errors: keys.map(k => ({ + hash: k, + message: db[k].message, + type: db[k].type, + severity: db[k].severity, + category: db[k].category, + source: db[k].source, + module: db[k].module, + stack: db[k].stack, + count: db[k].count, + firstSeen: new Date(db[k].firstSeen).toISOString(), + lastSeen: new Date(db[k].lastSeen).toISOString(), + })), + }; + + try { + const resp = await fetch(this._getSyncUrl(), { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + signal: AbortSignal.timeout(10000), + }); + if (resp.ok) { + const result = await resp.json(); + if (result.success) { + const sent = keys.length; + const accepted = result.ingested || 0; + if (accepted < sent) { + console.warn('[DebugSupervisor] Sync truncated: sent ' + sent + ' errors, server accepted ' + accepted + ' (max ' + (result.total_errors || '?') + ' total)'); + } else { + console.log('[DebugSupervisor] Synced ' + accepted + ' errors to backend'); + } + this._lastSyncOk = Date.now(); + return true; + } + } + console.warn('[DebugSupervisor] Sync returned HTTP ' + resp.status); + return false; + } catch (e) { + console.warn('[DebugSupervisor] Sync failed: ' + e.message); + return false; + } + } + + _cmdSync(args) { + const url = (args && args[0]) ? args[0] : null; + if (url) { + try { + localStorage.setItem('webx11_debug_sync_url', url); + this.terminal.print('✅ Sync URL set to: ' + url, 'success'); + } catch (e) { + this.terminal.print('❌ Failed to save sync URL', 'error'); + } + return; + } + this.terminal.print('🔄 Syncing errors to backend...', 'info'); + this._syncToBackend().then(ok => { + if (ok) { + this.terminal.print('✅ Sync complete', 'success'); + } else { + this.terminal.print('❌ Sync failed', 'error'); + } + }); + } + + _cmdSyncUrl(args) { + if (args && args[0]) { + try { + localStorage.setItem('webx11_debug_sync_url', args[0]); + this.terminal.print('✅ Sync URL set to: ' + args[0], 'success'); + } catch (e) { + this.terminal.print('❌ Failed to save sync URL', 'error'); + } + } else { + this.terminal.print('Current sync URL: ' + this._getSyncUrl(), 'info'); + } + } + // ── Dashboard Data ── getDashboardData() { -- cgit v1.2.3