mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-09 04:56:51 +03:00
fix: run prettier & remove unused fragments
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
import { ValidationResult } from './types';
|
import { ValidationResult } from './types';
|
||||||
|
|
||||||
// TODO refactor current validation and add tests
|
|
||||||
export function validateVlessUrl(url: string): ValidationResult {
|
export function validateVlessUrl(url: string): ValidationResult {
|
||||||
try {
|
try {
|
||||||
const parsedUrl = new URL(url);
|
const parsedUrl = new URL(url);
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ async function uploadFile(filePath) {
|
|||||||
const relativePath = path.relative(localDir, filePath);
|
const relativePath = path.relative(localDir, filePath);
|
||||||
const remotePath = path.posix.join(remoteDir, relativePath);
|
const remotePath = path.posix.join(remoteDir, relativePath);
|
||||||
|
|
||||||
console.log(`⬆️ Uploading: ${relativePath} -> ${remotePath}`);
|
console.log(`Uploading: ${relativePath} -> ${remotePath}`);
|
||||||
try {
|
try {
|
||||||
await sftp.fastPut(filePath, remotePath);
|
await sftp.fastPut(filePath, remotePath);
|
||||||
console.log(`✅ Uploaded: ${relativePath}`);
|
console.log(`Uploaded: ${relativePath}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`❌ Failed: ${relativePath}: ${err.message}`);
|
console.error(`Failed: ${relativePath}: ${err.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,34 +36,32 @@ async function deleteFile(filePath) {
|
|||||||
const relativePath = path.relative(localDir, filePath);
|
const relativePath = path.relative(localDir, filePath);
|
||||||
const remotePath = path.posix.join(remoteDir, relativePath);
|
const remotePath = path.posix.join(remoteDir, relativePath);
|
||||||
|
|
||||||
console.log(`🗑 Removing: ${relativePath}`);
|
console.log(`Removing: ${relativePath}`);
|
||||||
try {
|
try {
|
||||||
await sftp.delete(remotePath);
|
await sftp.delete(remotePath);
|
||||||
console.log(`✅ Removed: ${relativePath}`);
|
console.log(`Removed: ${relativePath}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.warn(`⚠️ Could not delete ${relativePath}: ${err.message}`);
|
console.warn(`Could not delete ${relativePath}: ${err.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadAllFiles() {
|
async function uploadAllFiles() {
|
||||||
console.log('🚀 Uploading all files from', localDir);
|
console.log('Uploading all files from', localDir);
|
||||||
|
|
||||||
const files = await glob(`${localDir}/**/*`, { nodir: true });
|
const files = await glob(`${localDir}/**/*`, { nodir: true });
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
await uploadFile(file);
|
await uploadFile(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('✅ Initial upload complete!');
|
console.log('Initial upload complete!');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
await sftp.connect(config);
|
await sftp.connect(config);
|
||||||
console.log(`✅ Connected to ${config.host}`);
|
console.log(`Connected to ${config.host}`);
|
||||||
|
|
||||||
// 🔹 Загрузить всё при старте
|
|
||||||
await uploadAllFiles();
|
await uploadAllFiles();
|
||||||
|
|
||||||
// 🔹 Затем следить за изменениями
|
|
||||||
chokidar
|
chokidar
|
||||||
.watch(localDir, { ignoreInitial: true })
|
.watch(localDir, { ignoreInitial: true })
|
||||||
.on('all', async (event, filePath) => {
|
.on('all', async (event, filePath) => {
|
||||||
@@ -75,7 +73,7 @@ async function main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
process.on('SIGINT', async () => {
|
process.on('SIGINT', async () => {
|
||||||
console.log('🔌 Disconnecting...');
|
console.log('Disconnecting...');
|
||||||
await sftp.end();
|
await sftp.end();
|
||||||
process.exit();
|
process.exit();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ function createConfigSection(section) {
|
|||||||
let o = s.tab('basic', _('Basic Settings'));
|
let o = s.tab('basic', _('Basic Settings'));
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.ListValue,
|
form.ListValue,
|
||||||
'mode',
|
'mode',
|
||||||
_('Connection Type'),
|
_('Connection Type'),
|
||||||
_('Select between VPN and Proxy connection methods for traffic routing'),
|
_('Select between VPN and Proxy connection methods for traffic routing'),
|
||||||
);
|
);
|
||||||
o.value('proxy', 'Proxy');
|
o.value('proxy', 'Proxy');
|
||||||
o.value('vpn', 'VPN');
|
o.value('vpn', 'VPN');
|
||||||
@@ -24,11 +24,11 @@ function createConfigSection(section) {
|
|||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.ListValue,
|
form.ListValue,
|
||||||
'proxy_config_type',
|
'proxy_config_type',
|
||||||
_('Configuration Type'),
|
_('Configuration Type'),
|
||||||
_('Select how to configure the proxy'),
|
_('Select how to configure the proxy'),
|
||||||
);
|
);
|
||||||
o.value('url', _('Connection URL'));
|
o.value('url', _('Connection URL'));
|
||||||
o.value('outbound', _('Outbound Config'));
|
o.value('outbound', _('Outbound Config'));
|
||||||
@@ -38,11 +38,11 @@ function createConfigSection(section) {
|
|||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.TextValue,
|
form.TextValue,
|
||||||
'proxy_string',
|
'proxy_string',
|
||||||
_('Proxy Configuration URL'),
|
_('Proxy Configuration URL'),
|
||||||
'',
|
'',
|
||||||
);
|
);
|
||||||
o.depends('proxy_config_type', 'url');
|
o.depends('proxy_config_type', 'url');
|
||||||
o.rows = 5;
|
o.rows = 5;
|
||||||
@@ -52,7 +52,7 @@ function createConfigSection(section) {
|
|||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
o.sectionDescriptions = new Map();
|
o.sectionDescriptions = new Map();
|
||||||
o.placeholder =
|
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';
|
'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) {
|
o.renderWidget = function (section_id, option_index, cfgvalue) {
|
||||||
const original = form.TextValue.prototype.renderWidget.apply(this, [
|
const original = form.TextValue.prototype.renderWidget.apply(this, [
|
||||||
@@ -66,9 +66,9 @@ function createConfigSection(section) {
|
|||||||
if (cfgvalue) {
|
if (cfgvalue) {
|
||||||
try {
|
try {
|
||||||
const activeConfig = cfgvalue
|
const activeConfig = cfgvalue
|
||||||
.split('\n')
|
.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('#')) {
|
if (activeConfig.includes('#')) {
|
||||||
@@ -76,24 +76,24 @@ function createConfigSection(section) {
|
|||||||
if (label && label.trim()) {
|
if (label && label.trim()) {
|
||||||
const decodedLabel = decodeURIComponent(label);
|
const decodedLabel = decodeURIComponent(label);
|
||||||
const descDiv = E(
|
const descDiv = E(
|
||||||
'div',
|
'div',
|
||||||
{ class: 'cbi-value-description' },
|
{ class: 'cbi-value-description' },
|
||||||
_('Current config: ') + decodedLabel,
|
_('Current config: ') + decodedLabel,
|
||||||
);
|
);
|
||||||
container.appendChild(descDiv);
|
container.appendChild(descDiv);
|
||||||
} else {
|
} else {
|
||||||
const descDiv = E(
|
const descDiv = E(
|
||||||
'div',
|
'div',
|
||||||
{ class: 'cbi-value-description' },
|
{ class: 'cbi-value-description' },
|
||||||
_('Config without description'),
|
_('Config without description'),
|
||||||
);
|
);
|
||||||
container.appendChild(descDiv);
|
container.appendChild(descDiv);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const descDiv = E(
|
const descDiv = E(
|
||||||
'div',
|
'div',
|
||||||
{ class: 'cbi-value-description' },
|
{ class: 'cbi-value-description' },
|
||||||
_('Config without description'),
|
_('Config without description'),
|
||||||
);
|
);
|
||||||
container.appendChild(descDiv);
|
container.appendChild(descDiv);
|
||||||
}
|
}
|
||||||
@@ -101,19 +101,19 @@ function createConfigSection(section) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Error parsing config label:', e);
|
console.error('Error parsing config label:', e);
|
||||||
const descDiv = E(
|
const descDiv = E(
|
||||||
'div',
|
'div',
|
||||||
{ class: 'cbi-value-description' },
|
{ class: 'cbi-value-description' },
|
||||||
_('Config without description'),
|
_('Config without description'),
|
||||||
);
|
);
|
||||||
container.appendChild(descDiv);
|
container.appendChild(descDiv);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const defaultDesc = E(
|
const defaultDesc = E(
|
||||||
'div',
|
'div',
|
||||||
{ class: 'cbi-value-description' },
|
{ class: 'cbi-value-description' },
|
||||||
_(
|
_(
|
||||||
'Enter connection string starting with vless:// or ss:// for proxy configuration. Add comments with // for backup configs',
|
'Enter connection string starting with vless:// or ss:// for proxy configuration. Add comments with // for backup configs',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
container.appendChild(defaultDesc);
|
container.appendChild(defaultDesc);
|
||||||
}
|
}
|
||||||
@@ -129,20 +129,20 @@ function createConfigSection(section) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const activeConfigs = value
|
const activeConfigs = value
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map((line) => line.trim())
|
.map((line) => line.trim())
|
||||||
.filter((line) => !line.startsWith('//'))
|
.filter((line) => !line.startsWith('//'))
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
||||||
if (!activeConfigs.length) {
|
if (!activeConfigs.length) {
|
||||||
return _(
|
return _(
|
||||||
'No active configuration found. One configuration is required.',
|
'No active configuration found. One configuration is required.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeConfigs.length > 1) {
|
if (activeConfigs.length > 1) {
|
||||||
return _(
|
return _(
|
||||||
'Multiply active configurations found. Please leave one configuration.',
|
'Multiply active configurations found. Please leave one configuration.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,11 +159,11 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.TextValue,
|
form.TextValue,
|
||||||
'outbound_json',
|
'outbound_json',
|
||||||
_('Outbound Configuration'),
|
_('Outbound Configuration'),
|
||||||
_('Enter complete outbound configuration in JSON format'),
|
_('Enter complete outbound configuration in JSON format'),
|
||||||
);
|
);
|
||||||
o.depends('proxy_config_type', 'outbound');
|
o.depends('proxy_config_type', 'outbound');
|
||||||
o.rows = 10;
|
o.rows = 10;
|
||||||
@@ -184,10 +184,10 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.DynamicList,
|
form.DynamicList,
|
||||||
'urltest_proxy_links',
|
'urltest_proxy_links',
|
||||||
_('URLTest Proxy Links'),
|
_('URLTest Proxy Links'),
|
||||||
);
|
);
|
||||||
o.depends('proxy_config_type', 'urltest');
|
o.depends('proxy_config_type', 'urltest');
|
||||||
o.placeholder = 'vless://, ss://, trojan:// links';
|
o.placeholder = 'vless://, ss://, trojan:// links';
|
||||||
@@ -208,11 +208,11 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.Flag,
|
form.Flag,
|
||||||
'ss_uot',
|
'ss_uot',
|
||||||
_('Shadowsocks UDP over TCP'),
|
_('Shadowsocks UDP over TCP'),
|
||||||
_('Apply for SS2022'),
|
_('Apply for SS2022'),
|
||||||
);
|
);
|
||||||
o.default = '0';
|
o.default = '0';
|
||||||
o.depends('mode', 'proxy');
|
o.depends('mode', 'proxy');
|
||||||
@@ -220,11 +220,11 @@ function createConfigSection(section) {
|
|||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
widgets.DeviceSelect,
|
widgets.DeviceSelect,
|
||||||
'interface',
|
'interface',
|
||||||
_('Network Interface'),
|
_('Network Interface'),
|
||||||
_('Select network interface for VPN connection'),
|
_('Select network interface for VPN connection'),
|
||||||
);
|
);
|
||||||
o.depends('mode', 'vpn');
|
o.depends('mode', 'vpn');
|
||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
@@ -262,17 +262,17 @@ function createConfigSection(section) {
|
|||||||
|
|
||||||
// Reject wireless-related devices
|
// Reject wireless-related devices
|
||||||
const isWireless =
|
const isWireless =
|
||||||
type === 'wifi' || type === 'wireless' || type.includes('wlan');
|
type === 'wifi' || type === 'wireless' || type.includes('wlan');
|
||||||
|
|
||||||
return !isWireless;
|
return !isWireless;
|
||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.Flag,
|
form.Flag,
|
||||||
'domain_resolver_enabled',
|
'domain_resolver_enabled',
|
||||||
_('Domain Resolver'),
|
_('Domain Resolver'),
|
||||||
_('Enable built-in DNS resolver for domains handled by this section'),
|
_('Enable built-in DNS resolver for domains handled by this section'),
|
||||||
);
|
);
|
||||||
o.default = '0';
|
o.default = '0';
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
@@ -280,11 +280,11 @@ function createConfigSection(section) {
|
|||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.ListValue,
|
form.ListValue,
|
||||||
'domain_resolver_dns_type',
|
'domain_resolver_dns_type',
|
||||||
_('DNS Protocol Type'),
|
_('DNS Protocol Type'),
|
||||||
_('Select the DNS protocol type for the domain resolver'),
|
_('Select the DNS protocol type for the domain resolver'),
|
||||||
);
|
);
|
||||||
o.value('doh', _('DNS over HTTPS (DoH)'));
|
o.value('doh', _('DNS over HTTPS (DoH)'));
|
||||||
o.value('dot', _('DNS over TLS (DoT)'));
|
o.value('dot', _('DNS over TLS (DoT)'));
|
||||||
@@ -295,11 +295,11 @@ function createConfigSection(section) {
|
|||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.Value,
|
form.Value,
|
||||||
'domain_resolver_dns_server',
|
'domain_resolver_dns_server',
|
||||||
_('DNS Server'),
|
_('DNS Server'),
|
||||||
_('Select or enter DNS server address'),
|
_('Select or enter DNS server address'),
|
||||||
);
|
);
|
||||||
Object.entries(main.DNS_SERVER_OPTIONS).forEach(([key, label]) => {
|
Object.entries(main.DNS_SERVER_OPTIONS).forEach(([key, label]) => {
|
||||||
o.value(key, _(label));
|
o.value(key, _(label));
|
||||||
@@ -319,21 +319,21 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.Flag,
|
form.Flag,
|
||||||
'community_lists_enabled',
|
'community_lists_enabled',
|
||||||
_('Community Lists'),
|
_('Community Lists'),
|
||||||
);
|
);
|
||||||
o.default = '0';
|
o.default = '0';
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.DynamicList,
|
form.DynamicList,
|
||||||
'community_lists',
|
'community_lists',
|
||||||
_('Service List'),
|
_('Service List'),
|
||||||
_('Select predefined service for routing') +
|
_('Select predefined service for routing') +
|
||||||
' <a href="https://github.com/itdoginfo/allow-domains" target="_blank">github.com/itdoginfo/allow-domains</a>',
|
' <a href="https://github.com/itdoginfo/allow-domains" target="_blank">github.com/itdoginfo/allow-domains</a>',
|
||||||
);
|
);
|
||||||
o.placeholder = 'Service list';
|
o.placeholder = 'Service list';
|
||||||
@@ -357,50 +357,50 @@ function createConfigSection(section) {
|
|||||||
let notifications = [];
|
let notifications = [];
|
||||||
|
|
||||||
const selectedRegionalOptions = main.REGIONAL_OPTIONS.filter((opt) =>
|
const selectedRegionalOptions = main.REGIONAL_OPTIONS.filter((opt) =>
|
||||||
newValues.includes(opt),
|
newValues.includes(opt),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (selectedRegionalOptions.length > 1) {
|
if (selectedRegionalOptions.length > 1) {
|
||||||
const lastSelected =
|
const lastSelected =
|
||||||
selectedRegionalOptions[selectedRegionalOptions.length - 1];
|
selectedRegionalOptions[selectedRegionalOptions.length - 1];
|
||||||
const removedRegions = selectedRegionalOptions.slice(0, -1);
|
const removedRegions = selectedRegionalOptions.slice(0, -1);
|
||||||
newValues = newValues.filter(
|
newValues = newValues.filter(
|
||||||
(v) => v === lastSelected || !main.REGIONAL_OPTIONS.includes(v),
|
(v) => v === lastSelected || !main.REGIONAL_OPTIONS.includes(v),
|
||||||
);
|
);
|
||||||
notifications.push(
|
notifications.push(
|
||||||
E('p', { class: 'alert-message warning' }, [
|
E('p', { class: 'alert-message warning' }, [
|
||||||
E('strong', {}, _('Regional options cannot be used together')),
|
E('strong', {}, _('Regional options cannot be used together')),
|
||||||
E('br'),
|
E('br'),
|
||||||
_(
|
_(
|
||||||
'Warning: %s cannot be used together with %s. Previous selections have been removed.',
|
'Warning: %s cannot be used together with %s. Previous selections have been removed.',
|
||||||
).format(removedRegions.join(', '), lastSelected),
|
).format(removedRegions.join(', '), lastSelected),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newValues.includes('russia_inside')) {
|
if (newValues.includes('russia_inside')) {
|
||||||
const removedServices = newValues.filter(
|
const removedServices = newValues.filter(
|
||||||
(v) => !main.ALLOWED_WITH_RUSSIA_INSIDE.includes(v),
|
(v) => !main.ALLOWED_WITH_RUSSIA_INSIDE.includes(v),
|
||||||
);
|
);
|
||||||
if (removedServices.length > 0) {
|
if (removedServices.length > 0) {
|
||||||
newValues = newValues.filter((v) =>
|
newValues = newValues.filter((v) =>
|
||||||
main.ALLOWED_WITH_RUSSIA_INSIDE.includes(v),
|
main.ALLOWED_WITH_RUSSIA_INSIDE.includes(v),
|
||||||
);
|
);
|
||||||
notifications.push(
|
notifications.push(
|
||||||
E('p', { class: 'alert-message warning' }, [
|
E('p', { class: 'alert-message warning' }, [
|
||||||
E('strong', {}, _('Russia inside restrictions')),
|
E('strong', {}, _('Russia inside restrictions')),
|
||||||
E('br'),
|
E('br'),
|
||||||
_(
|
_(
|
||||||
'Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection.',
|
'Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection.',
|
||||||
).format(
|
).format(
|
||||||
main.ALLOWED_WITH_RUSSIA_INSIDE.map(
|
main.ALLOWED_WITH_RUSSIA_INSIDE.map(
|
||||||
(key) => main.DOMAIN_LIST_OPTIONS[key],
|
(key) => main.DOMAIN_LIST_OPTIONS[key],
|
||||||
)
|
)
|
||||||
.filter((label) => label !== 'Russia inside')
|
.filter((label) => label !== 'Russia inside')
|
||||||
.join(', '),
|
.join(', '),
|
||||||
removedServices.join(', '),
|
removedServices.join(', '),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -410,7 +410,7 @@ function createConfigSection(section) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
notifications.forEach((notification) =>
|
notifications.forEach((notification) =>
|
||||||
ui.addNotification(null, notification),
|
ui.addNotification(null, notification),
|
||||||
);
|
);
|
||||||
lastValues = newValues;
|
lastValues = newValues;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -421,11 +421,11 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.ListValue,
|
form.ListValue,
|
||||||
'user_domain_list_type',
|
'user_domain_list_type',
|
||||||
_('User Domain List Type'),
|
_('User Domain List Type'),
|
||||||
_('Select how to add your custom domains'),
|
_('Select how to add your custom domains'),
|
||||||
);
|
);
|
||||||
o.value('disabled', _('Disabled'));
|
o.value('disabled', _('Disabled'));
|
||||||
o.value('dynamic', _('Dynamic List'));
|
o.value('dynamic', _('Dynamic List'));
|
||||||
@@ -435,13 +435,13 @@ function createConfigSection(section) {
|
|||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.DynamicList,
|
form.DynamicList,
|
||||||
'user_domains',
|
'user_domains',
|
||||||
_('User Domains'),
|
_('User Domains'),
|
||||||
_(
|
_(
|
||||||
'Enter domain names without protocols (example: sub.example.com or example.com)',
|
'Enter domain names without protocols (example: sub.example.com or example.com)',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
o.placeholder = 'Domains list';
|
o.placeholder = 'Domains list';
|
||||||
o.depends('user_domain_list_type', 'dynamic');
|
o.depends('user_domain_list_type', 'dynamic');
|
||||||
@@ -463,16 +463,16 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.TextValue,
|
form.TextValue,
|
||||||
'user_domains_text',
|
'user_domains_text',
|
||||||
_('User Domains List'),
|
_('User Domains List'),
|
||||||
_(
|
_(
|
||||||
'Enter domain names separated by comma, space or newline. You can add comments after //',
|
'Enter domain names separated by comma, space or newline. You can add comments after //',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
o.placeholder =
|
o.placeholder =
|
||||||
'example.com, sub.example.com\n// Social networks\ndomain.com test.com // personal domains';
|
'example.com, sub.example.com\n// Social networks\ndomain.com test.com // personal domains';
|
||||||
o.depends('user_domain_list_type', 'text');
|
o.depends('user_domain_list_type', 'text');
|
||||||
o.rows = 8;
|
o.rows = 8;
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
@@ -487,7 +487,7 @@ function createConfigSection(section) {
|
|||||||
|
|
||||||
if (!domains.length) {
|
if (!domains.length) {
|
||||||
return _(
|
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.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,8 +495,8 @@ function createConfigSection(section) {
|
|||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
const errors = results
|
const errors = results
|
||||||
.filter((validation) => !validation.valid) // Leave only failed validations
|
.filter((validation) => !validation.valid) // Leave only failed validations
|
||||||
.map((validation) => _(`${validation.value}: ${validation.message}`)); // Collect validation errors
|
.map((validation) => _(`${validation.value}: ${validation.message}`)); // Collect validation errors
|
||||||
|
|
||||||
return [_('Validation errors:'), ...errors].join('\n');
|
return [_('Validation errors:'), ...errors].join('\n');
|
||||||
}
|
}
|
||||||
@@ -505,22 +505,22 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.Flag,
|
form.Flag,
|
||||||
'local_domain_lists_enabled',
|
'local_domain_lists_enabled',
|
||||||
_('Local Domain Lists'),
|
_('Local Domain Lists'),
|
||||||
_('Use the list from the router filesystem'),
|
_('Use the list from the router filesystem'),
|
||||||
);
|
);
|
||||||
o.default = '0';
|
o.default = '0';
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.DynamicList,
|
form.DynamicList,
|
||||||
'local_domain_lists',
|
'local_domain_lists',
|
||||||
_('Local Domain List Paths'),
|
_('Local Domain List Paths'),
|
||||||
_('Enter the list file path'),
|
_('Enter the list file path'),
|
||||||
);
|
);
|
||||||
o.placeholder = '/path/file.lst';
|
o.placeholder = '/path/file.lst';
|
||||||
o.depends('local_domain_lists_enabled', '1');
|
o.depends('local_domain_lists_enabled', '1');
|
||||||
@@ -542,22 +542,22 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.Flag,
|
form.Flag,
|
||||||
'remote_domain_lists_enabled',
|
'remote_domain_lists_enabled',
|
||||||
_('Remote Domain Lists'),
|
_('Remote Domain Lists'),
|
||||||
_('Download and use domain lists from remote URLs'),
|
_('Download and use domain lists from remote URLs'),
|
||||||
);
|
);
|
||||||
o.default = '0';
|
o.default = '0';
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.DynamicList,
|
form.DynamicList,
|
||||||
'remote_domain_lists',
|
'remote_domain_lists',
|
||||||
_('Remote Domain URLs'),
|
_('Remote Domain URLs'),
|
||||||
_('Enter full URLs starting with http:// or https://'),
|
_('Enter full URLs starting with http:// or https://'),
|
||||||
);
|
);
|
||||||
o.placeholder = 'URL';
|
o.placeholder = 'URL';
|
||||||
o.depends('remote_domain_lists_enabled', '1');
|
o.depends('remote_domain_lists_enabled', '1');
|
||||||
@@ -579,22 +579,22 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.Flag,
|
form.Flag,
|
||||||
'local_subnet_lists_enabled',
|
'local_subnet_lists_enabled',
|
||||||
_('Local Subnet Lists'),
|
_('Local Subnet Lists'),
|
||||||
_('Use the list from the router filesystem'),
|
_('Use the list from the router filesystem'),
|
||||||
);
|
);
|
||||||
o.default = '0';
|
o.default = '0';
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.DynamicList,
|
form.DynamicList,
|
||||||
'local_subnet_lists',
|
'local_subnet_lists',
|
||||||
_('Local Subnet List Paths'),
|
_('Local Subnet List Paths'),
|
||||||
_('Enter the list file path'),
|
_('Enter the list file path'),
|
||||||
);
|
);
|
||||||
o.placeholder = '/path/file.lst';
|
o.placeholder = '/path/file.lst';
|
||||||
o.depends('local_subnet_lists_enabled', '1');
|
o.depends('local_subnet_lists_enabled', '1');
|
||||||
@@ -616,11 +616,11 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.ListValue,
|
form.ListValue,
|
||||||
'user_subnet_list_type',
|
'user_subnet_list_type',
|
||||||
_('User Subnet List Type'),
|
_('User Subnet List Type'),
|
||||||
_('Select how to add your custom subnets'),
|
_('Select how to add your custom subnets'),
|
||||||
);
|
);
|
||||||
o.value('disabled', _('Disabled'));
|
o.value('disabled', _('Disabled'));
|
||||||
o.value('dynamic', _('Dynamic List'));
|
o.value('dynamic', _('Dynamic List'));
|
||||||
@@ -630,13 +630,13 @@ function createConfigSection(section) {
|
|||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.DynamicList,
|
form.DynamicList,
|
||||||
'user_subnets',
|
'user_subnets',
|
||||||
_('User Subnets'),
|
_('User Subnets'),
|
||||||
_(
|
_(
|
||||||
'Enter subnets in CIDR notation (example: 103.21.244.0/22) or single IP addresses',
|
'Enter subnets in CIDR notation (example: 103.21.244.0/22) or single IP addresses',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
o.placeholder = 'IP or subnet';
|
o.placeholder = 'IP or subnet';
|
||||||
o.depends('user_subnet_list_type', 'dynamic');
|
o.depends('user_subnet_list_type', 'dynamic');
|
||||||
@@ -658,16 +658,16 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.TextValue,
|
form.TextValue,
|
||||||
'user_subnets_text',
|
'user_subnets_text',
|
||||||
_('User Subnets List'),
|
_('User Subnets List'),
|
||||||
_(
|
_(
|
||||||
'Enter subnets in CIDR notation or single IP addresses, separated by comma, space or newline. You can add comments after //',
|
'Enter subnets in CIDR notation or single IP addresses, separated by comma, space or newline. You can add comments after //',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
o.placeholder =
|
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';
|
'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.depends('user_subnet_list_type', 'text');
|
||||||
o.rows = 10;
|
o.rows = 10;
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
@@ -682,7 +682,7 @@ function createConfigSection(section) {
|
|||||||
|
|
||||||
if (!subnets.length) {
|
if (!subnets.length) {
|
||||||
return _(
|
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.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,8 +690,8 @@ function createConfigSection(section) {
|
|||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
const errors = results
|
const errors = results
|
||||||
.filter((validation) => !validation.valid) // Leave only failed validations
|
.filter((validation) => !validation.valid) // Leave only failed validations
|
||||||
.map((validation) => _(`${validation.value}: ${validation.message}`)); // Collect validation errors
|
.map((validation) => _(`${validation.value}: ${validation.message}`)); // Collect validation errors
|
||||||
|
|
||||||
return [_('Validation errors:'), ...errors].join('\n');
|
return [_('Validation errors:'), ...errors].join('\n');
|
||||||
}
|
}
|
||||||
@@ -700,22 +700,22 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.Flag,
|
form.Flag,
|
||||||
'remote_subnet_lists_enabled',
|
'remote_subnet_lists_enabled',
|
||||||
_('Remote Subnet Lists'),
|
_('Remote Subnet Lists'),
|
||||||
_('Download and use subnet lists from remote URLs'),
|
_('Download and use subnet lists from remote URLs'),
|
||||||
);
|
);
|
||||||
o.default = '0';
|
o.default = '0';
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.DynamicList,
|
form.DynamicList,
|
||||||
'remote_subnet_lists',
|
'remote_subnet_lists',
|
||||||
_('Remote Subnet URLs'),
|
_('Remote Subnet URLs'),
|
||||||
_('Enter full URLs starting with http:// or https://'),
|
_('Enter full URLs starting with http:// or https://'),
|
||||||
);
|
);
|
||||||
o.placeholder = 'URL';
|
o.placeholder = 'URL';
|
||||||
o.depends('remote_subnet_lists_enabled', '1');
|
o.depends('remote_subnet_lists_enabled', '1');
|
||||||
@@ -737,24 +737,24 @@ function createConfigSection(section) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.Flag,
|
form.Flag,
|
||||||
'all_traffic_from_ip_enabled',
|
'all_traffic_from_ip_enabled',
|
||||||
_('IP for full redirection'),
|
_('IP for full redirection'),
|
||||||
_(
|
_(
|
||||||
'Specify local IP addresses whose traffic will always use the configured route',
|
'Specify local IP addresses whose traffic will always use the configured route',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
o.default = '0';
|
o.default = '0';
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
o.ucisection = s.section;
|
o.ucisection = s.section;
|
||||||
|
|
||||||
o = s.taboption(
|
o = s.taboption(
|
||||||
'basic',
|
'basic',
|
||||||
form.DynamicList,
|
form.DynamicList,
|
||||||
'all_traffic_ip',
|
'all_traffic_ip',
|
||||||
_('Local IPs'),
|
_('Local IPs'),
|
||||||
_('Enter valid IPv4 addresses'),
|
_('Enter valid IPv4 addresses'),
|
||||||
);
|
);
|
||||||
o.placeholder = 'IP';
|
o.placeholder = 'IP';
|
||||||
o.depends('all_traffic_from_ip_enabled', '1');
|
o.depends('all_traffic_from_ip_enabled', '1');
|
||||||
|
|||||||
@@ -8,19 +8,19 @@
|
|||||||
'require view.podkop.main as main';
|
'require view.podkop.main as main';
|
||||||
|
|
||||||
function createDashboardSection(mainSection) {
|
function createDashboardSection(mainSection) {
|
||||||
let o = mainSection.tab('dashboard', _('Dashboard'));
|
let o = mainSection.tab('dashboard', _('Dashboard'));
|
||||||
|
|
||||||
o = mainSection.taboption('dashboard', form.DummyValue, '_status');
|
o = mainSection.taboption('dashboard', form.DummyValue, '_status');
|
||||||
o.rawhtml = true;
|
o.rawhtml = true;
|
||||||
o.cfgvalue = () => {
|
o.cfgvalue = () => {
|
||||||
main.initDashboardController()
|
main.initDashboardController();
|
||||||
|
|
||||||
return main.renderDashboard()
|
return main.renderDashboard();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const EntryPoint = {
|
const EntryPoint = {
|
||||||
createDashboardSection,
|
createDashboardSection,
|
||||||
}
|
};
|
||||||
|
|
||||||
return baseclass.extend(EntryPoint);
|
return baseclass.extend(EntryPoint);
|
||||||
|
|||||||
@@ -10,88 +10,73 @@
|
|||||||
'require view.podkop.main as main';
|
'require view.podkop.main as main';
|
||||||
|
|
||||||
const EntryNode = {
|
const EntryNode = {
|
||||||
async render() {
|
async render() {
|
||||||
main.injectGlobalStyles();
|
main.injectGlobalStyles();
|
||||||
|
|
||||||
// main.getClashVersion()
|
const podkopFormMap = new form.Map('podkop', '', null, ['main', 'extra']);
|
||||||
// .then(result => console.log('getClashVersion - then', result))
|
|
||||||
// .catch(err => console.log('getClashVersion - err', err))
|
|
||||||
// .finally(() => console.log('getClashVersion - finish'));
|
|
||||||
//
|
|
||||||
// main.getClashConfig()
|
|
||||||
// .then(result => console.log('getClashConfig - then', result))
|
|
||||||
// .catch(err => console.log('getClashConfig - err', err))
|
|
||||||
// .finally(() => console.log('getClashConfig - finish'));
|
|
||||||
//
|
|
||||||
// main.getClashProxies()
|
|
||||||
// .then(result => console.log('getClashProxies - then', result))
|
|
||||||
// .catch(err => console.log('getClashProxies - err', err))
|
|
||||||
// .finally(() => console.log('getClashProxies - finish'));
|
|
||||||
|
|
||||||
const podkopFormMap = new form.Map('podkop', '', null, ['main', 'extra']);
|
// Main Section
|
||||||
|
const mainSection = podkopFormMap.section(form.TypedSection, 'main');
|
||||||
|
mainSection.anonymous = true;
|
||||||
|
|
||||||
// Main Section
|
configSection.createConfigSection(mainSection);
|
||||||
const mainSection = podkopFormMap.section(form.TypedSection, 'main');
|
|
||||||
mainSection.anonymous = true;
|
|
||||||
|
|
||||||
configSection.createConfigSection(mainSection);
|
// Additional Settings Tab (main section)
|
||||||
|
additionalTab.createAdditionalSection(mainSection);
|
||||||
|
|
||||||
// Additional Settings Tab (main section)
|
// Diagnostics Tab (main section)
|
||||||
additionalTab.createAdditionalSection(mainSection);
|
diagnosticTab.createDiagnosticsSection(mainSection);
|
||||||
|
const podkopFormMapPromise = podkopFormMap.render().then((node) => {
|
||||||
|
// Set up diagnostics event handlers
|
||||||
|
diagnosticTab.setupDiagnosticsEventHandlers(node);
|
||||||
|
|
||||||
// Diagnostics Tab (main section)
|
// Start critical error polling for all tabs
|
||||||
diagnosticTab.createDiagnosticsSection(mainSection);
|
utils.startErrorPolling();
|
||||||
const podkopFormMapPromise = podkopFormMap.render().then(node => {
|
|
||||||
// Set up diagnostics event handlers
|
|
||||||
diagnosticTab.setupDiagnosticsEventHandlers(node);
|
|
||||||
|
|
||||||
// Start critical error polling for all tabs
|
// Add event listener to keep error polling active when switching tabs
|
||||||
|
const tabs = node.querySelectorAll('.cbi-tabmenu');
|
||||||
|
if (tabs.length > 0) {
|
||||||
|
tabs[0].addEventListener('click', function (e) {
|
||||||
|
const tab = e.target.closest('.cbi-tab');
|
||||||
|
if (tab) {
|
||||||
|
// Ensure error polling continues when switching tabs
|
||||||
utils.startErrorPolling();
|
utils.startErrorPolling();
|
||||||
|
}
|
||||||
// Add event listener to keep error polling active when switching tabs
|
|
||||||
const tabs = node.querySelectorAll('.cbi-tabmenu');
|
|
||||||
if (tabs.length > 0) {
|
|
||||||
tabs[0].addEventListener('click', function (e) {
|
|
||||||
const tab = e.target.closest('.cbi-tab');
|
|
||||||
if (tab) {
|
|
||||||
// Ensure error polling continues when switching tabs
|
|
||||||
utils.startErrorPolling();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add visibility change handler to manage error polling
|
|
||||||
document.addEventListener('visibilitychange', function () {
|
|
||||||
if (document.hidden) {
|
|
||||||
utils.stopErrorPolling();
|
|
||||||
} else {
|
|
||||||
utils.startErrorPolling();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return node;
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Extra Section
|
// Add visibility change handler to manage error polling
|
||||||
const extraSection = podkopFormMap.section(form.TypedSection, 'extra', _('Extra configurations'));
|
document.addEventListener('visibilitychange', function () {
|
||||||
extraSection.anonymous = false;
|
if (document.hidden) {
|
||||||
extraSection.addremove = true;
|
utils.stopErrorPolling();
|
||||||
extraSection.addbtntitle = _('Add Section');
|
} else {
|
||||||
extraSection.multiple = true;
|
utils.startErrorPolling();
|
||||||
configSection.createConfigSection(extraSection);
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return node;
|
||||||
|
});
|
||||||
|
|
||||||
// Initial dashboard render
|
// Extra Section
|
||||||
dashboardTab.createDashboardSection(mainSection);
|
const extraSection = podkopFormMap.section(
|
||||||
|
form.TypedSection,
|
||||||
|
'extra',
|
||||||
|
_('Extra configurations'),
|
||||||
|
);
|
||||||
|
extraSection.anonymous = false;
|
||||||
|
extraSection.addremove = true;
|
||||||
|
extraSection.addbtntitle = _('Add Section');
|
||||||
|
extraSection.multiple = true;
|
||||||
|
configSection.createConfigSection(extraSection);
|
||||||
|
|
||||||
// Inject dashboard actualizer logic
|
// Initial dashboard render
|
||||||
// main.initDashboardController();
|
dashboardTab.createDashboardSection(mainSection);
|
||||||
|
|
||||||
// Inject core service
|
// Inject core service
|
||||||
main.coreService();
|
main.coreService();
|
||||||
|
|
||||||
return podkopFormMapPromise;
|
return podkopFormMapPromise;
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
return view.extend(EntryNode);
|
return view.extend(EntryNode);
|
||||||
|
|||||||
Reference in New Issue
Block a user