mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-08 20:46:50 +03:00
fix: run prettier for luci app js assets
This commit is contained in:
@@ -7,22 +7,46 @@
|
||||
function createAdditionalSection(mainSection) {
|
||||
let o = mainSection.tab('additional', _('Additional Settings'));
|
||||
|
||||
o = mainSection.taboption('additional', form.Flag, 'yacd', _('Yacd enable'), `<a href="${main.getBaseUrl()}:9090/ui" target="_blank">${main.getBaseUrl()}:9090/ui</a>`);
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.Flag,
|
||||
'yacd',
|
||||
_('Yacd enable'),
|
||||
`<a href="${main.getBaseUrl()}:9090/ui" target="_blank">${main.getBaseUrl()}:9090/ui</a>`,
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
|
||||
o = mainSection.taboption('additional', form.Flag, 'exclude_ntp', _('Exclude NTP'), _('Allows you to exclude NTP protocol traffic from the tunnel'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.Flag,
|
||||
'exclude_ntp',
|
||||
_('Exclude NTP'),
|
||||
_('Allows you to exclude NTP protocol traffic from the tunnel'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
|
||||
o = mainSection.taboption('additional', form.Flag, 'quic_disable', _('QUIC disable'), _('For issues with the video stream'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.Flag,
|
||||
'quic_disable',
|
||||
_('QUIC disable'),
|
||||
_('For issues with the video stream'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
|
||||
o = mainSection.taboption('additional', form.ListValue, 'update_interval', _('List Update Frequency'), _('Select how often the lists will be updated'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.ListValue,
|
||||
'update_interval',
|
||||
_('List Update Frequency'),
|
||||
_('Select how often the lists will be updated'),
|
||||
);
|
||||
Object.entries(main.UPDATE_INTERVAL_OPTIONS).forEach(([key, label]) => {
|
||||
o.value(key, _(label));
|
||||
});
|
||||
@@ -30,7 +54,13 @@ function createAdditionalSection(mainSection) {
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
|
||||
o = mainSection.taboption('additional', form.ListValue, 'dns_type', _('DNS Protocol Type'), _('Select DNS protocol to use'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.ListValue,
|
||||
'dns_type',
|
||||
_('DNS Protocol Type'),
|
||||
_('Select DNS protocol to use'),
|
||||
);
|
||||
o.value('doh', _('DNS over HTTPS (DoH)'));
|
||||
o.value('dot', _('DNS over TLS (DoT)'));
|
||||
o.value('udp', _('UDP (Unprotected DNS)'));
|
||||
@@ -38,7 +68,13 @@ function createAdditionalSection(mainSection) {
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
|
||||
o = mainSection.taboption('additional', form.Value, 'dns_server', _('DNS Server'), _('Select or enter DNS server address'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.Value,
|
||||
'dns_server',
|
||||
_('DNS Server'),
|
||||
_('Select or enter DNS server address'),
|
||||
);
|
||||
Object.entries(main.DNS_SERVER_OPTIONS).forEach(([key, label]) => {
|
||||
o.value(key, _(label));
|
||||
});
|
||||
@@ -55,7 +91,15 @@ function createAdditionalSection(mainSection) {
|
||||
return _(validation.message);
|
||||
};
|
||||
|
||||
o = mainSection.taboption('additional', form.Value, 'bootstrap_dns_server', _('Bootstrap DNS server'), _('The DNS server used to look up the IP address of an upstream DNS server'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.Value,
|
||||
'bootstrap_dns_server',
|
||||
_('Bootstrap DNS server'),
|
||||
_(
|
||||
'The DNS server used to look up the IP address of an upstream DNS server',
|
||||
),
|
||||
);
|
||||
Object.entries(main.BOOTSTRAP_DNS_SERVER_OPTIONS).forEach(([key, label]) => {
|
||||
o.value(key, _(label));
|
||||
});
|
||||
@@ -72,7 +116,13 @@ function createAdditionalSection(mainSection) {
|
||||
return _(validation.message);
|
||||
};
|
||||
|
||||
o = mainSection.taboption('additional', form.Value, 'dns_rewrite_ttl', _('DNS Rewrite TTL'), _('Time in seconds for DNS record caching (default: 60)'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.Value,
|
||||
'dns_rewrite_ttl',
|
||||
_('DNS Rewrite TTL'),
|
||||
_('Time in seconds for DNS record caching (default: 60)'),
|
||||
);
|
||||
o.default = '60';
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
@@ -89,16 +139,35 @@ function createAdditionalSection(mainSection) {
|
||||
return true;
|
||||
};
|
||||
|
||||
o = mainSection.taboption('additional', form.ListValue, 'config_path', _('Config File Path'), _('Select path for sing-box config file. Change this ONLY if you know what you are doing'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.ListValue,
|
||||
'config_path',
|
||||
_('Config File Path'),
|
||||
_(
|
||||
'Select path for sing-box config file. Change this ONLY if you know what you are doing',
|
||||
),
|
||||
);
|
||||
o.value('/etc/sing-box/config.json', 'Flash (/etc/sing-box/config.json)');
|
||||
o.value('/tmp/sing-box/config.json', 'RAM (/tmp/sing-box/config.json)');
|
||||
o.default = '/etc/sing-box/config.json';
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
|
||||
o = mainSection.taboption('additional', form.Value, 'cache_path', _('Cache File Path'), _('Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.Value,
|
||||
'cache_path',
|
||||
_('Cache File Path'),
|
||||
_(
|
||||
'Select or enter path for sing-box cache file. Change this ONLY if you know what you are doing',
|
||||
),
|
||||
);
|
||||
o.value('/tmp/sing-box/cache.db', 'RAM (/tmp/sing-box/cache.db)');
|
||||
o.value('/usr/share/sing-box/cache.db', 'Flash (/usr/share/sing-box/cache.db)');
|
||||
o.value(
|
||||
'/usr/share/sing-box/cache.db',
|
||||
'Flash (/usr/share/sing-box/cache.db)',
|
||||
);
|
||||
o.default = '/tmp/sing-box/cache.db';
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
@@ -123,7 +192,13 @@ function createAdditionalSection(mainSection) {
|
||||
return true;
|
||||
};
|
||||
|
||||
o = mainSection.taboption('additional', widgets.DeviceSelect, 'iface', _('Source Network Interface'), _('Select the network interface from which the traffic will originate'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
widgets.DeviceSelect,
|
||||
'iface',
|
||||
_('Source Network Interface'),
|
||||
_('Select the network interface from which the traffic will originate'),
|
||||
);
|
||||
o.ucisection = 'main';
|
||||
o.default = 'br-lan';
|
||||
o.noaliases = true;
|
||||
@@ -138,7 +213,7 @@ function createAdditionalSection(mainSection) {
|
||||
}
|
||||
|
||||
// Try to find the device object by its name
|
||||
const device = this.devices.find(dev => dev.getName() === value);
|
||||
const device = this.devices.find((dev) => dev.getName() === value);
|
||||
|
||||
// If no device is found, allow the value
|
||||
if (!device) {
|
||||
@@ -156,12 +231,24 @@ function createAdditionalSection(mainSection) {
|
||||
return !isWireless;
|
||||
};
|
||||
|
||||
o = mainSection.taboption('additional', form.Flag, 'mon_restart_ifaces', _('Interface monitoring'), _('Interface monitoring for bad WAN'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.Flag,
|
||||
'mon_restart_ifaces',
|
||||
_('Interface monitoring'),
|
||||
_('Interface monitoring for bad WAN'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
|
||||
o = mainSection.taboption('additional', widgets.NetworkSelect, 'restart_ifaces', _('Interface for monitoring'), _('Select the WAN interfaces to be monitored'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
widgets.NetworkSelect,
|
||||
'restart_ifaces',
|
||||
_('Interface for monitoring'),
|
||||
_('Select the WAN interfaces to be monitored'),
|
||||
);
|
||||
o.ucisection = 'main';
|
||||
o.depends('mon_restart_ifaces', '1');
|
||||
o.multiple = true;
|
||||
@@ -180,7 +267,13 @@ function createAdditionalSection(mainSection) {
|
||||
return true;
|
||||
};
|
||||
|
||||
o = mainSection.taboption('additional', form.Value, 'procd_reload_delay', _('Interface Monitoring Delay'), _('Delay in milliseconds before reloading podkop after interface UP'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.Value,
|
||||
'procd_reload_delay',
|
||||
_('Interface Monitoring Delay'),
|
||||
_('Delay in milliseconds before reloading podkop after interface UP'),
|
||||
);
|
||||
o.ucisection = 'main';
|
||||
o.depends('mon_restart_ifaces', '1');
|
||||
o.default = '2000';
|
||||
@@ -192,23 +285,47 @@ function createAdditionalSection(mainSection) {
|
||||
return true;
|
||||
};
|
||||
|
||||
o = mainSection.taboption('additional', form.Flag, 'dont_touch_dhcp', _('Dont touch my DHCP!'), _('Podkop will not change the DHCP config'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.Flag,
|
||||
'dont_touch_dhcp',
|
||||
_('Dont touch my DHCP!'),
|
||||
_('Podkop will not change the DHCP config'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
|
||||
o = mainSection.taboption('additional', form.Flag, 'detour', _('Proxy download of lists'), _('Downloading all lists via main Proxy/VPN'));
|
||||
o = mainSection.taboption(
|
||||
'additional',
|
||||
form.Flag,
|
||||
'detour',
|
||||
_('Proxy download of lists'),
|
||||
_('Downloading all lists via main Proxy/VPN'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
|
||||
// Extra IPs and exclusions (main section)
|
||||
o = mainSection.taboption('basic', form.Flag, 'exclude_from_ip_enabled', _('IP for exclusion'), _('Specify local IP addresses that will never use the configured route'));
|
||||
o = mainSection.taboption(
|
||||
'basic',
|
||||
form.Flag,
|
||||
'exclude_from_ip_enabled',
|
||||
_('IP for exclusion'),
|
||||
_('Specify local IP addresses that will never use the configured route'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
|
||||
o = mainSection.taboption('basic', form.DynamicList, 'exclude_traffic_ip', _('Local IPs'), _('Enter valid IPv4 addresses'));
|
||||
o = mainSection.taboption(
|
||||
'basic',
|
||||
form.DynamicList,
|
||||
'exclude_traffic_ip',
|
||||
_('Local IPs'),
|
||||
_('Enter valid IPv4 addresses'),
|
||||
);
|
||||
o.placeholder = 'IP';
|
||||
o.depends('exclude_from_ip_enabled', '1');
|
||||
o.rmempty = false;
|
||||
@@ -216,7 +333,7 @@ function createAdditionalSection(mainSection) {
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
const validation = main.validateIPV4(value);
|
||||
@@ -225,15 +342,21 @@ function createAdditionalSection(mainSection) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
return _(validation.message);
|
||||
};
|
||||
|
||||
o = mainSection.taboption('basic', form.Flag, 'socks5', _('Mixed enable'), _('Browser port: 2080'));
|
||||
o = mainSection.taboption(
|
||||
'basic',
|
||||
form.Flag,
|
||||
'socks5',
|
||||
_('Mixed enable'),
|
||||
_('Browser port: 2080'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = 'main';
|
||||
}
|
||||
|
||||
return baseclass.extend({
|
||||
createAdditionalSection
|
||||
createAdditionalSection,
|
||||
});
|
||||
|
||||
@@ -6,19 +6,30 @@
|
||||
'require view.podkop.main as main';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
|
||||
function createConfigSection(section) {
|
||||
const s = section;
|
||||
|
||||
let o = s.tab('basic', _('Basic Settings'));
|
||||
|
||||
o = s.taboption('basic', form.ListValue, 'mode', _('Connection Type'), _('Select between VPN and Proxy connection methods for traffic routing'));
|
||||
o.value('proxy', ('Proxy'));
|
||||
o.value('vpn', ('VPN'));
|
||||
o.value('block', ('Block'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.ListValue,
|
||||
'mode',
|
||||
_('Connection Type'),
|
||||
_('Select between VPN and Proxy connection methods for traffic routing'),
|
||||
);
|
||||
o.value('proxy', 'Proxy');
|
||||
o.value('vpn', 'VPN');
|
||||
o.value('block', 'Block');
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', form.ListValue, 'proxy_config_type', _('Configuration Type'), _('Select how to configure the proxy'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.ListValue,
|
||||
'proxy_config_type',
|
||||
_('Configuration Type'),
|
||||
_('Select how to configure the proxy'),
|
||||
);
|
||||
o.value('url', _('Connection URL'));
|
||||
o.value('outbound', _('Outbound Config'));
|
||||
o.value('urltest', _('URLTest'));
|
||||
@@ -26,7 +37,13 @@ function createConfigSection(section) {
|
||||
o.depends('mode', 'proxy');
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', form.TextValue, 'proxy_string', _('Proxy Configuration URL'), '');
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.TextValue,
|
||||
'proxy_string',
|
||||
_('Proxy Configuration URL'),
|
||||
'',
|
||||
);
|
||||
o.depends('proxy_config_type', 'url');
|
||||
o.rows = 5;
|
||||
o.wrap = 'soft';
|
||||
@@ -34,43 +51,70 @@ function createConfigSection(section) {
|
||||
o.rmempty = false;
|
||||
o.ucisection = s.section;
|
||||
o.sectionDescriptions = new Map();
|
||||
o.placeholder = 'vless://uuid@server:port?type=tcp&security=tls#main\n// backup ss://method:pass@server:port\n// backup2 vless://uuid@server:port?type=grpc&security=reality#alt\n// backup3 trojan://04agAQapcl@127.0.0.1:33641?type=tcp&security=none#trojan-tcp-none';
|
||||
o.placeholder =
|
||||
'vless://uuid@server:port?type=tcp&security=tls#main\n// backup ss://method:pass@server:port\n// backup2 vless://uuid@server:port?type=grpc&security=reality#alt\n// backup3 trojan://04agAQapcl@127.0.0.1:33641?type=tcp&security=none#trojan-tcp-none';
|
||||
|
||||
o.renderWidget = function (section_id, option_index, cfgvalue) {
|
||||
const original = form.TextValue.prototype.renderWidget.apply(this, [section_id, option_index, cfgvalue]);
|
||||
const original = form.TextValue.prototype.renderWidget.apply(this, [
|
||||
section_id,
|
||||
option_index,
|
||||
cfgvalue,
|
||||
]);
|
||||
const container = E('div', {});
|
||||
container.appendChild(original);
|
||||
|
||||
if (cfgvalue) {
|
||||
try {
|
||||
const activeConfig = cfgvalue.split('\n')
|
||||
.map(line => line.trim())
|
||||
.find(line => line && !line.startsWith('//'));
|
||||
const activeConfig = cfgvalue
|
||||
.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.find((line) => line && !line.startsWith('//'));
|
||||
|
||||
if (activeConfig) {
|
||||
if (activeConfig.includes('#')) {
|
||||
const label = activeConfig.split('#').pop();
|
||||
if (label && label.trim()) {
|
||||
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);
|
||||
} else {
|
||||
const descDiv = E('div', { 'class': 'cbi-value-description' }, _('Config without description'));
|
||||
const descDiv = E(
|
||||
'div',
|
||||
{ class: 'cbi-value-description' },
|
||||
_('Config without description'),
|
||||
);
|
||||
container.appendChild(descDiv);
|
||||
}
|
||||
} else {
|
||||
const descDiv = E('div', { 'class': 'cbi-value-description' }, _('Config without description'));
|
||||
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' }, _('Config without description'));
|
||||
const descDiv = E(
|
||||
'div',
|
||||
{ class: 'cbi-value-description' },
|
||||
_('Config without description'),
|
||||
);
|
||||
container.appendChild(descDiv);
|
||||
}
|
||||
} else {
|
||||
const defaultDesc = E('div', { 'class': 'cbi-value-description' },
|
||||
_('Enter connection string starting with vless:// or ss:// for proxy configuration. Add comments with // for backup configs'));
|
||||
const defaultDesc = E(
|
||||
'div',
|
||||
{ class: 'cbi-value-description' },
|
||||
_(
|
||||
'Enter connection string starting with vless:// or ss:// for proxy configuration. Add comments with // for backup configs',
|
||||
),
|
||||
);
|
||||
container.appendChild(defaultDesc);
|
||||
}
|
||||
|
||||
@@ -80,16 +124,19 @@ function createConfigSection(section) {
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
const activeConfig = value.split('\n')
|
||||
.map(line => line.trim())
|
||||
.find(line => line && !line.startsWith('//'));
|
||||
const activeConfig = value
|
||||
.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.find((line) => line && !line.startsWith('//'));
|
||||
|
||||
if (!activeConfig) {
|
||||
return _('No active configuration found. At least one non-commented line is required.');
|
||||
return _(
|
||||
'No active configuration found. At least one non-commented line is required.',
|
||||
);
|
||||
}
|
||||
|
||||
const validation = main.validateProxyUrl(activeConfig);
|
||||
@@ -98,20 +145,26 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
return _(validation.message);
|
||||
} catch (e) {
|
||||
return `${_('Invalid URL format:')} ${e?.message}`;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.TextValue, 'outbound_json', _('Outbound Configuration'), _('Enter complete outbound configuration in JSON format'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.TextValue,
|
||||
'outbound_json',
|
||||
_('Outbound Configuration'),
|
||||
_('Enter complete outbound configuration in JSON format'),
|
||||
);
|
||||
o.depends('proxy_config_type', 'outbound');
|
||||
o.rows = 10;
|
||||
o.ucisection = s.section;
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
const validation = main.validateOutboundJson(value);
|
||||
@@ -120,10 +173,15 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
return _(validation.message);
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.DynamicList, 'urltest_proxy_links', _('URLTest Proxy Links'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.DynamicList,
|
||||
'urltest_proxy_links',
|
||||
_('URLTest Proxy Links'),
|
||||
);
|
||||
o.depends('proxy_config_type', 'urltest');
|
||||
o.placeholder = 'vless://, ss://, trojan:// links';
|
||||
o.rmempty = false;
|
||||
@@ -133,7 +191,7 @@ function createConfigSection(section) {
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
const validation = main.validateProxyUrl(value);
|
||||
@@ -142,16 +200,28 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
return _(validation.message);
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'ss_uot', _('Shadowsocks UDP over TCP'), _('Apply for SS2022'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.Flag,
|
||||
'ss_uot',
|
||||
_('Shadowsocks UDP over TCP'),
|
||||
_('Apply for SS2022'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.depends('mode', 'proxy');
|
||||
o.rmempty = false;
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', widgets.DeviceSelect, 'interface', _('Network Interface'), _('Select network interface for VPN connection'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
widgets.DeviceSelect,
|
||||
'interface',
|
||||
_('Network Interface'),
|
||||
_('Select network interface for VPN connection'),
|
||||
);
|
||||
o.depends('mode', 'vpn');
|
||||
o.ucisection = s.section;
|
||||
o.noaliases = true;
|
||||
@@ -176,7 +246,7 @@ function createConfigSection(section) {
|
||||
}
|
||||
|
||||
// Try to find the device object with the given name
|
||||
const device = this.devices.find(dev => dev.getName() === value);
|
||||
const device = this.devices.find((dev) => dev.getName() === value);
|
||||
|
||||
// If no device is found, allow the value
|
||||
if (!device) {
|
||||
@@ -193,13 +263,25 @@ function createConfigSection(section) {
|
||||
return !isWireless;
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'domain_resolver_enabled', _('Domain Resolver'), _('Enable built-in DNS resolver for domains handled by this section'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.Flag,
|
||||
'domain_resolver_enabled',
|
||||
_('Domain Resolver'),
|
||||
_('Enable built-in DNS resolver for domains handled by this section'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.depends('mode', 'vpn');
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', form.ListValue, 'domain_resolver_dns_type', _('DNS Protocol Type'), _('Select the DNS protocol type for the domain resolver'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.ListValue,
|
||||
'domain_resolver_dns_type',
|
||||
_('DNS Protocol Type'),
|
||||
_('Select the DNS protocol type for the domain resolver'),
|
||||
);
|
||||
o.value('doh', _('DNS over HTTPS (DoH)'));
|
||||
o.value('dot', _('DNS over TLS (DoT)'));
|
||||
o.value('udp', _('UDP (Unprotected DNS)'));
|
||||
@@ -208,7 +290,13 @@ function createConfigSection(section) {
|
||||
o.depends('domain_resolver_enabled', '1');
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', form.Value, 'domain_resolver_dns_server', _('DNS Server'), _('Select or enter DNS server address'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.Value,
|
||||
'domain_resolver_dns_server',
|
||||
_('DNS Server'),
|
||||
_('Select or enter DNS server address'),
|
||||
);
|
||||
Object.entries(main.DNS_SERVER_OPTIONS).forEach(([key, label]) => {
|
||||
o.value(key, _(label));
|
||||
});
|
||||
@@ -223,15 +311,27 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
return _(validation.message);
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'community_lists_enabled', _('Community Lists'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.Flag,
|
||||
'community_lists_enabled',
|
||||
_('Community Lists'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', form.DynamicList, 'community_lists', _('Service List'), _('Select predefined service for routing') + ' <a href="https://github.com/itdoginfo/allow-domains" target="_blank">github.com/itdoginfo/allow-domains</a>');
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.DynamicList,
|
||||
'community_lists',
|
||||
_('Service List'),
|
||||
_('Select predefined service for routing') +
|
||||
' <a href="https://github.com/itdoginfo/allow-domains" target="_blank">github.com/itdoginfo/allow-domains</a>',
|
||||
);
|
||||
o.placeholder = 'Service list';
|
||||
Object.entries(main.DOMAIN_LIST_OPTIONS).forEach(([key, label]) => {
|
||||
o.value(key, _(label));
|
||||
@@ -252,31 +352,52 @@ function createConfigSection(section) {
|
||||
let newValues = [...values];
|
||||
let notifications = [];
|
||||
|
||||
const selectedRegionalOptions = main.REGIONAL_OPTIONS.filter(opt => newValues.includes(opt));
|
||||
const selectedRegionalOptions = main.REGIONAL_OPTIONS.filter((opt) =>
|
||||
newValues.includes(opt),
|
||||
);
|
||||
|
||||
if (selectedRegionalOptions.length > 1) {
|
||||
const lastSelected = selectedRegionalOptions[selectedRegionalOptions.length - 1];
|
||||
const lastSelected =
|
||||
selectedRegionalOptions[selectedRegionalOptions.length - 1];
|
||||
const removedRegions = selectedRegionalOptions.slice(0, -1);
|
||||
newValues = newValues.filter(v => v === lastSelected || !main.REGIONAL_OPTIONS.includes(v));
|
||||
notifications.push(E('p', { class: 'alert-message warning' }, [
|
||||
E('strong', {}, _('Regional options cannot be used together')), E('br'),
|
||||
_('Warning: %s cannot be used together with %s. Previous selections have been removed.')
|
||||
.format(removedRegions.join(', '), lastSelected)
|
||||
]));
|
||||
newValues = newValues.filter(
|
||||
(v) => v === lastSelected || !main.REGIONAL_OPTIONS.includes(v),
|
||||
);
|
||||
notifications.push(
|
||||
E('p', { class: 'alert-message warning' }, [
|
||||
E('strong', {}, _('Regional options cannot be used together')),
|
||||
E('br'),
|
||||
_(
|
||||
'Warning: %s cannot be used together with %s. Previous selections have been removed.',
|
||||
).format(removedRegions.join(', '), lastSelected),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
if (newValues.includes('russia_inside')) {
|
||||
const removedServices = newValues.filter(v => !main.ALLOWED_WITH_RUSSIA_INSIDE.includes(v));
|
||||
const removedServices = newValues.filter(
|
||||
(v) => !main.ALLOWED_WITH_RUSSIA_INSIDE.includes(v),
|
||||
);
|
||||
if (removedServices.length > 0) {
|
||||
newValues = newValues.filter(v => main.ALLOWED_WITH_RUSSIA_INSIDE.includes(v));
|
||||
notifications.push(E('p', { class: 'alert-message warning' }, [
|
||||
E('strong', {}, _('Russia inside restrictions')), E('br'),
|
||||
_('Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection.')
|
||||
.format(
|
||||
main.ALLOWED_WITH_RUSSIA_INSIDE.map(key => main.DOMAIN_LIST_OPTIONS[key]).filter(label => label !== 'Russia inside').join(', '),
|
||||
removedServices.join(', ')
|
||||
newValues = newValues.filter((v) =>
|
||||
main.ALLOWED_WITH_RUSSIA_INSIDE.includes(v),
|
||||
);
|
||||
notifications.push(
|
||||
E('p', { class: 'alert-message warning' }, [
|
||||
E('strong', {}, _('Russia inside restrictions')),
|
||||
E('br'),
|
||||
_(
|
||||
'Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection.',
|
||||
).format(
|
||||
main.ALLOWED_WITH_RUSSIA_INSIDE.map(
|
||||
(key) => main.DOMAIN_LIST_OPTIONS[key],
|
||||
)
|
||||
]));
|
||||
.filter((label) => label !== 'Russia inside')
|
||||
.join(', '),
|
||||
removedServices.join(', '),
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,7 +405,9 @@ function createConfigSection(section) {
|
||||
this.getUIElement(section_id).setValue(newValues);
|
||||
}
|
||||
|
||||
notifications.forEach(notification => ui.addNotification(null, notification));
|
||||
notifications.forEach((notification) =>
|
||||
ui.addNotification(null, notification),
|
||||
);
|
||||
lastValues = newValues;
|
||||
} catch (e) {
|
||||
console.error('Error in onchange handler:', e);
|
||||
@@ -293,7 +416,13 @@ function createConfigSection(section) {
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.ListValue, 'user_domain_list_type', _('User Domain List Type'), _('Select how to add your custom domains'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.ListValue,
|
||||
'user_domain_list_type',
|
||||
_('User Domain List Type'),
|
||||
_('Select how to add your custom domains'),
|
||||
);
|
||||
o.value('disabled', _('Disabled'));
|
||||
o.value('dynamic', _('Dynamic List'));
|
||||
o.value('text', _('Text List'));
|
||||
@@ -301,7 +430,15 @@ function createConfigSection(section) {
|
||||
o.rmempty = false;
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', form.DynamicList, 'user_domains', _('User Domains'), _('Enter domain names without protocols (example: sub.example.com or example.com)'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.DynamicList,
|
||||
'user_domains',
|
||||
_('User Domains'),
|
||||
_(
|
||||
'Enter domain names without protocols (example: sub.example.com or example.com)',
|
||||
),
|
||||
);
|
||||
o.placeholder = 'Domains list';
|
||||
o.depends('user_domain_list_type', 'dynamic');
|
||||
o.rmempty = false;
|
||||
@@ -309,7 +446,7 @@ function createConfigSection(section) {
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
const validation = main.validateDomain(value);
|
||||
@@ -318,11 +455,20 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
return _(validation.message);
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.TextValue, 'user_domains_text', _('User Domains List'), _('Enter domain names separated by comma, space or newline. You can add comments after //'));
|
||||
o.placeholder = 'example.com, sub.example.com\n// Social networks\ndomain.com test.com // personal domains';
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.TextValue,
|
||||
'user_domains_text',
|
||||
_('User Domains List'),
|
||||
_(
|
||||
'Enter domain names separated by comma, space or newline. You can add comments after //',
|
||||
),
|
||||
);
|
||||
o.placeholder =
|
||||
'example.com, sub.example.com\n// Social networks\ndomain.com test.com // personal domains';
|
||||
o.depends('user_domain_list_type', 'text');
|
||||
o.rows = 8;
|
||||
o.rmempty = false;
|
||||
@@ -330,14 +476,14 @@ function createConfigSection(section) {
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
const domains = main.parseValueList(value);
|
||||
|
||||
if (!domains.length) {
|
||||
return _(
|
||||
'At least one valid domain must be specified. Comments-only content is not allowed.'
|
||||
'At least one valid domain must be specified. Comments-only content is not allowed.',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -345,8 +491,8 @@ function createConfigSection(section) {
|
||||
|
||||
if (!valid) {
|
||||
const errors = results
|
||||
.filter(validation => !validation.valid) // Leave only failed validations
|
||||
.map((validation) => _(`${validation.value}: ${validation.message}`)) // Collect validation errors
|
||||
.filter((validation) => !validation.valid) // Leave only failed validations
|
||||
.map((validation) => _(`${validation.value}: ${validation.message}`)); // Collect validation errors
|
||||
|
||||
return [_('Validation errors:'), ...errors].join('\n');
|
||||
}
|
||||
@@ -354,12 +500,24 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'local_domain_lists_enabled', _('Local Domain Lists'), _('Use the list from the router filesystem'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.Flag,
|
||||
'local_domain_lists_enabled',
|
||||
_('Local Domain Lists'),
|
||||
_('Use the list from the router filesystem'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', form.DynamicList, 'local_domain_lists', _('Local Domain List Paths'), _('Enter the list file path'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.DynamicList,
|
||||
'local_domain_lists',
|
||||
_('Local Domain List Paths'),
|
||||
_('Enter the list file path'),
|
||||
);
|
||||
o.placeholder = '/path/file.lst';
|
||||
o.depends('local_domain_lists_enabled', '1');
|
||||
o.rmempty = false;
|
||||
@@ -367,7 +525,7 @@ function createConfigSection(section) {
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
const validation = main.validatePath(value);
|
||||
@@ -376,15 +534,27 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
return _(validation.message);
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'remote_domain_lists_enabled', _('Remote Domain Lists'), _('Download and use domain lists from remote URLs'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.Flag,
|
||||
'remote_domain_lists_enabled',
|
||||
_('Remote Domain Lists'),
|
||||
_('Download and use domain lists from remote URLs'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', form.DynamicList, 'remote_domain_lists', _('Remote Domain URLs'), _('Enter full URLs starting with http:// or https://'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.DynamicList,
|
||||
'remote_domain_lists',
|
||||
_('Remote Domain URLs'),
|
||||
_('Enter full URLs starting with http:// or https://'),
|
||||
);
|
||||
o.placeholder = 'URL';
|
||||
o.depends('remote_domain_lists_enabled', '1');
|
||||
o.rmempty = false;
|
||||
@@ -392,7 +562,7 @@ function createConfigSection(section) {
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
const validation = main.validateUrl(value);
|
||||
@@ -401,15 +571,27 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
return _(validation.message);
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'local_subnet_lists_enabled', _('Local Subnet Lists'), _('Use the list from the router filesystem'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.Flag,
|
||||
'local_subnet_lists_enabled',
|
||||
_('Local Subnet Lists'),
|
||||
_('Use the list from the router filesystem'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', form.DynamicList, 'local_subnet_lists', _('Local Subnet List Paths'), _('Enter the list file path'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.DynamicList,
|
||||
'local_subnet_lists',
|
||||
_('Local Subnet List Paths'),
|
||||
_('Enter the list file path'),
|
||||
);
|
||||
o.placeholder = '/path/file.lst';
|
||||
o.depends('local_subnet_lists_enabled', '1');
|
||||
o.rmempty = false;
|
||||
@@ -417,7 +599,7 @@ function createConfigSection(section) {
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
const validation = main.validatePath(value);
|
||||
@@ -426,10 +608,16 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
return _(validation.message);
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.ListValue, 'user_subnet_list_type', _('User Subnet List Type'), _('Select how to add your custom subnets'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.ListValue,
|
||||
'user_subnet_list_type',
|
||||
_('User Subnet List Type'),
|
||||
_('Select how to add your custom subnets'),
|
||||
);
|
||||
o.value('disabled', _('Disabled'));
|
||||
o.value('dynamic', _('Dynamic List'));
|
||||
o.value('text', _('Text List (comma/space/newline separated)'));
|
||||
@@ -437,7 +625,15 @@ function createConfigSection(section) {
|
||||
o.rmempty = false;
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', form.DynamicList, 'user_subnets', _('User Subnets'), _('Enter subnets in CIDR notation (example: 103.21.244.0/22) or single IP addresses'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.DynamicList,
|
||||
'user_subnets',
|
||||
_('User Subnets'),
|
||||
_(
|
||||
'Enter subnets in CIDR notation (example: 103.21.244.0/22) or single IP addresses',
|
||||
),
|
||||
);
|
||||
o.placeholder = 'IP or subnet';
|
||||
o.depends('user_subnet_list_type', 'dynamic');
|
||||
o.rmempty = false;
|
||||
@@ -445,7 +641,7 @@ function createConfigSection(section) {
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
const validation = main.validateSubnet(value);
|
||||
@@ -454,11 +650,20 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
return _(validation.message);
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.TextValue, 'user_subnets_text', _('User Subnets List'), _('Enter subnets in CIDR notation or single IP addresses, separated by comma, space or newline. You can add comments after //'));
|
||||
o.placeholder = '103.21.244.0/22\n// Google DNS\n8.8.8.8\n1.1.1.1/32, 9.9.9.9 // Cloudflare and Quad9';
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.TextValue,
|
||||
'user_subnets_text',
|
||||
_('User Subnets List'),
|
||||
_(
|
||||
'Enter subnets in CIDR notation or single IP addresses, separated by comma, space or newline. You can add comments after //',
|
||||
),
|
||||
);
|
||||
o.placeholder =
|
||||
'103.21.244.0/22\n// Google DNS\n8.8.8.8\n1.1.1.1/32, 9.9.9.9 // Cloudflare and Quad9';
|
||||
o.depends('user_subnet_list_type', 'text');
|
||||
o.rows = 10;
|
||||
o.rmempty = false;
|
||||
@@ -466,14 +671,14 @@ function createConfigSection(section) {
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
const subnets = main.parseValueList(value);
|
||||
|
||||
if (!subnets.length) {
|
||||
return _(
|
||||
'At least one valid subnet or IP must be specified. Comments-only content is not allowed.'
|
||||
'At least one valid subnet or IP must be specified. Comments-only content is not allowed.',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -481,8 +686,8 @@ function createConfigSection(section) {
|
||||
|
||||
if (!valid) {
|
||||
const errors = results
|
||||
.filter(validation => !validation.valid) // Leave only failed validations
|
||||
.map((validation) => _(`${validation.value}: ${validation.message}`)) // Collect validation errors
|
||||
.filter((validation) => !validation.valid) // Leave only failed validations
|
||||
.map((validation) => _(`${validation.value}: ${validation.message}`)); // Collect validation errors
|
||||
|
||||
return [_('Validation errors:'), ...errors].join('\n');
|
||||
}
|
||||
@@ -490,12 +695,24 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'remote_subnet_lists_enabled', _('Remote Subnet Lists'), _('Download and use subnet lists from remote URLs'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.Flag,
|
||||
'remote_subnet_lists_enabled',
|
||||
_('Remote Subnet Lists'),
|
||||
_('Download and use subnet lists from remote URLs'),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', form.DynamicList, 'remote_subnet_lists', _('Remote Subnet URLs'), _('Enter full URLs starting with http:// or https://'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.DynamicList,
|
||||
'remote_subnet_lists',
|
||||
_('Remote Subnet URLs'),
|
||||
_('Enter full URLs starting with http:// or https://'),
|
||||
);
|
||||
o.placeholder = 'URL';
|
||||
o.depends('remote_subnet_lists_enabled', '1');
|
||||
o.rmempty = false;
|
||||
@@ -503,7 +720,7 @@ function createConfigSection(section) {
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
const validation = main.validateUrl(value);
|
||||
@@ -512,15 +729,29 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
return _(validation.message);
|
||||
};
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'all_traffic_from_ip_enabled', _('IP for full redirection'), _('Specify local IP addresses whose traffic will always use the configured route'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.Flag,
|
||||
'all_traffic_from_ip_enabled',
|
||||
_('IP for full redirection'),
|
||||
_(
|
||||
'Specify local IP addresses whose traffic will always use the configured route',
|
||||
),
|
||||
);
|
||||
o.default = '0';
|
||||
o.rmempty = false;
|
||||
o.ucisection = s.section;
|
||||
|
||||
o = s.taboption('basic', form.DynamicList, 'all_traffic_ip', _('Local IPs'), _('Enter valid IPv4 addresses'));
|
||||
o = s.taboption(
|
||||
'basic',
|
||||
form.DynamicList,
|
||||
'all_traffic_ip',
|
||||
_('Local IPs'),
|
||||
_('Enter valid IPv4 addresses'),
|
||||
);
|
||||
o.placeholder = 'IP';
|
||||
o.depends('all_traffic_from_ip_enabled', '1');
|
||||
o.rmempty = false;
|
||||
@@ -528,7 +759,7 @@ function createConfigSection(section) {
|
||||
o.validate = function (section_id, value) {
|
||||
// Optional
|
||||
if (!value || value.length === 0) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
const validation = main.validateIPV4(value);
|
||||
@@ -537,10 +768,10 @@ function createConfigSection(section) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _(validation.message)
|
||||
return _(validation.message);
|
||||
};
|
||||
}
|
||||
|
||||
return baseclass.extend({
|
||||
createConfigSection
|
||||
createConfigSection,
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,14 +15,12 @@ let errorPollTimer = null;
|
||||
|
||||
// Helper function to fetch errors from the podkop command
|
||||
async function getPodkopErrors() {
|
||||
return new Promise(resolve => {
|
||||
safeExec('/usr/bin/podkop', ['check_logs'], 'P0_PRIORITY', result => {
|
||||
return new Promise((resolve) => {
|
||||
safeExec('/usr/bin/podkop', ['check_logs'], 'P0_PRIORITY', (result) => {
|
||||
if (!result || !result.stdout) return resolve([]);
|
||||
|
||||
const logs = result.stdout.split('\n');
|
||||
const errors = logs.filter(log =>
|
||||
log.includes('[critical]')
|
||||
);
|
||||
const errors = logs.filter((log) => log.includes('[critical]'));
|
||||
|
||||
resolve(errors);
|
||||
});
|
||||
@@ -31,20 +29,29 @@ async function getPodkopErrors() {
|
||||
|
||||
// Show error notification to the user
|
||||
function showErrorNotification(error, isMultiple = false) {
|
||||
const notificationContent = E('div', { 'class': 'alert-message error' }, [
|
||||
E('pre', { 'class': 'error-log' }, error)
|
||||
const notificationContent = E('div', { class: 'alert-message error' }, [
|
||||
E('pre', { class: 'error-log' }, error),
|
||||
]);
|
||||
|
||||
ui.addNotification(null, notificationContent);
|
||||
}
|
||||
|
||||
// Helper function for command execution with prioritization
|
||||
function safeExec(command, args, priority, callback, timeout = main.COMMAND_TIMEOUT) {
|
||||
function safeExec(
|
||||
command,
|
||||
args,
|
||||
priority,
|
||||
callback,
|
||||
timeout = main.COMMAND_TIMEOUT,
|
||||
) {
|
||||
// Default to highest priority execution if priority is not provided or invalid
|
||||
let schedulingDelay = main.COMMAND_SCHEDULING.P0_PRIORITY;
|
||||
|
||||
// If priority is a string, try to get the corresponding delay value
|
||||
if (typeof priority === 'string' && main.COMMAND_SCHEDULING[priority] !== undefined) {
|
||||
if (
|
||||
typeof priority === 'string' &&
|
||||
main.COMMAND_SCHEDULING[priority] !== undefined
|
||||
) {
|
||||
schedulingDelay = main.COMMAND_SCHEDULING[priority];
|
||||
}
|
||||
|
||||
@@ -59,7 +66,7 @@ function safeExec(command, args, priority, callback, timeout = main.COMMAND_TIME
|
||||
controller.signal.addEventListener('abort', () => {
|
||||
reject(new Error('Command execution timed out'));
|
||||
});
|
||||
})
|
||||
}),
|
||||
]);
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
@@ -70,7 +77,9 @@ function safeExec(command, args, priority, callback, timeout = main.COMMAND_TIME
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.warn(`Command execution failed or timed out: ${command} ${args.join(' ')}`);
|
||||
console.warn(
|
||||
`Command execution failed or timed out: ${command} ${args.join(' ')}`,
|
||||
);
|
||||
const errorResult = { stdout: '', stderr: error.message, error: error };
|
||||
|
||||
if (callback && typeof callback === 'function') {
|
||||
@@ -84,8 +93,7 @@ function safeExec(command, args, priority, callback, timeout = main.COMMAND_TIME
|
||||
if (callback && typeof callback === 'function') {
|
||||
setTimeout(executeCommand, schedulingDelay);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return executeCommand();
|
||||
}
|
||||
}
|
||||
@@ -97,19 +105,19 @@ async function checkForCriticalErrors() {
|
||||
|
||||
if (errors && errors.length > 0) {
|
||||
// Filter out errors we've already seen
|
||||
const newErrors = errors.filter(error => !lastErrorsSet.has(error));
|
||||
const newErrors = errors.filter((error) => !lastErrorsSet.has(error));
|
||||
|
||||
if (newErrors.length > 0) {
|
||||
// On initial check, just store errors without showing notifications
|
||||
if (!isInitialCheck) {
|
||||
// Show each new error as a notification
|
||||
newErrors.forEach(error => {
|
||||
newErrors.forEach((error) => {
|
||||
showErrorNotification(error, newErrors.length > 1);
|
||||
});
|
||||
}
|
||||
|
||||
// Add new errors to our set of seen errors
|
||||
newErrors.forEach(error => lastErrorsSet.add(error));
|
||||
newErrors.forEach((error) => lastErrorsSet.add(error));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +141,10 @@ function startErrorPolling() {
|
||||
checkForCriticalErrors();
|
||||
|
||||
// Then set up periodic checks
|
||||
errorPollTimer = setInterval(checkForCriticalErrors, main.ERROR_POLL_INTERVAL);
|
||||
errorPollTimer = setInterval(
|
||||
checkForCriticalErrors,
|
||||
main.ERROR_POLL_INTERVAL,
|
||||
);
|
||||
}
|
||||
|
||||
// Stop polling for errors
|
||||
@@ -148,5 +159,5 @@ return baseclass.extend({
|
||||
startErrorPolling,
|
||||
stopErrorPolling,
|
||||
checkForCriticalErrors,
|
||||
safeExec
|
||||
safeExec,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user