diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js index 83e2b82..f7df280 100644 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js +++ b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js @@ -12,6 +12,8 @@ const STATUS_COLORS = { WARNING: '#ff9800' }; +const ERROR_POLL_INTERVAL = 5000; // 5 seconds + async function safeExec(command, args = [], timeout = 7000) { try { const controller = new AbortController(); @@ -850,6 +852,84 @@ function checkDNSAvailability() { }); } +async function getPodkopErrors() { + try { + const result = await safeExec('/usr/bin/podkop', ['check_logs']); + if (!result || !result.stdout) return []; + + const logs = result.stdout.split('\n'); + const errors = logs.filter(log => + // log.includes('saved for future filters') || + log.includes('[critical]') + ); + + console.log('Found errors:', errors); + return errors; + } catch (error) { + console.error('Error getting podkop logs:', error); + return []; + } +} + +let errorPollTimer = null; +let lastErrorsSet = new Set(); +let isInitialCheck = true; + +function showErrorNotification(error, isMultiple = false) { + const notificationContent = E('div', { 'class': 'alert-message error' }, [ + E('pre', { 'class': 'error-log' }, error) + ]); + + ui.addNotification(null, notificationContent); +} + +function startErrorPolling() { + if (errorPollTimer) { + clearInterval(errorPollTimer); + } + + async function checkErrors() { + const result = await safeExec('/usr/bin/podkop', ['check_logs']); + if (!result || !result.stdout) return; + + const logs = result.stdout; + + const errorLines = logs.split('\n').filter(line => + // line.includes('saved for future filters') || + line.includes('[critical]') + ); + + if (errorLines.length > 0) { + const currentErrors = new Set(errorLines); + + if (isInitialCheck) { + if (errorLines.length > 0) { + showErrorNotification(errorLines.join('\n'), true); + } + isInitialCheck = false; + } else { + const newErrors = [...currentErrors].filter(error => !lastErrorsSet.has(error)); + + newErrors.forEach(error => { + showErrorNotification(error, false); + }); + } + lastErrorsSet = currentErrors; + } + } + + checkErrors(); + + errorPollTimer = setInterval(checkErrors, ERROR_POLL_INTERVAL); +} + +function stopErrorPolling() { + if (errorPollTimer) { + clearInterval(errorPollTimer); + errorPollTimer = null; + } +} + return view.extend({ async render() { document.head.insertAdjacentHTML('beforeend', ` @@ -1348,8 +1428,10 @@ return view.extend({ const diagnosticsContainer = document.getElementById('diagnostics-status'); if (document.hidden) { stopDiagnosticsUpdates(); + stopErrorPolling(); } else if (diagnosticsContainer && diagnosticsContainer.hasAttribute('data-loading')) { startDiagnosticsUpdates(); + startErrorPolling(); } }); @@ -1360,6 +1442,7 @@ return view.extend({ if (!this.hasAttribute('data-loading')) { this.setAttribute('data-loading', 'true'); startDiagnosticsUpdates(); + startErrorPolling(); } }); } @@ -1375,9 +1458,11 @@ return view.extend({ if (container && !container.hasAttribute('data-loading')) { container.setAttribute('data-loading', 'true'); startDiagnosticsUpdates(); + startErrorPolling(); } } else { stopDiagnosticsUpdates(); + stopErrorPolling(); } } }); @@ -1388,6 +1473,7 @@ return view.extend({ if (container && !container.hasAttribute('data-loading')) { container.setAttribute('data-loading', 'true'); startDiagnosticsUpdates(); + startErrorPolling(); } } } diff --git a/podkop/files/usr/bin/podkop b/podkop/files/usr/bin/podkop index e733920..e33707b 100755 --- a/podkop/files/usr/bin/podkop +++ b/podkop/files/usr/bin/podkop @@ -45,6 +45,7 @@ nolog() { } start() { + log "Starting podkop" migration config_foreach process_validate_service @@ -1857,12 +1858,24 @@ check_fakeip() { check_logs() { nolog "Showing podkop logs from system journal..." - if command -v logread >/dev/null 2>&1; then - logread -e podkop | tail -n 50 - else + if ! command -v logread >/dev/null 2>&1; then nolog "Error: logread command not found" return 1 fi + + # Get all logs first + local all_logs=$(logread) + + # Find the last occurrence of "Starting podkop" + local start_line=$(echo "$all_logs" | grep -n "podkop.*Starting podkop" | tail -n 1 | cut -d: -f1) + + if [ -z "$start_line" ]; then + nolog "No 'Starting podkop' message found in logs" + return 1 + fi + + # Output all logs from the last start + echo "$all_logs" | tail -n +"$start_line" } show_sing_box_config() { @@ -1918,6 +1931,7 @@ show_config() { -e 's/\(ss:\/\/[^@]*@\)/ss:\/\/MASKED@/g' \ -e 's/\(pbk=[^&]*\)/pbk=MASKED/g' \ -e 's/\(sid=[^&]*\)/sid=MASKED/g' \ + -e 's/\(option dns_server '\''[^'\'']*\.dns\.nextdns\.io'\''\)/option dns_server '\''MASKED.dns.nextdns.io'\''/g' \ > "$tmp_config" cat "$tmp_config"