From 5e95148492ee8a7d611d7d3ad9b1808a3d12c8f6 Mon Sep 17 00:00:00 2001 From: divocat Date: Thu, 2 Oct 2025 22:23:41 +0300 Subject: [PATCH] feat: migrate constants to modular --- fe-app-podkop/src/constants.ts | 91 ++++++++++++++ fe-app-podkop/src/main.ts | 1 + .../resources/view/podkop/additionalTab.js | 5 +- .../resources/view/podkop/configSection.js | 15 ++- .../resources/view/podkop/constants.js | 113 ------------------ .../resources/view/podkop/diagnosticTab.js | 66 +++++----- .../luci-static/resources/view/podkop/main.js | 112 +++++++++++++++++ .../resources/view/podkop/utils.js | 14 +-- 8 files changed, 253 insertions(+), 164 deletions(-) create mode 100644 fe-app-podkop/src/constants.ts delete mode 100644 luci-app-podkop/htdocs/luci-static/resources/view/podkop/constants.js diff --git a/fe-app-podkop/src/constants.ts b/fe-app-podkop/src/constants.ts new file mode 100644 index 0000000..b0ccded --- /dev/null +++ b/fe-app-podkop/src/constants.ts @@ -0,0 +1,91 @@ +export const STATUS_COLORS = { + SUCCESS: '#4caf50', + ERROR: '#f44336', + WARNING: '#ff9800' +}; + +export const FAKEIP_CHECK_DOMAIN = 'fakeip.podkop.fyi'; +export const IP_CHECK_DOMAIN = 'ip.podkop.fyi'; + +export const REGIONAL_OPTIONS = ['russia_inside', 'russia_outside', 'ukraine_inside']; +export const ALLOWED_WITH_RUSSIA_INSIDE = [ + 'russia_inside', + 'meta', + 'twitter', + 'discord', + 'telegram', + 'cloudflare', + 'google_ai', + 'google_play', + 'hetzner', + 'ovh', + 'hodca', + 'digitalocean', + 'cloudfront' +]; + +export const DOMAIN_LIST_OPTIONS = { + russia_inside: 'Russia inside', + russia_outside: 'Russia outside', + ukraine_inside: 'Ukraine', + geoblock: 'Geo Block', + block: 'Block', + porn: 'Porn', + news: 'News', + anime: 'Anime', + youtube: 'Youtube', + discord: 'Discord', + meta: 'Meta', + twitter: 'Twitter (X)', + hdrezka: 'HDRezka', + tiktok: 'Tik-Tok', + telegram: 'Telegram', + cloudflare: 'Cloudflare', + google_ai: 'Google AI', + google_play: 'Google Play', + hodca: 'H.O.D.C.A', + hetzner: 'Hetzner ASN', + ovh: 'OVH ASN', + digitalocean: 'Digital Ocean ASN', + cloudfront: 'CloudFront ASN' +}; + +export const UPDATE_INTERVAL_OPTIONS = { + '1h': 'Every hour', + '3h': 'Every 3 hours', + '12h': 'Every 12 hours', + '1d': 'Every day', + '3d': 'Every 3 days' +}; + +export const DNS_SERVER_OPTIONS = { + '1.1.1.1': '1.1.1.1 (Cloudflare)', + '8.8.8.8': '8.8.8.8 (Google)', + '9.9.9.9': '9.9.9.9 (Quad9)', + 'dns.adguard-dns.com': 'dns.adguard-dns.com (AdGuard Default)', + 'unfiltered.adguard-dns.com': 'unfiltered.adguard-dns.com (AdGuard Unfiltered)', + 'family.adguard-dns.com': 'family.adguard-dns.com (AdGuard Family)' +}; + +export const DIAGNOSTICS_UPDATE_INTERVAL = 10000; // 10 seconds +export const CACHE_TIMEOUT = DIAGNOSTICS_UPDATE_INTERVAL - 1000; // 9 seconds +export const ERROR_POLL_INTERVAL = 10000; // 10 seconds +export const COMMAND_TIMEOUT = 10000; // 10 seconds +export const FETCH_TIMEOUT = 10000; // 10 seconds +export const BUTTON_FEEDBACK_TIMEOUT = 1000; // 1 second +export const DIAGNOSTICS_INITIAL_DELAY = 100; // 100 milliseconds + +// Command scheduling intervals in diagnostics (in milliseconds) +export const COMMAND_SCHEDULING = { + P0_PRIORITY: 0, // Highest priority (no delay) + P1_PRIORITY: 100, // Very high priority + P2_PRIORITY: 300, // High priority + P3_PRIORITY: 500, // Above average + P4_PRIORITY: 700, // Standard priority + P5_PRIORITY: 900, // Below average + P6_PRIORITY: 1100, // Low priority + P7_PRIORITY: 1300, // Very low priority + P8_PRIORITY: 1500, // Background execution + P9_PRIORITY: 1700, // Idle mode execution + P10_PRIORITY: 1900 // Lowest priority +}; diff --git a/fe-app-podkop/src/main.ts b/fe-app-podkop/src/main.ts index 88d79ca..bc2665e 100644 --- a/fe-app-podkop/src/main.ts +++ b/fe-app-podkop/src/main.ts @@ -2,3 +2,4 @@ 'require baseclass'; export * from './validators'; +export * from './constants' diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/additionalTab.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/additionalTab.js index 3fc6170..397a0d7 100644 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/additionalTab.js +++ b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/additionalTab.js @@ -1,7 +1,6 @@ 'use strict'; 'require form'; 'require baseclass'; -'require view.podkop.constants as constants'; 'require tools.widgets as widgets'; 'require view.podkop.main as main'; @@ -24,7 +23,7 @@ function createAdditionalSection(mainSection) { o.ucisection = 'main'; o = mainSection.taboption('additional', form.ListValue, 'update_interval', _('List Update Frequency'), _('Select how often the lists will be updated')); - Object.entries(constants.UPDATE_INTERVAL_OPTIONS).forEach(([key, label]) => { + Object.entries(main.UPDATE_INTERVAL_OPTIONS).forEach(([key, label]) => { o.value(key, _(label)); }); o.default = '1d'; @@ -40,7 +39,7 @@ function createAdditionalSection(mainSection) { o.ucisection = 'main'; o = mainSection.taboption('additional', form.Value, 'dns_server', _('DNS Server'), _('Select or enter DNS server address')); - Object.entries(constants.DNS_SERVER_OPTIONS).forEach(([key, label]) => { + Object.entries(main.DNS_SERVER_OPTIONS).forEach(([key, label]) => { o.value(key, _(label)); }); o.default = '8.8.8.8'; 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 59653fc..cdca7be 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 @@ -3,7 +3,6 @@ 'require form'; 'require ui'; 'require network'; -'require view.podkop.constants as constants'; 'require view.podkop.main as main'; 'require tools.widgets as widgets'; @@ -246,7 +245,7 @@ function createConfigSection(section, map, network) { o.ucisection = s.section; o = s.taboption('basic', form.Value, 'domain_resolver_dns_server', _('DNS Server'), _('Select or enter DNS server address')); - Object.entries(constants.DNS_SERVER_OPTIONS).forEach(([key, label]) => { + Object.entries(main.DNS_SERVER_OPTIONS).forEach(([key, label]) => { o.value(key, _(label)); }); o.default = '8.8.8.8'; @@ -270,7 +269,7 @@ function createConfigSection(section, map, network) { o = s.taboption('basic', form.DynamicList, 'community_lists', _('Service List'), _('Select predefined service for routing') + ' github.com/itdoginfo/allow-domains'); o.placeholder = 'Service list'; - Object.entries(constants.DOMAIN_LIST_OPTIONS).forEach(([key, label]) => { + Object.entries(main.DOMAIN_LIST_OPTIONS).forEach(([key, label]) => { o.value(key, _(label)); }); o.depends('community_lists_enabled', '1'); @@ -289,12 +288,12 @@ function createConfigSection(section, map, network) { let newValues = [...values]; let notifications = []; - const selectedRegionalOptions = constants.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 removedRegions = selectedRegionalOptions.slice(0, -1); - newValues = newValues.filter(v => v === lastSelected || !constants.REGIONAL_OPTIONS.includes(v)); + 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.') @@ -303,14 +302,14 @@ function createConfigSection(section, map, network) { } if (newValues.includes('russia_inside')) { - const removedServices = newValues.filter(v => !constants.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 => constants.ALLOWED_WITH_RUSSIA_INSIDE.includes(v)); + 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( - constants.ALLOWED_WITH_RUSSIA_INSIDE.map(key => constants.DOMAIN_LIST_OPTIONS[key]).filter(label => label !== 'Russia inside').join(', '), + main.ALLOWED_WITH_RUSSIA_INSIDE.map(key => main.DOMAIN_LIST_OPTIONS[key]).filter(label => label !== 'Russia inside').join(', '), removedServices.join(', ') ) ])); diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/constants.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/constants.js deleted file mode 100644 index d6c5858..0000000 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/constants.js +++ /dev/null @@ -1,113 +0,0 @@ -'use strict'; -'require baseclass'; - -const STATUS_COLORS = { - SUCCESS: '#4caf50', - ERROR: '#f44336', - WARNING: '#ff9800' -}; - -const FAKEIP_CHECK_DOMAIN = 'fakeip.podkop.fyi'; -const IP_CHECK_DOMAIN = 'ip.podkop.fyi'; - -const REGIONAL_OPTIONS = ['russia_inside', 'russia_outside', 'ukraine_inside']; -const ALLOWED_WITH_RUSSIA_INSIDE = [ - 'russia_inside', - 'meta', - 'twitter', - 'discord', - 'telegram', - 'cloudflare', - 'google_ai', - 'google_play', - 'hetzner', - 'ovh', - 'hodca', - 'digitalocean', - 'cloudfront' -]; - -const DOMAIN_LIST_OPTIONS = { - russia_inside: 'Russia inside', - russia_outside: 'Russia outside', - ukraine_inside: 'Ukraine', - geoblock: 'Geo Block', - block: 'Block', - porn: 'Porn', - news: 'News', - anime: 'Anime', - youtube: 'Youtube', - discord: 'Discord', - meta: 'Meta', - twitter: 'Twitter (X)', - hdrezka: 'HDRezka', - tiktok: 'Tik-Tok', - telegram: 'Telegram', - cloudflare: 'Cloudflare', - google_ai: 'Google AI', - google_play: 'Google Play', - hodca: 'H.O.D.C.A', - hetzner: 'Hetzner ASN', - ovh: 'OVH ASN', - digitalocean: 'Digital Ocean ASN', - cloudfront: 'CloudFront ASN' -}; - -const UPDATE_INTERVAL_OPTIONS = { - '1h': 'Every hour', - '3h': 'Every 3 hours', - '12h': 'Every 12 hours', - '1d': 'Every day', - '3d': 'Every 3 days' -}; - -const DNS_SERVER_OPTIONS = { - '1.1.1.1': '1.1.1.1 (Cloudflare)', - '8.8.8.8': '8.8.8.8 (Google)', - '9.9.9.9': '9.9.9.9 (Quad9)', - 'dns.adguard-dns.com': 'dns.adguard-dns.com (AdGuard Default)', - 'unfiltered.adguard-dns.com': 'unfiltered.adguard-dns.com (AdGuard Unfiltered)', - 'family.adguard-dns.com': 'family.adguard-dns.com (AdGuard Family)' -}; - -const DIAGNOSTICS_UPDATE_INTERVAL = 10000; // 10 seconds -const CACHE_TIMEOUT = DIAGNOSTICS_UPDATE_INTERVAL - 1000; // 9 seconds -const ERROR_POLL_INTERVAL = 10000; // 10 seconds -const COMMAND_TIMEOUT = 10000; // 10 seconds -const FETCH_TIMEOUT = 10000; // 10 seconds -const BUTTON_FEEDBACK_TIMEOUT = 1000; // 1 second -const DIAGNOSTICS_INITIAL_DELAY = 100; // 100 milliseconds - -// Интервалы планирования команд в диагностике (в миллисекундах) -const COMMAND_SCHEDULING = { - P0_PRIORITY: 0, // Наивысший приоритет (без задержки) - P1_PRIORITY: 100, // Очень высокий приоритет - P2_PRIORITY: 300, // Высокий приоритет - P3_PRIORITY: 500, // Выше среднего - P4_PRIORITY: 700, // Стандартный приоритет - P5_PRIORITY: 900, // Ниже среднего - P6_PRIORITY: 1100, // Низкий приоритет - P7_PRIORITY: 1300, // Очень низкий приоритет - P8_PRIORITY: 1500, // Фоновое выполнение - P9_PRIORITY: 1700, // Выполнение в режиме простоя - P10_PRIORITY: 1900 // Наименьший приоритет -}; - -return baseclass.extend({ - STATUS_COLORS, - FAKEIP_CHECK_DOMAIN, - IP_CHECK_DOMAIN, - REGIONAL_OPTIONS, - ALLOWED_WITH_RUSSIA_INSIDE, - DOMAIN_LIST_OPTIONS, - UPDATE_INTERVAL_OPTIONS, - DNS_SERVER_OPTIONS, - DIAGNOSTICS_UPDATE_INTERVAL, - ERROR_POLL_INTERVAL, - COMMAND_TIMEOUT, - FETCH_TIMEOUT, - BUTTON_FEEDBACK_TIMEOUT, - DIAGNOSTICS_INITIAL_DELAY, - COMMAND_SCHEDULING, - CACHE_TIMEOUT -}); diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/diagnosticTab.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/diagnosticTab.js index 4ca06f5..a316a15 100644 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/diagnosticTab.js +++ b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/diagnosticTab.js @@ -4,8 +4,8 @@ 'require ui'; 'require uci'; 'require fs'; -'require view.podkop.constants as constants'; 'require view.podkop.utils as utils'; +'require view.podkop.main as main'; // Cache system for network requests const fetchCache = {}; @@ -16,7 +16,7 @@ async function cachedFetch(url, options = {}) { const currentTime = Date.now(); // If we have a valid cached response, return it - if (fetchCache[cacheKey] && currentTime - fetchCache[cacheKey].timestamp < constants.CACHE_TIMEOUT) { + if (fetchCache[cacheKey] && currentTime - fetchCache[cacheKey].timestamp < main.CACHE_TIMEOUT) { console.log(`Using cached response for ${url}`); return Promise.resolve(fetchCache[cacheKey].response.clone()); } @@ -38,18 +38,18 @@ async function cachedFetch(url, options = {}) { } // Helper functions for command execution with prioritization - Using from utils.js now -function safeExec(command, args, priority, callback, timeout = constants.COMMAND_TIMEOUT) { +function safeExec(command, args, priority, callback, timeout = main.COMMAND_TIMEOUT) { return utils.safeExec(command, args, priority, callback, timeout); } // Helper functions for handling checks function runCheck(checkFunction, priority, callback) { // Default to highest priority execution if priority is not provided or invalid - let schedulingDelay = constants.COMMAND_SCHEDULING.P0_PRIORITY; + let schedulingDelay = main.COMMAND_SCHEDULING.P0_PRIORITY; // If priority is a string, try to get the corresponding delay value - if (typeof priority === 'string' && constants.COMMAND_SCHEDULING[priority] !== undefined) { - schedulingDelay = constants.COMMAND_SCHEDULING[priority]; + if (typeof priority === 'string' && main.COMMAND_SCHEDULING[priority] !== undefined) { + schedulingDelay = main.COMMAND_SCHEDULING[priority]; } const executeCheck = async () => { @@ -77,11 +77,11 @@ function runCheck(checkFunction, priority, callback) { function runAsyncTask(taskFunction, priority) { // Default to highest priority execution if priority is not provided or invalid - let schedulingDelay = constants.COMMAND_SCHEDULING.P0_PRIORITY; + let schedulingDelay = main.COMMAND_SCHEDULING.P0_PRIORITY; // If priority is a string, try to get the corresponding delay value - if (typeof priority === 'string' && constants.COMMAND_SCHEDULING[priority] !== undefined) { - schedulingDelay = constants.COMMAND_SCHEDULING[priority]; + if (typeof priority === 'string' && main.COMMAND_SCHEDULING[priority] !== undefined) { + schedulingDelay = main.COMMAND_SCHEDULING[priority]; } setTimeout(async () => { @@ -98,7 +98,7 @@ function createStatus(state, message, color) { return { state, message: _(message), - color: constants.STATUS_COLORS[color] + color: main.STATUS_COLORS[color] }; } @@ -119,7 +119,7 @@ function copyToClipboard(text, button) { document.execCommand('copy'); const originalText = button.textContent; button.textContent = _('Copied!'); - setTimeout(() => button.textContent = originalText, constants.BUTTON_FEEDBACK_TIMEOUT); + setTimeout(() => button.textContent = originalText, main.BUTTON_FEEDBACK_TIMEOUT); } catch (err) { ui.addNotification(null, E('p', {}, _('Failed to copy: ') + err.message)); } @@ -138,10 +138,10 @@ function maskIP(ip) { async function checkFakeIP() { try { const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), constants.FETCH_TIMEOUT); + const timeoutId = setTimeout(() => controller.abort(), main.FETCH_TIMEOUT); try { - const response = await cachedFetch(`https://${constants.FAKEIP_CHECK_DOMAIN}/check`, { signal: controller.signal }); + const response = await cachedFetch(`https://${main.FAKEIP_CHECK_DOMAIN}/check`, { signal: controller.signal }); const data = await response.json(); clearTimeout(timeoutId); @@ -163,7 +163,7 @@ async function checkFakeIP() { async function checkFakeIPCLI() { try { return new Promise((resolve) => { - safeExec('nslookup', ['-timeout=2', constants.FAKEIP_CHECK_DOMAIN, '127.0.0.42'], 'P0_PRIORITY', result => { + safeExec('nslookup', ['-timeout=2', main.FAKEIP_CHECK_DOMAIN, '127.0.0.42'], 'P0_PRIORITY', result => { if (result.stdout && result.stdout.includes('198.18')) { resolve(createStatus('working', 'working on router', 'SUCCESS')); } else { @@ -221,13 +221,13 @@ function checkDNSAvailability() { async function checkBypass() { try { const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), constants.FETCH_TIMEOUT); + const timeoutId = setTimeout(() => controller.abort(), main.FETCH_TIMEOUT); try { - const response1 = await cachedFetch(`https://${constants.FAKEIP_CHECK_DOMAIN}/check`, { signal: controller.signal }); + const response1 = await cachedFetch(`https://${main.FAKEIP_CHECK_DOMAIN}/check`, { signal: controller.signal }); const data1 = await response1.json(); - const response2 = await cachedFetch(`https://${constants.IP_CHECK_DOMAIN}/check`, { signal: controller.signal }); + const response2 = await cachedFetch(`https://${main.IP_CHECK_DOMAIN}/check`, { signal: controller.signal }); const data2 = await response2.json(); clearTimeout(timeoutId); @@ -327,9 +327,9 @@ function showConfigModal(command, title) { try { const controller = new AbortController(); - const timeoutId = setTimeout(() => controller.abort(), constants.FETCH_TIMEOUT); + const timeoutId = setTimeout(() => controller.abort(), main.FETCH_TIMEOUT); - cachedFetch(`https://${constants.FAKEIP_CHECK_DOMAIN}/check`, { signal: controller.signal }) + cachedFetch(`https://${main.FAKEIP_CHECK_DOMAIN}/check`, { signal: controller.signal }) .then(response => response.json()) .then(data => { clearTimeout(timeoutId); @@ -343,10 +343,10 @@ function showConfigModal(command, title) { } // Bypass check - cachedFetch(`https://${constants.FAKEIP_CHECK_DOMAIN}/check`, { signal: controller.signal }) + cachedFetch(`https://${main.FAKEIP_CHECK_DOMAIN}/check`, { signal: controller.signal }) .then(bypassResponse => bypassResponse.json()) .then(bypassData => { - cachedFetch(`https://${constants.IP_CHECK_DOMAIN}/check`, { signal: controller.signal }) + cachedFetch(`https://${main.IP_CHECK_DOMAIN}/check`, { signal: controller.signal }) .then(bypassResponse2 => bypassResponse2.json()) .then(bypassData2 => { formattedOutput += '━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'; @@ -602,7 +602,7 @@ function startDiagnosticsUpdates() { updateDiagnostics(); // Then set up periodic updates - diagnosticsUpdateTimer = setInterval(updateDiagnostics, constants.DIAGNOSTICS_UPDATE_INTERVAL); + diagnosticsUpdateTimer = setInterval(updateDiagnostics, main.DIAGNOSTICS_UPDATE_INTERVAL); } function stopDiagnosticsUpdates() { @@ -630,7 +630,7 @@ async function updateDiagnostics() { // Update Podkop status text updateTextElement('podkop-status-text', E('span', { - 'style': `color: ${parsedPodkopStatus.enabled ? constants.STATUS_COLORS.SUCCESS : constants.STATUS_COLORS.ERROR}` + 'style': `color: ${parsedPodkopStatus.enabled ? main.STATUS_COLORS.SUCCESS : main.STATUS_COLORS.ERROR}` }, [ parsedPodkopStatus.enabled ? '✔ Autostart enabled' : '✘ Autostart disabled' ]) @@ -661,7 +661,7 @@ async function updateDiagnostics() { } } catch (error) { updateTextElement('podkop-status-text', - E('span', { 'style': `color: ${constants.STATUS_COLORS.ERROR}` }, '✘ Error') + E('span', { 'style': `color: ${main.STATUS_COLORS.ERROR}` }, '✘ Error') ); } }); @@ -675,7 +675,7 @@ async function updateDiagnostics() { updateTextElement('singbox-status-text', E('span', { 'style': `color: ${parsedSingboxStatus.running && !parsedSingboxStatus.enabled ? - constants.STATUS_COLORS.SUCCESS : constants.STATUS_COLORS.ERROR}` + main.STATUS_COLORS.SUCCESS : main.STATUS_COLORS.ERROR}` }, [ parsedSingboxStatus.running && !parsedSingboxStatus.enabled ? '✔ running' : '✘ ' + parsedSingboxStatus.status @@ -683,7 +683,7 @@ async function updateDiagnostics() { ); } catch (error) { updateTextElement('singbox-status-text', - E('span', { 'style': `color: ${constants.STATUS_COLORS.ERROR}` }, '✘ Error') + E('span', { 'style': `color: ${main.STATUS_COLORS.ERROR}` }, '✘ Error') ); } }); @@ -724,7 +724,7 @@ async function updateDiagnostics() { // FakeIP and DNS status checks runCheck(checkFakeIP, 'P3_PRIORITY', result => { updateTextElement('fakeip-browser-status', - E('span', { style: `color: ${result.error ? constants.STATUS_COLORS.WARNING : result.color}` }, [ + E('span', { style: `color: ${result.error ? main.STATUS_COLORS.WARNING : result.color}` }, [ result.error ? '! ' : result.state === 'working' ? '✔ ' : result.state === 'not_working' ? '✘ ' : '! ', result.error ? 'check error' : result.state === 'working' ? _('works in browser') : _('does not work in browser') ]) @@ -733,7 +733,7 @@ async function updateDiagnostics() { runCheck(checkFakeIPCLI, 'P8_PRIORITY', result => { updateTextElement('fakeip-router-status', - E('span', { style: `color: ${result.error ? constants.STATUS_COLORS.WARNING : result.color}` }, [ + E('span', { style: `color: ${result.error ? main.STATUS_COLORS.WARNING : result.color}` }, [ result.error ? '! ' : result.state === 'working' ? '✔ ' : result.state === 'not_working' ? '✘ ' : '! ', result.error ? 'check error' : result.state === 'working' ? _('works on router') : _('does not work on router') ]) @@ -743,10 +743,10 @@ async function updateDiagnostics() { runCheck(checkDNSAvailability, 'P4_PRIORITY', result => { if (result.error) { updateTextElement('dns-remote-status', - E('span', { style: `color: ${constants.STATUS_COLORS.WARNING}` }, '! DNS check error') + E('span', { style: `color: ${main.STATUS_COLORS.WARNING}` }, '! DNS check error') ); updateTextElement('dns-local-status', - E('span', { style: `color: ${constants.STATUS_COLORS.WARNING}` }, '! DNS check error') + E('span', { style: `color: ${main.STATUS_COLORS.WARNING}` }, '! DNS check error') ); } else { updateTextElement('dns-remote-status', @@ -767,7 +767,7 @@ async function updateDiagnostics() { runCheck(checkBypass, 'P1_PRIORITY', result => { updateTextElement('bypass-status', - E('span', { style: `color: ${result.error ? constants.STATUS_COLORS.WARNING : result.color}` }, [ + E('span', { style: `color: ${result.error ? main.STATUS_COLORS.WARNING : result.color}` }, [ result.error ? '! ' : result.state === 'working' ? '✔ ' : result.state === 'not_working' ? '✘ ' : '! ', result.error ? 'check error' : result.message ]) @@ -875,7 +875,7 @@ function setupDiagnosticsEventHandlers(node) { } }); } - }, constants.DIAGNOSTICS_INITIAL_DELAY); + }, main.DIAGNOSTICS_INITIAL_DELAY); node.classList.add('fade-in'); return node; @@ -884,4 +884,4 @@ function setupDiagnosticsEventHandlers(node) { return baseclass.extend({ createDiagnosticsSection, setupDiagnosticsEventHandlers -}); \ No newline at end of file +}); 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 df15d3c..6b4953a 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 @@ -58,7 +58,119 @@ function validateUrl(url, protocols = ["http:", "https:"]) { return { valid: false, message: "Invalid URL format" }; } } + +// src/constants.ts +var STATUS_COLORS = { + SUCCESS: "#4caf50", + ERROR: "#f44336", + WARNING: "#ff9800" +}; +var FAKEIP_CHECK_DOMAIN = "fakeip.podkop.fyi"; +var IP_CHECK_DOMAIN = "ip.podkop.fyi"; +var REGIONAL_OPTIONS = ["russia_inside", "russia_outside", "ukraine_inside"]; +var ALLOWED_WITH_RUSSIA_INSIDE = [ + "russia_inside", + "meta", + "twitter", + "discord", + "telegram", + "cloudflare", + "google_ai", + "google_play", + "hetzner", + "ovh", + "hodca", + "digitalocean", + "cloudfront" +]; +var DOMAIN_LIST_OPTIONS = { + russia_inside: "Russia inside", + russia_outside: "Russia outside", + ukraine_inside: "Ukraine", + geoblock: "Geo Block", + block: "Block", + porn: "Porn", + news: "News", + anime: "Anime", + youtube: "Youtube", + discord: "Discord", + meta: "Meta", + twitter: "Twitter (X)", + hdrezka: "HDRezka", + tiktok: "Tik-Tok", + telegram: "Telegram", + cloudflare: "Cloudflare", + google_ai: "Google AI", + google_play: "Google Play", + hodca: "H.O.D.C.A", + hetzner: "Hetzner ASN", + ovh: "OVH ASN", + digitalocean: "Digital Ocean ASN", + cloudfront: "CloudFront ASN" +}; +var UPDATE_INTERVAL_OPTIONS = { + "1h": "Every hour", + "3h": "Every 3 hours", + "12h": "Every 12 hours", + "1d": "Every day", + "3d": "Every 3 days" +}; +var DNS_SERVER_OPTIONS = { + "1.1.1.1": "1.1.1.1 (Cloudflare)", + "8.8.8.8": "8.8.8.8 (Google)", + "9.9.9.9": "9.9.9.9 (Quad9)", + "dns.adguard-dns.com": "dns.adguard-dns.com (AdGuard Default)", + "unfiltered.adguard-dns.com": "unfiltered.adguard-dns.com (AdGuard Unfiltered)", + "family.adguard-dns.com": "family.adguard-dns.com (AdGuard Family)" +}; +var DIAGNOSTICS_UPDATE_INTERVAL = 1e4; +var CACHE_TIMEOUT = DIAGNOSTICS_UPDATE_INTERVAL - 1e3; +var ERROR_POLL_INTERVAL = 1e4; +var COMMAND_TIMEOUT = 1e4; +var FETCH_TIMEOUT = 1e4; +var BUTTON_FEEDBACK_TIMEOUT = 1e3; +var DIAGNOSTICS_INITIAL_DELAY = 100; +var COMMAND_SCHEDULING = { + P0_PRIORITY: 0, + // Highest priority (no delay) + P1_PRIORITY: 100, + // Very high priority + P2_PRIORITY: 300, + // High priority + P3_PRIORITY: 500, + // Above average + P4_PRIORITY: 700, + // Standard priority + P5_PRIORITY: 900, + // Below average + P6_PRIORITY: 1100, + // Low priority + P7_PRIORITY: 1300, + // Very low priority + P8_PRIORITY: 1500, + // Background execution + P9_PRIORITY: 1700, + // Idle mode execution + P10_PRIORITY: 1900 + // Lowest priority +}; return baseclass.extend({ + ALLOWED_WITH_RUSSIA_INSIDE, + BUTTON_FEEDBACK_TIMEOUT, + CACHE_TIMEOUT, + COMMAND_SCHEDULING, + COMMAND_TIMEOUT, + DIAGNOSTICS_INITIAL_DELAY, + DIAGNOSTICS_UPDATE_INTERVAL, + DNS_SERVER_OPTIONS, + DOMAIN_LIST_OPTIONS, + ERROR_POLL_INTERVAL, + FAKEIP_CHECK_DOMAIN, + FETCH_TIMEOUT, + IP_CHECK_DOMAIN, + REGIONAL_OPTIONS, + STATUS_COLORS, + UPDATE_INTERVAL_OPTIONS, validateDNS, validateDomain, validateIPV4, diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/utils.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/utils.js index 164afb9..46cb086 100644 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/utils.js +++ b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/utils.js @@ -2,7 +2,7 @@ 'require baseclass'; 'require ui'; 'require fs'; -'require view.podkop.constants as constants'; +'require view.podkop.main as main'; // Flag to track if this is the first error check let isInitialCheck = true; @@ -39,13 +39,13 @@ function showErrorNotification(error, isMultiple = false) { } // Helper function for command execution with prioritization -function safeExec(command, args, priority, callback, timeout = constants.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 = constants.COMMAND_SCHEDULING.P0_PRIORITY; + let schedulingDelay = main.COMMAND_SCHEDULING.P0_PRIORITY; // If priority is a string, try to get the corresponding delay value - if (typeof priority === 'string' && constants.COMMAND_SCHEDULING[priority] !== undefined) { - schedulingDelay = constants.COMMAND_SCHEDULING[priority]; + if (typeof priority === 'string' && main.COMMAND_SCHEDULING[priority] !== undefined) { + schedulingDelay = main.COMMAND_SCHEDULING[priority]; } const executeCommand = async () => { @@ -133,7 +133,7 @@ function startErrorPolling() { checkForCriticalErrors(); // Then set up periodic checks - errorPollTimer = setInterval(checkForCriticalErrors, constants.ERROR_POLL_INTERVAL); + errorPollTimer = setInterval(checkForCriticalErrors, main.ERROR_POLL_INTERVAL); } // Stop polling for errors @@ -149,4 +149,4 @@ return baseclass.extend({ stopErrorPolling, checkForCriticalErrors, safeExec -}); \ No newline at end of file +});