diff --git a/fe-app-podkop/src/constants.ts b/fe-app-podkop/src/constants.ts index 7f39c3f..bdfe8f8 100644 --- a/fe-app-podkop/src/constants.ts +++ b/fe-app-podkop/src/constants.ts @@ -104,4 +104,4 @@ export const COMMAND_SCHEDULING = { P8_PRIORITY: 1500, // Background execution P9_PRIORITY: 1700, // Idle mode execution P10_PRIORITY: 1900, // Lowest priority -}; +} as const; diff --git a/fe-app-podkop/src/validators/index.ts b/fe-app-podkop/src/validators/index.ts index fd9e2cc..88e6b03 100644 --- a/fe-app-podkop/src/validators/index.ts +++ b/fe-app-podkop/src/validators/index.ts @@ -9,3 +9,4 @@ export * from './validateShadowsocksUrl'; export * from './validateVlessUrl'; export * from './validateOutboundJson'; export * from './validateTrojanUrl'; +export * from './validateProxyUrl'; diff --git a/fe-app-podkop/src/validators/validateProxyUrl.ts b/fe-app-podkop/src/validators/validateProxyUrl.ts new file mode 100644 index 0000000..b9ef593 --- /dev/null +++ b/fe-app-podkop/src/validators/validateProxyUrl.ts @@ -0,0 +1,24 @@ +import { ValidationResult } from './types'; +import { validateShadowsocksUrl } from './validateShadowsocksUrl'; +import { validateVlessUrl } from './validateVlessUrl'; +import { validateTrojanUrl } from './validateTrojanUrl'; + +// TODO refactor current validation and add tests +export function validateProxyUrl(url: string): ValidationResult { + if (url.startsWith('ss://')) { + return validateShadowsocksUrl(url); + } + + if (url.startsWith('vless://')) { + return validateVlessUrl(url); + } + + if (url.startsWith('trojan://')) { + return validateTrojanUrl(url); + } + + return { + valid: false, + message: 'URL must start with vless:// or ss:// or trojan://', + }; +} diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/configSection.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/configSection.js index a842d46..0c215c6 100644 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/configSection.js +++ b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/configSection.js @@ -92,38 +92,13 @@ function createConfigSection(section) { return _('No active configuration found. At least one non-commented line is required.'); } - if (activeConfig.startsWith('ss://')) { - const validation = main.validateShadowsocksUrl(activeConfig); + const validation = main.validateProxyUrl(activeConfig); - if (validation.valid) { - return true; - } - - return _(validation.message) + if (validation.valid) { + return true; } - if (activeConfig.startsWith('vless://')) { - const validation = main.validateVlessUrl(activeConfig); - - if (validation.valid) { - return true; - } - - return _(validation.message) - } - - if (activeConfig.startsWith('trojan://')) { - const validation = main.validateTrojanUrl(activeConfig); - - if (validation.valid) { - return true; - } - - return _(validation.message) - } - - return _('URL must start with vless:// or ss:// or trojan://') - + return _(validation.message) } catch (e) { return `${_('Invalid URL format:')} ${e?.message}`; } @@ -150,11 +125,25 @@ function createConfigSection(section) { o = s.taboption('basic', form.DynamicList, 'urltest_proxy_links', _('URLTest Proxy Links')); o.depends('proxy_config_type', 'urltest'); - o.placeholder = 'vless:// or ss:// link'; + o.placeholder = 'vless://, ss://, trojan:// links'; o.rmempty = false; o.textarea = true; o.rows = 3; o.wrap = 'soft'; + o.validate = function (section_id, value) { + // Optional + if (!value || value.length === 0) { + return true + } + + const validation = main.validateProxyUrl(value); + + if (validation.valid) { + return true; + } + + return _(validation.message) + }; o = s.taboption('basic', form.Flag, 'ss_uot', _('Shadowsocks UDP over TCP'), _('Apply for SS2022')); o.default = '0'; diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js index ae3ee34..130c9fb 100644 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js +++ b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/main.js @@ -299,6 +299,23 @@ function validateTrojanUrl(url) { return { valid: true, message: "Valid" }; } +// src/validators/validateProxyUrl.ts +function validateProxyUrl(url) { + if (url.startsWith("ss://")) { + return validateShadowsocksUrl(url); + } + if (url.startsWith("vless://")) { + return validateVlessUrl(url); + } + if (url.startsWith("trojan://")) { + return validateTrojanUrl(url); + } + return { + valid: false, + message: "URL must start with vless:// or ss:// or trojan://" + }; +} + // src/helpers/getBaseUrl.ts function getBaseUrl() { const { protocol, hostname } = window.location; @@ -485,6 +502,7 @@ return baseclass.extend({ validateIPV4, validateOutboundJson, validatePath, + validateProxyUrl, validateShadowsocksUrl, validateSubnet, validateTrojanUrl,