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 b824e3a..d150896 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 @@ -4,6 +4,7 @@ 'require ui'; 'require network'; 'require fs'; +'require uci'; const STATUS_COLORS = { SUCCESS: '#4caf50', @@ -90,20 +91,24 @@ function createConfigSection(section, map, network) { if (cfgvalue) { try { - // Extract only the active configuration (first non-comment line) const activeConfig = cfgvalue.split('\n') .map(line => line.trim()) .find(line => line && !line.startsWith('//')); if (activeConfig) { - const label = activeConfig.split('#').pop() || 'unnamed'; - const decodedLabel = decodeURIComponent(label); - const descDiv = E('div', { 'class': 'cbi-value-description' }, _('Current config: ') + decodedLabel); - container.appendChild(descDiv); + if (activeConfig.includes('#')) { + const label = activeConfig.split('#').pop() || 'unnamed'; + const decodedLabel = decodeURIComponent(label); + const descDiv = E('div', { 'class': 'cbi-value-description' }, _('Current config: ') + decodedLabel); + container.appendChild(descDiv); + } else { + const descDiv = E('div', { 'class': 'cbi-value-description' }, _('Config without description')); + container.appendChild(descDiv); + } } } catch (e) { console.error('Error parsing config label:', e); - const descDiv = E('div', { 'class': 'cbi-value-description' }, _('Current config: ') + (cfgvalue.split('#').pop() || 'unnamed')); + const descDiv = E('div', { 'class': 'cbi-value-description' }, _('Config without description')); container.appendChild(descDiv); } } else { @@ -121,7 +126,6 @@ function createConfigSection(section, map, network) { } try { - // Get the first non-comment line as the active configuration const activeConfig = value.split('\n') .map(line => line.trim()) .find(line => line && !line.startsWith('//')); @@ -663,9 +667,8 @@ const createStatusPanel = (title, status, buttons) => { }; // Update the status section creation -let createStatusSection = function (podkopStatus, singboxStatus, podkop, luci, singbox, system, fakeipStatus, fakeipCLIStatus, dnsStatus, bypassStatus) { +let createStatusSection = function (podkopStatus, singboxStatus, podkop, luci, singbox, system, fakeipStatus, fakeipCLIStatus, dnsStatus, bypassStatus, configName) { return E('div', { 'class': 'cbi-section' }, [ - E('h3', {}, _('Service Status')), E('div', { 'class': 'table', style: 'display: flex; gap: 20px;' }, [ // Podkop Status Panel createStatusPanel('Podkop Status', podkopStatus, [ @@ -755,16 +758,22 @@ let createStatusSection = function (podkopStatus, singboxStatus, podkop, luci, s E('div', { style: 'margin-bottom: 5px;' }, [ E('strong', {}, _('DNS Status')), E('br'), - E('span', { style: `color: ${dnsStatus.color}` }, [ - dnsStatus.state === 'available' ? '✔' : dnsStatus.state === 'unavailable' ? '✘' : '!', + E('span', { style: `color: ${dnsStatus.remote.color}` }, [ + dnsStatus.remote.state === 'available' ? '✔' : dnsStatus.remote.state === 'unavailable' ? '✘' : '!', ' ', - dnsStatus.message + dnsStatus.remote.message + ]), + E('br'), + E('span', { style: `color: ${dnsStatus.local.color}` }, [ + dnsStatus.local.state === 'available' ? '✔' : dnsStatus.local.state === 'unavailable' ? '✘' : '!', + ' ', + dnsStatus.local.message ]) ]) ]), E('div', { style: 'margin-bottom: 10px;' }, [ E('div', { style: 'margin-bottom: 5px;' }, [ - E('strong', {}, _('Main config')), + E('strong', {}, configName), E('br'), E('span', { style: `color: ${bypassStatus.color}` }, [ bypassStatus.state === 'working' ? '✔' : bypassStatus.state === 'not_working' ? '✘' : '!', @@ -789,6 +798,39 @@ let createStatusSection = function (podkopStatus, singboxStatus, podkop, luci, s ]); }; +function checkDNSAvailability() { + const createStatus = (state, message, color) => ({ + state, + message: _(message), + color: STATUS_COLORS[color] + }); + + return new Promise(async (resolve) => { + try { + const dnsStatusResult = await safeExec('/usr/bin/podkop', ['check_dns_available']); + const dnsStatus = JSON.parse(dnsStatusResult.stdout || '{"dns_type":"unknown","dns_server":"unknown","is_available":0,"status":"unknown","local_dns_working":0,"local_dns_status":"unknown"}'); + + const remoteStatus = dnsStatus.is_available ? + createStatus('available', `${dnsStatus.dns_type.toUpperCase()} (${dnsStatus.dns_server}) available`, 'SUCCESS') : + createStatus('unavailable', `${dnsStatus.dns_type.toUpperCase()} (${dnsStatus.dns_server}) unavailable`, 'ERROR'); + + const localStatus = dnsStatus.local_dns_working ? + createStatus('available', 'Router DNS working', 'SUCCESS') : + createStatus('unavailable', 'Router DNS not working', 'ERROR'); + + return resolve({ + remote: remoteStatus, + local: localStatus + }); + } catch (error) { + return resolve({ + remote: createStatus('error', 'DNS check error', 'WARNING'), + local: createStatus('error', 'DNS check error', 'WARNING') + }); + } + }); +} + return view.extend({ async render() { document.head.insertAdjacentHTML('beforeend', ` @@ -1164,29 +1206,6 @@ return view.extend({ }); } - function checkDNSAvailability() { - const createStatus = (state, message, color) => ({ - state, - message: _(message), - color: STATUS_COLORS[color] - }); - - return new Promise(async (resolve) => { - try { - const dnsStatusResult = await safeExec('/usr/bin/podkop', ['check_dns_available']); - const dnsStatus = JSON.parse(dnsStatusResult.stdout || '{"dns_type":"unknown","dns_server":"unknown","is_available":0,"status":"unknown"}'); - - if (dnsStatus.is_available) { - return resolve(createStatus('available', `${dnsStatus.dns_type.toUpperCase()} (${dnsStatus.dns_server}) available`, 'SUCCESS')); - } else { - return resolve(createStatus('unavailable', `${dnsStatus.dns_type.toUpperCase()} (${dnsStatus.dns_server}) unavailable`, 'ERROR')); - } - } catch (error) { - return resolve(createStatus('error', 'DNS check error', 'WARNING')); - } - }); - } - async function updateDiagnostics() { try { const [ @@ -1219,7 +1238,31 @@ return view.extend({ const container = document.getElementById('diagnostics-status'); if (!container) return; - const statusSection = createStatusSection(parsedPodkopStatus, parsedSingboxStatus, podkop, luci, singbox, system, fakeipStatus, fakeipCLIStatus, dnsStatus, bypassStatus); + let configName = _('Main config'); + try { + const data = await uci.load('podkop'); + const proxyString = uci.get('podkop', 'main', 'proxy_string'); + + if (proxyString) { + const activeConfig = proxyString.split('\n') + .map(line => line.trim()) + .find(line => line && !line.startsWith('//')); + + if (activeConfig) { + if (activeConfig.includes('#')) { + const label = activeConfig.split('#').pop() || 'unnamed'; + configName = _('Config: ') + decodeURIComponent(label); + } else { + configName = _('Main config'); + } + } + } + } catch (e) { + console.error('Error getting config name from UCI:', e); + } + + // Create a modified statusSection function with the configName + const statusSection = createStatusSection(parsedPodkopStatus, parsedSingboxStatus, podkop, luci, singbox, system, fakeipStatus, fakeipCLIStatus, dnsStatus, bypassStatus, configName); container.innerHTML = ''; container.appendChild(statusSection); @@ -1238,6 +1281,22 @@ return view.extend({ fakeipCLIStatus.message ]).outerHTML; } + + const dnsRemoteElement = document.getElementById('dns-remote-status'); + if (dnsRemoteElement) { + dnsRemoteElement.innerHTML = E('span', { 'style': `color: ${dnsStatus.remote.color}` }, [ + dnsStatus.remote.state === 'available' ? '✔ ' : dnsStatus.remote.state === 'unavailable' ? '✘ ' : '! ', + dnsStatus.remote.message + ]).outerHTML; + } + + const dnsLocalElement = document.getElementById('dns-local-status'); + if (dnsLocalElement) { + dnsLocalElement.innerHTML = E('span', { 'style': `color: ${dnsStatus.local.color}` }, [ + dnsStatus.local.state === 'available' ? '✔ ' : dnsStatus.local.state === 'unavailable' ? '✘ ' : '! ', + dnsStatus.local.message + ]).outerHTML; + } } catch (e) { const container = document.getElementById('diagnostics-status'); if (container) { diff --git a/podkop/files/usr/bin/podkop b/podkop/files/usr/bin/podkop index dcef9bd..4195579 100755 --- a/podkop/files/usr/bin/podkop +++ b/podkop/files/usr/bin/podkop @@ -2027,6 +2027,8 @@ check_dns_available() { local dns_server=$(uci get podkop.main.dns_server 2>/dev/null) local is_available=0 local status="unavailable" + local local_dns_working=0 + local local_dns_status="unavailable" if [ "$dns_type" = "doh" ]; then # Different DoH providers use different endpoints and formats @@ -2058,7 +2060,13 @@ check_dns_available() { fi fi - echo "{\"dns_type\":\"$dns_type\",\"dns_server\":\"$dns_server\",\"is_available\":$is_available,\"status\":\"$status\"}" + # Check if local DNS resolver is working + if nslookup -timeout=2 $TEST_DOMAIN 127.0.0.1 >/dev/null 2>&1; then + local_dns_working=1 + local_dns_status="available" + fi + + echo "{\"dns_type\":\"$dns_type\",\"dns_server\":\"$dns_server\",\"is_available\":$is_available,\"status\":\"$status\",\"local_dns_working\":$local_dns_working,\"local_dns_status\":\"$local_dns_status\"}" } sing_box_add_secure_dns_probe_domain() {