mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-07 03:56:55 +03:00
feat: add local DNS availability check and display in UI
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
'require ui';
|
'require ui';
|
||||||
'require network';
|
'require network';
|
||||||
'require fs';
|
'require fs';
|
||||||
|
'require uci';
|
||||||
|
|
||||||
const STATUS_COLORS = {
|
const STATUS_COLORS = {
|
||||||
SUCCESS: '#4caf50',
|
SUCCESS: '#4caf50',
|
||||||
@@ -90,20 +91,24 @@ function createConfigSection(section, map, network) {
|
|||||||
|
|
||||||
if (cfgvalue) {
|
if (cfgvalue) {
|
||||||
try {
|
try {
|
||||||
// Extract only the active configuration (first non-comment line)
|
|
||||||
const activeConfig = cfgvalue.split('\n')
|
const activeConfig = cfgvalue.split('\n')
|
||||||
.map(line => line.trim())
|
.map(line => line.trim())
|
||||||
.find(line => line && !line.startsWith('//'));
|
.find(line => line && !line.startsWith('//'));
|
||||||
|
|
||||||
if (activeConfig) {
|
if (activeConfig) {
|
||||||
|
if (activeConfig.includes('#')) {
|
||||||
const label = activeConfig.split('#').pop() || 'unnamed';
|
const label = activeConfig.split('#').pop() || 'unnamed';
|
||||||
const decodedLabel = decodeURIComponent(label);
|
const decodedLabel = decodeURIComponent(label);
|
||||||
const descDiv = E('div', { 'class': 'cbi-value-description' }, _('Current config: ') + decodedLabel);
|
const descDiv = E('div', { 'class': 'cbi-value-description' }, _('Current config: ') + decodedLabel);
|
||||||
container.appendChild(descDiv);
|
container.appendChild(descDiv);
|
||||||
|
} else {
|
||||||
|
const descDiv = E('div', { 'class': 'cbi-value-description' }, _('Config without description'));
|
||||||
|
container.appendChild(descDiv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error parsing config label:', 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);
|
container.appendChild(descDiv);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -121,7 +126,6 @@ function createConfigSection(section, map, network) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get the first non-comment line as the active configuration
|
|
||||||
const activeConfig = value.split('\n')
|
const activeConfig = value.split('\n')
|
||||||
.map(line => line.trim())
|
.map(line => line.trim())
|
||||||
.find(line => line && !line.startsWith('//'));
|
.find(line => line && !line.startsWith('//'));
|
||||||
@@ -663,9 +667,8 @@ const createStatusPanel = (title, status, buttons) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Update the status section creation
|
// 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' }, [
|
return E('div', { 'class': 'cbi-section' }, [
|
||||||
E('h3', {}, _('Service Status')),
|
|
||||||
E('div', { 'class': 'table', style: 'display: flex; gap: 20px;' }, [
|
E('div', { 'class': 'table', style: 'display: flex; gap: 20px;' }, [
|
||||||
// Podkop Status Panel
|
// Podkop Status Panel
|
||||||
createStatusPanel('Podkop Status', podkopStatus, [
|
createStatusPanel('Podkop Status', podkopStatus, [
|
||||||
@@ -755,16 +758,22 @@ let createStatusSection = function (podkopStatus, singboxStatus, podkop, luci, s
|
|||||||
E('div', { style: 'margin-bottom: 5px;' }, [
|
E('div', { style: 'margin-bottom: 5px;' }, [
|
||||||
E('strong', {}, _('DNS Status')),
|
E('strong', {}, _('DNS Status')),
|
||||||
E('br'),
|
E('br'),
|
||||||
E('span', { style: `color: ${dnsStatus.color}` }, [
|
E('span', { style: `color: ${dnsStatus.remote.color}` }, [
|
||||||
dnsStatus.state === 'available' ? '✔' : dnsStatus.state === 'unavailable' ? '✘' : '!',
|
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: 10px;' }, [
|
||||||
E('div', { style: 'margin-bottom: 5px;' }, [
|
E('div', { style: 'margin-bottom: 5px;' }, [
|
||||||
E('strong', {}, _('Main config')),
|
E('strong', {}, configName),
|
||||||
E('br'),
|
E('br'),
|
||||||
E('span', { style: `color: ${bypassStatus.color}` }, [
|
E('span', { style: `color: ${bypassStatus.color}` }, [
|
||||||
bypassStatus.state === 'working' ? '✔' : bypassStatus.state === 'not_working' ? '✘' : '!',
|
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({
|
return view.extend({
|
||||||
async render() {
|
async render() {
|
||||||
document.head.insertAdjacentHTML('beforeend', `
|
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() {
|
async function updateDiagnostics() {
|
||||||
try {
|
try {
|
||||||
const [
|
const [
|
||||||
@@ -1219,7 +1238,31 @@ return view.extend({
|
|||||||
const container = document.getElementById('diagnostics-status');
|
const container = document.getElementById('diagnostics-status');
|
||||||
if (!container) return;
|
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.innerHTML = '';
|
||||||
container.appendChild(statusSection);
|
container.appendChild(statusSection);
|
||||||
|
|
||||||
@@ -1238,6 +1281,22 @@ return view.extend({
|
|||||||
fakeipCLIStatus.message
|
fakeipCLIStatus.message
|
||||||
]).outerHTML;
|
]).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) {
|
} catch (e) {
|
||||||
const container = document.getElementById('diagnostics-status');
|
const container = document.getElementById('diagnostics-status');
|
||||||
if (container) {
|
if (container) {
|
||||||
|
|||||||
@@ -2027,6 +2027,8 @@ check_dns_available() {
|
|||||||
local dns_server=$(uci get podkop.main.dns_server 2>/dev/null)
|
local dns_server=$(uci get podkop.main.dns_server 2>/dev/null)
|
||||||
local is_available=0
|
local is_available=0
|
||||||
local status="unavailable"
|
local status="unavailable"
|
||||||
|
local local_dns_working=0
|
||||||
|
local local_dns_status="unavailable"
|
||||||
|
|
||||||
if [ "$dns_type" = "doh" ]; then
|
if [ "$dns_type" = "doh" ]; then
|
||||||
# Different DoH providers use different endpoints and formats
|
# Different DoH providers use different endpoints and formats
|
||||||
@@ -2058,7 +2060,13 @@ check_dns_available() {
|
|||||||
fi
|
fi
|
||||||
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() {
|
sing_box_add_secure_dns_probe_domain() {
|
||||||
|
|||||||
Reference in New Issue
Block a user