From 788c539e163c97cdf9b0ad444b40107542e66568 Mon Sep 17 00:00:00 2001 From: divocat Date: Sun, 26 Oct 2025 01:09:24 +0300 Subject: [PATCH 1/3] feat: add outbounds checks to diagnostics --- fe-app-podkop/locales/calls.json | 44 ++++--- fe-app-podkop/locales/podkop.pot | 41 +++--- fe-app-podkop/locales/podkop.ru.po | 7 +- .../src/podkop/methods/shell/index.ts | 16 +-- .../tabs/diagnostic/checks/contstants.ts | 8 +- .../diagnostic/checks/runSectionsCheck.ts | 111 ++++++++++++++++ .../tabs/diagnostic/diagnostic.store.ts | 16 +++ .../podkop/tabs/diagnostic/initController.ts | 3 + fe-app-podkop/src/podkop/types.ts | 7 + .../luci-static/resources/view/podkop/main.js | 124 ++++++++++++++++-- luci-app-podkop/po/ru/podkop.po | 7 +- luci-app-podkop/po/templates/podkop.pot | 41 +++--- 12 files changed, 355 insertions(+), 70 deletions(-) create mode 100644 fe-app-podkop/src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts diff --git a/fe-app-podkop/locales/calls.json b/fe-app-podkop/locales/calls.json index 847ad5c..466ceff 100644 --- a/fe-app-podkop/locales/calls.json +++ b/fe-app-podkop/locales/calls.json @@ -117,6 +117,7 @@ "places": [ "src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:27", "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:28", + "src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:27", "src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:25" ] }, @@ -127,6 +128,7 @@ "src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:15", "src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:15", "src/podkop/tabs/diagnostic/checks/runNftCheck.ts:13", + "src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:15", "src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:13" ] }, @@ -512,12 +514,12 @@ "call": "Failed to execute!", "key": "Failed to execute!", "places": [ - "src/podkop/tabs/diagnostic/initController.ts:226", - "src/podkop/tabs/diagnostic/initController.ts:230", - "src/podkop/tabs/diagnostic/initController.ts:260", - "src/podkop/tabs/diagnostic/initController.ts:264", - "src/podkop/tabs/diagnostic/initController.ts:298", - "src/podkop/tabs/diagnostic/initController.ts:302" + "src/podkop/tabs/diagnostic/initController.ts:227", + "src/podkop/tabs/diagnostic/initController.ts:231", + "src/podkop/tabs/diagnostic/initController.ts:261", + "src/podkop/tabs/diagnostic/initController.ts:265", + "src/podkop/tabs/diagnostic/initController.ts:299", + "src/podkop/tabs/diagnostic/initController.ts:303" ] }, { @@ -545,7 +547,7 @@ "call": "Global check", "key": "Global check", "places": [ - "src/podkop/tabs/diagnostic/initController.ts:221" + "src/podkop/tabs/diagnostic/initController.ts:222" ] }, { @@ -805,7 +807,7 @@ "call": "Latest", "key": "Latest", "places": [ - "src/podkop/tabs/diagnostic/initController.ts:452" + "src/podkop/tabs/diagnostic/initController.ts:453" ] }, { @@ -878,6 +880,14 @@ "src/podkop/tabs/diagnostic/partials/renderCheckSection.ts:189" ] }, + { + "call": "Not responding", + "key": "Not responding", + "places": [ + "src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:59", + "src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:79" + ] + }, { "call": "Not running", "key": "Not running", @@ -885,7 +895,8 @@ "src/podkop/tabs/diagnostic/diagnostic.store.ts:55", "src/podkop/tabs/diagnostic/diagnostic.store.ts:63", "src/podkop/tabs/diagnostic/diagnostic.store.ts:71", - "src/podkop/tabs/diagnostic/diagnostic.store.ts:79" + "src/podkop/tabs/diagnostic/diagnostic.store.ts:79", + "src/podkop/tabs/diagnostic/diagnostic.store.ts:87" ] }, { @@ -920,7 +931,7 @@ "call": "Outdated", "key": "Outdated", "places": [ - "src/podkop/tabs/diagnostic/initController.ts:442" + "src/podkop/tabs/diagnostic/initController.ts:443" ] }, { @@ -962,10 +973,11 @@ "call": "Pending", "key": "Pending", "places": [ - "src/podkop/tabs/diagnostic/diagnostic.store.ts:95", "src/podkop/tabs/diagnostic/diagnostic.store.ts:103", "src/podkop/tabs/diagnostic/diagnostic.store.ts:111", - "src/podkop/tabs/diagnostic/diagnostic.store.ts:119" + "src/podkop/tabs/diagnostic/diagnostic.store.ts:119", + "src/podkop/tabs/diagnostic/diagnostic.store.ts:127", + "src/podkop/tabs/diagnostic/diagnostic.store.ts:135" ] }, { @@ -1246,7 +1258,7 @@ "call": "Show sing-box config", "key": "Show sing-box config", "places": [ - "src/podkop/tabs/diagnostic/initController.ts:289", + "src/podkop/tabs/diagnostic/initController.ts:290", "src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:116" ] }, @@ -1473,13 +1485,13 @@ "call": "unknown", "key": "unknown", "places": [ - "src/podkop/tabs/diagnostic/initController.ts:37", "src/podkop/tabs/diagnostic/initController.ts:38", "src/podkop/tabs/diagnostic/initController.ts:39", "src/podkop/tabs/diagnostic/initController.ts:40", "src/podkop/tabs/diagnostic/initController.ts:41", "src/podkop/tabs/diagnostic/initController.ts:42", - "src/podkop/tabs/diagnostic/initController.ts:416" + "src/podkop/tabs/diagnostic/initController.ts:43", + "src/podkop/tabs/diagnostic/initController.ts:417" ] }, { @@ -1598,7 +1610,7 @@ "call": "View logs", "key": "View logs", "places": [ - "src/podkop/tabs/diagnostic/initController.ts:255", + "src/podkop/tabs/diagnostic/initController.ts:256", "src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:107" ] }, diff --git a/fe-app-podkop/locales/podkop.pot b/fe-app-podkop/locales/podkop.pot index 54e8965..b23bcca 100644 --- a/fe-app-podkop/locales/podkop.pot +++ b/fe-app-podkop/locales/podkop.pot @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PODKOP\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-10-23 17:43+0300\n" -"PO-Revision-Date: 2025-10-23 17:43+0300\n" +"POT-Creation-Date: 2025-10-25 22:08+0300\n" +"PO-Revision-Date: 2025-10-25 22:08+0300\n" "Last-Translator: divocat \n" "Language-Team: LANGUAGE \n" "Language: \n" @@ -82,6 +82,7 @@ msgstr "" #: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:27 #: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:28 +#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:27 #: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:25 msgid "Cannot receive checks result" msgstr "" @@ -89,6 +90,7 @@ msgstr "" #: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:15 #: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:15 #: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:13 +#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:15 #: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:13 msgid "Checking, please wait" msgstr "" @@ -312,12 +314,12 @@ msgstr "" msgid "Failed to copy!" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:226 -#: src/podkop/tabs/diagnostic/initController.ts:230 -#: src/podkop/tabs/diagnostic/initController.ts:260 -#: src/podkop/tabs/diagnostic/initController.ts:264 -#: src/podkop/tabs/diagnostic/initController.ts:298 -#: src/podkop/tabs/diagnostic/initController.ts:302 +#: src/podkop/tabs/diagnostic/initController.ts:227 +#: src/podkop/tabs/diagnostic/initController.ts:231 +#: src/podkop/tabs/diagnostic/initController.ts:261 +#: src/podkop/tabs/diagnostic/initController.ts:265 +#: src/podkop/tabs/diagnostic/initController.ts:299 +#: src/podkop/tabs/diagnostic/initController.ts:303 msgid "Failed to execute!" msgstr "" @@ -333,7 +335,7 @@ msgstr "" msgid "Get global check" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:221 +#: src/podkop/tabs/diagnostic/initController.ts:222 msgid "Global check" msgstr "" @@ -482,7 +484,7 @@ msgstr "" msgid "Issues detected" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:452 +#: src/podkop/tabs/diagnostic/initController.ts:453 msgid "Latest" msgstr "" @@ -526,10 +528,16 @@ msgstr "" msgid "Not implement yet" msgstr "" +#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:59 +#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:79 +msgid "Not responding" +msgstr "" + #: src/podkop/tabs/diagnostic/diagnostic.store.ts:55 #: src/podkop/tabs/diagnostic/diagnostic.store.ts:63 #: src/podkop/tabs/diagnostic/diagnostic.store.ts:71 #: src/podkop/tabs/diagnostic/diagnostic.store.ts:79 +#: src/podkop/tabs/diagnostic/diagnostic.store.ts:87 msgid "Not running" msgstr "" @@ -549,7 +557,7 @@ msgstr "" msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:442 +#: src/podkop/tabs/diagnostic/initController.ts:443 msgid "Outdated" msgstr "" @@ -573,10 +581,11 @@ msgstr "" msgid "Path must end with cache.db" msgstr "" -#: src/podkop/tabs/diagnostic/diagnostic.store.ts:95 #: src/podkop/tabs/diagnostic/diagnostic.store.ts:103 #: src/podkop/tabs/diagnostic/diagnostic.store.ts:111 #: src/podkop/tabs/diagnostic/diagnostic.store.ts:119 +#: src/podkop/tabs/diagnostic/diagnostic.store.ts:127 +#: src/podkop/tabs/diagnostic/diagnostic.store.ts:135 msgid "Pending" msgstr "" @@ -737,7 +746,7 @@ msgstr "" msgid "Settings" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:289 +#: src/podkop/tabs/diagnostic/initController.ts:290 #: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:116 msgid "Show sing-box config" msgstr "" @@ -868,13 +877,13 @@ msgstr "" msgid "UDP over TCP" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:37 #: src/podkop/tabs/diagnostic/initController.ts:38 #: src/podkop/tabs/diagnostic/initController.ts:39 #: src/podkop/tabs/diagnostic/initController.ts:40 #: src/podkop/tabs/diagnostic/initController.ts:41 #: src/podkop/tabs/diagnostic/initController.ts:42 -#: src/podkop/tabs/diagnostic/initController.ts:416 +#: src/podkop/tabs/diagnostic/initController.ts:43 +#: src/podkop/tabs/diagnostic/initController.ts:417 msgid "unknown" msgstr "" @@ -948,7 +957,7 @@ msgstr "" msgid "Validation errors:" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:255 +#: src/podkop/tabs/diagnostic/initController.ts:256 #: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:107 msgid "View logs" msgstr "" diff --git a/fe-app-podkop/locales/podkop.ru.po b/fe-app-podkop/locales/podkop.ru.po index c2caea2..3296fc8 100644 --- a/fe-app-podkop/locales/podkop.ru.po +++ b/fe-app-podkop/locales/podkop.ru.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PODKOP\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-10-23 20:43+0300\n" -"PO-Revision-Date: 2025-10-23 20:43+0300\n" +"POT-Creation-Date: 2025-10-25 01:08+0300\n" +"PO-Revision-Date: 2025-10-25 01:08+0300\n" "Last-Translator: divocat\n" "Language-Team: none\n" "Language: ru\n" @@ -386,6 +386,9 @@ msgstr "Другие правила маркировки не найдены" msgid "Not implement yet" msgstr "Ещё не реализовано" +msgid "Not responding" +msgstr "Не отвечает" + msgid "Not running" msgstr "Не запущено" diff --git a/fe-app-podkop/src/podkop/methods/shell/index.ts b/fe-app-podkop/src/podkop/methods/shell/index.ts index 1a6fe7c..e0d3475 100644 --- a/fe-app-podkop/src/podkop/methods/shell/index.ts +++ b/fe-app-podkop/src/podkop/methods/shell/index.ts @@ -29,15 +29,15 @@ export const PodkopShellMethods = { Podkop.AvailableClashAPIMethods.GET_PROXIES, ]), getClashApiProxyLatency: async (tag: string) => - callBaseMethod(Podkop.AvailableMethods.CLASH_API, [ - Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY, - tag, - ]), + callBaseMethod( + Podkop.AvailableMethods.CLASH_API, + [Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY, tag], + ), getClashApiGroupLatency: async (tag: string) => - callBaseMethod(Podkop.AvailableMethods.CLASH_API, [ - Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY, - tag, - ]), + callBaseMethod( + Podkop.AvailableMethods.CLASH_API, + [Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY, tag], + ), setClashApiGroupProxy: async (group: string, proxy: string) => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [ Podkop.AvailableClashAPIMethods.SET_GROUP_PROXY, diff --git a/fe-app-podkop/src/podkop/tabs/diagnostic/checks/contstants.ts b/fe-app-podkop/src/podkop/tabs/diagnostic/checks/contstants.ts index 326c40a..2911d89 100644 --- a/fe-app-podkop/src/podkop/tabs/diagnostic/checks/contstants.ts +++ b/fe-app-podkop/src/podkop/tabs/diagnostic/checks/contstants.ts @@ -5,6 +5,7 @@ export enum DIAGNOSTICS_CHECKS { SINGBOX = 'SINGBOX', NFT = 'NFT', FAKEIP = 'FAKEIP', + OUTBOUNDS = 'OUTBOUNDS', } export const DIAGNOSTICS_CHECKS_MAP: Record< @@ -26,8 +27,13 @@ export const DIAGNOSTICS_CHECKS_MAP: Record< title: getCheckTitle('Nftables'), code: DIAGNOSTICS_CHECKS.NFT, }, - [DIAGNOSTICS_CHECKS.FAKEIP]: { + [DIAGNOSTICS_CHECKS.OUTBOUNDS]: { order: 4, + title: getCheckTitle('Outbounds'), + code: DIAGNOSTICS_CHECKS.OUTBOUNDS, + }, + [DIAGNOSTICS_CHECKS.FAKEIP]: { + order: 5, title: getCheckTitle('FakeIP'), code: DIAGNOSTICS_CHECKS.FAKEIP, }, diff --git a/fe-app-podkop/src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts b/fe-app-podkop/src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts new file mode 100644 index 0000000..d46cb47 --- /dev/null +++ b/fe-app-podkop/src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts @@ -0,0 +1,111 @@ +import { DIAGNOSTICS_CHECKS_MAP } from './contstants'; +import { PodkopShellMethods } from '../../../methods'; +import { updateCheckStore } from './updateCheckStore'; +import { getMeta } from '../helpers/getMeta'; +import { getDashboardSections } from '../../../methods/custom/getDashboardSections'; +import { IDiagnosticsChecksItem } from '../../../services'; + +export async function runSectionsCheck() { + const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS; + + updateCheckStore({ + order, + code, + title, + description: _('Checking, please wait'), + state: 'loading', + items: [], + }); + + const sections = await getDashboardSections(); + + if (!sections.success) { + updateCheckStore({ + order, + code, + title, + description: _('Cannot receive checks result'), + state: 'error', + items: [], + }); + + throw new Error('Sections checks failed'); + } + + const items = (await Promise.all( + sections.data.map(async (section) => { + async function getLatency() { + if (section.withTagSelect) { + const latencyGroup = await PodkopShellMethods.getClashApiGroupLatency( + section.code, + ); + console.log('Latency group', latencyGroup); + + const success = latencyGroup.success && !latencyGroup.data.message; + + if (success) { + const latency = Object.values(latencyGroup.data) + .map((item) => (item ? `${item}ms` : 'n/a')) + .join(' / '); + + return { + success: true, + latency, + }; + } + + return { + success: true, + latency: _('Not responding'), + }; + } + + const latencyProxy = await PodkopShellMethods.getClashApiProxyLatency( + section.code, + ); + console.log('Latency proxy', latencyProxy); + + const success = latencyProxy.success && !latencyProxy.data.message; + + if (success) { + return { + success: true, + latency: `${latencyProxy.data.delay} ms`, + }; + } + + return { + success: false, + latency: _('Not responding'), + }; + } + + const { latency, success } = await getLatency(); + + return { + state: success ? 'success' : 'error', + key: section.displayName, + value: latency, + }; + }), + )) as Array; + + const allGood = items.every((item) => item.state === 'success'); + + const atLeastOneGood = items.some((item) => item.state === 'success'); + + const { state, description } = getMeta({ atLeastOneGood, allGood }); + + updateCheckStore({ + order, + code, + title, + description, + state, + items, + }); + + if (!atLeastOneGood) { + throw new Error('Sections checks failed'); + } +} diff --git a/fe-app-podkop/src/podkop/tabs/diagnostic/diagnostic.store.ts b/fe-app-podkop/src/podkop/tabs/diagnostic/diagnostic.store.ts index 8da0b3e..c6ea562 100644 --- a/fe-app-podkop/src/podkop/tabs/diagnostic/diagnostic.store.ts +++ b/fe-app-podkop/src/podkop/tabs/diagnostic/diagnostic.store.ts @@ -72,6 +72,14 @@ export const initialDiagnosticStore: Pick< items: [], state: 'skipped', }, + { + code: DIAGNOSTICS_CHECKS.OUTBOUNDS, + title: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.title, + order: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.order, + description: _('Not running'), + items: [], + state: 'skipped', + }, { code: DIAGNOSTICS_CHECKS.FAKEIP, title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title, @@ -112,6 +120,14 @@ export const loadingDiagnosticsChecksStore: Pick< items: [], state: 'skipped', }, + { + code: DIAGNOSTICS_CHECKS.OUTBOUNDS, + title: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.title, + order: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.order, + description: _('Pending'), + items: [], + state: 'skipped', + }, { code: DIAGNOSTICS_CHECKS.FAKEIP, title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title, diff --git a/fe-app-podkop/src/podkop/tabs/diagnostic/initController.ts b/fe-app-podkop/src/podkop/tabs/diagnostic/initController.ts index 06d4cae..a815e22 100644 --- a/fe-app-podkop/src/podkop/tabs/diagnostic/initController.ts +++ b/fe-app-podkop/src/podkop/tabs/diagnostic/initController.ts @@ -19,6 +19,7 @@ import { renderModal } from '../../../partials'; import { PODKOP_LUCI_APP_VERSION } from '../../../constants'; import { showToast } from '../../../helpers/showToast'; import { renderWikiDisclaimer } from './partials/renderWikiDisclaimer'; +import { runSectionsCheck } from './checks/runSectionsCheck'; async function fetchSystemInfo() { const systemInfo = await PodkopShellMethods.getSystemInfo(); @@ -518,6 +519,8 @@ async function runChecks() { await runNftCheck(); + await runSectionsCheck(); + await runFakeIPCheck(); } catch (e) { logger.error('[DIAGNOSTIC]', 'runChecks - e', e); diff --git a/fe-app-podkop/src/podkop/types.ts b/fe-app-podkop/src/podkop/types.ts index 9b8aefd..25e65d7 100644 --- a/fe-app-podkop/src/podkop/types.ts +++ b/fe-app-podkop/src/podkop/types.ts @@ -196,4 +196,11 @@ export namespace Podkop { openwrt_version: string; device_model: string; } + + export interface GetClashApiProxyLatency { + delay: number; + message?: string; + } + + export type GetClashApiGroupLatency = Record; } 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 bcf89bc..ab1bc25 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 @@ -563,14 +563,14 @@ var PodkopShellMethods = { getClashApiProxies: async () => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [ Podkop.AvailableClashAPIMethods.GET_PROXIES ]), - getClashApiProxyLatency: async (tag) => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [ - Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY, - tag - ]), - getClashApiGroupLatency: async (tag) => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [ - Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY, - tag - ]), + getClashApiProxyLatency: async (tag) => callBaseMethod( + Podkop.AvailableMethods.CLASH_API, + [Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY, tag] + ), + getClashApiGroupLatency: async (tag) => callBaseMethod( + Podkop.AvailableMethods.CLASH_API, + [Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY, tag] + ), setClashApiGroupProxy: async (group, proxy) => callBaseMethod(Podkop.AvailableMethods.CLASH_API, [ Podkop.AvailableClashAPIMethods.SET_GROUP_PROXY, group, @@ -1004,8 +1004,13 @@ var DIAGNOSTICS_CHECKS_MAP = { title: getCheckTitle("Nftables"), code: "NFT" /* NFT */ }, - ["FAKEIP" /* FAKEIP */]: { + ["OUTBOUNDS" /* OUTBOUNDS */]: { order: 4, + title: getCheckTitle("Outbounds"), + code: "OUTBOUNDS" /* OUTBOUNDS */ + }, + ["FAKEIP" /* FAKEIP */]: { + order: 5, title: getCheckTitle("FakeIP"), code: "FAKEIP" /* FAKEIP */ } @@ -1074,6 +1079,14 @@ var initialDiagnosticStore = { items: [], state: "skipped" }, + { + code: "OUTBOUNDS" /* OUTBOUNDS */, + title: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.title, + order: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.order, + description: _("Not running"), + items: [], + state: "skipped" + }, { code: "FAKEIP" /* FAKEIP */, title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title, @@ -1110,6 +1123,14 @@ var loadingDiagnosticsChecksStore = { items: [], state: "skipped" }, + { + code: "OUTBOUNDS" /* OUTBOUNDS */, + title: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.title, + order: DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS.order, + description: _("Pending"), + items: [], + state: "skipped" + }, { code: "FAKEIP" /* FAKEIP */, title: DIAGNOSTICS_CHECKS_MAP.FAKEIP.title, @@ -3685,6 +3706,90 @@ function renderWikiDisclaimer(kind) { ]); } +// src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts +async function runSectionsCheck() { + const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.OUTBOUNDS; + updateCheckStore({ + order, + code, + title, + description: _("Checking, please wait"), + state: "loading", + items: [] + }); + const sections = await getDashboardSections(); + if (!sections.success) { + updateCheckStore({ + order, + code, + title, + description: _("Cannot receive checks result"), + state: "error", + items: [] + }); + throw new Error("Sections checks failed"); + } + const items = await Promise.all( + sections.data.map(async (section) => { + async function getLatency() { + if (section.withTagSelect) { + const latencyGroup = await PodkopShellMethods.getClashApiGroupLatency( + section.code + ); + console.log("Latency group", latencyGroup); + const success3 = latencyGroup.success && !latencyGroup.data.message; + if (success3) { + const latency2 = Object.values(latencyGroup.data).map((item) => item ? `${item}ms` : "n/a").join(" / "); + return { + success: true, + latency: latency2 + }; + } + return { + success: true, + latency: _("Not responding") + }; + } + const latencyProxy = await PodkopShellMethods.getClashApiProxyLatency( + section.code + ); + console.log("Latency proxy", latencyProxy); + const success2 = latencyProxy.success && !latencyProxy.data.message; + if (success2) { + return { + success: true, + latency: `${latencyProxy.data.delay} ms` + }; + } + return { + success: false, + latency: _("Not responding") + }; + } + const { latency, success } = await getLatency(); + return { + state: success ? "success" : "error", + key: section.displayName, + value: latency + }; + }) + ); + const allGood = items.every((item) => item.state === "success"); + const atLeastOneGood = items.some((item) => item.state === "success"); + const { state, description } = getMeta({ atLeastOneGood, allGood }); + updateCheckStore({ + order, + code, + title, + description, + state, + items + }); + if (!atLeastOneGood) { + throw new Error("Sections checks failed"); + } +} + // src/podkop/tabs/diagnostic/initController.ts async function fetchSystemInfo() { const systemInfo = await PodkopShellMethods.getSystemInfo(); @@ -4118,6 +4223,7 @@ async function runChecks() { await runDnsCheck(); await runSingBoxCheck(); await runNftCheck(); + await runSectionsCheck(); await runFakeIPCheck(); } catch (e) { logger.error("[DIAGNOSTIC]", "runChecks - e", e); diff --git a/luci-app-podkop/po/ru/podkop.po b/luci-app-podkop/po/ru/podkop.po index c2caea2..3296fc8 100644 --- a/luci-app-podkop/po/ru/podkop.po +++ b/luci-app-podkop/po/ru/podkop.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PODKOP\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-10-23 20:43+0300\n" -"PO-Revision-Date: 2025-10-23 20:43+0300\n" +"POT-Creation-Date: 2025-10-25 01:08+0300\n" +"PO-Revision-Date: 2025-10-25 01:08+0300\n" "Last-Translator: divocat\n" "Language-Team: none\n" "Language: ru\n" @@ -386,6 +386,9 @@ msgstr "Другие правила маркировки не найдены" msgid "Not implement yet" msgstr "Ещё не реализовано" +msgid "Not responding" +msgstr "Не отвечает" + msgid "Not running" msgstr "Не запущено" diff --git a/luci-app-podkop/po/templates/podkop.pot b/luci-app-podkop/po/templates/podkop.pot index 54e8965..b23bcca 100644 --- a/luci-app-podkop/po/templates/podkop.pot +++ b/luci-app-podkop/po/templates/podkop.pot @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PODKOP\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-10-23 17:43+0300\n" -"PO-Revision-Date: 2025-10-23 17:43+0300\n" +"POT-Creation-Date: 2025-10-25 22:08+0300\n" +"PO-Revision-Date: 2025-10-25 22:08+0300\n" "Last-Translator: divocat \n" "Language-Team: LANGUAGE \n" "Language: \n" @@ -82,6 +82,7 @@ msgstr "" #: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:27 #: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:28 +#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:27 #: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:25 msgid "Cannot receive checks result" msgstr "" @@ -89,6 +90,7 @@ msgstr "" #: src/podkop/tabs/diagnostic/checks/runDnsCheck.ts:15 #: src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts:15 #: src/podkop/tabs/diagnostic/checks/runNftCheck.ts:13 +#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:15 #: src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts:13 msgid "Checking, please wait" msgstr "" @@ -312,12 +314,12 @@ msgstr "" msgid "Failed to copy!" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:226 -#: src/podkop/tabs/diagnostic/initController.ts:230 -#: src/podkop/tabs/diagnostic/initController.ts:260 -#: src/podkop/tabs/diagnostic/initController.ts:264 -#: src/podkop/tabs/diagnostic/initController.ts:298 -#: src/podkop/tabs/diagnostic/initController.ts:302 +#: src/podkop/tabs/diagnostic/initController.ts:227 +#: src/podkop/tabs/diagnostic/initController.ts:231 +#: src/podkop/tabs/diagnostic/initController.ts:261 +#: src/podkop/tabs/diagnostic/initController.ts:265 +#: src/podkop/tabs/diagnostic/initController.ts:299 +#: src/podkop/tabs/diagnostic/initController.ts:303 msgid "Failed to execute!" msgstr "" @@ -333,7 +335,7 @@ msgstr "" msgid "Get global check" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:221 +#: src/podkop/tabs/diagnostic/initController.ts:222 msgid "Global check" msgstr "" @@ -482,7 +484,7 @@ msgstr "" msgid "Issues detected" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:452 +#: src/podkop/tabs/diagnostic/initController.ts:453 msgid "Latest" msgstr "" @@ -526,10 +528,16 @@ msgstr "" msgid "Not implement yet" msgstr "" +#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:59 +#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:79 +msgid "Not responding" +msgstr "" + #: src/podkop/tabs/diagnostic/diagnostic.store.ts:55 #: src/podkop/tabs/diagnostic/diagnostic.store.ts:63 #: src/podkop/tabs/diagnostic/diagnostic.store.ts:71 #: src/podkop/tabs/diagnostic/diagnostic.store.ts:79 +#: src/podkop/tabs/diagnostic/diagnostic.store.ts:87 msgid "Not running" msgstr "" @@ -549,7 +557,7 @@ msgstr "" msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:442 +#: src/podkop/tabs/diagnostic/initController.ts:443 msgid "Outdated" msgstr "" @@ -573,10 +581,11 @@ msgstr "" msgid "Path must end with cache.db" msgstr "" -#: src/podkop/tabs/diagnostic/diagnostic.store.ts:95 #: src/podkop/tabs/diagnostic/diagnostic.store.ts:103 #: src/podkop/tabs/diagnostic/diagnostic.store.ts:111 #: src/podkop/tabs/diagnostic/diagnostic.store.ts:119 +#: src/podkop/tabs/diagnostic/diagnostic.store.ts:127 +#: src/podkop/tabs/diagnostic/diagnostic.store.ts:135 msgid "Pending" msgstr "" @@ -737,7 +746,7 @@ msgstr "" msgid "Settings" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:289 +#: src/podkop/tabs/diagnostic/initController.ts:290 #: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:116 msgid "Show sing-box config" msgstr "" @@ -868,13 +877,13 @@ msgstr "" msgid "UDP over TCP" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:37 #: src/podkop/tabs/diagnostic/initController.ts:38 #: src/podkop/tabs/diagnostic/initController.ts:39 #: src/podkop/tabs/diagnostic/initController.ts:40 #: src/podkop/tabs/diagnostic/initController.ts:41 #: src/podkop/tabs/diagnostic/initController.ts:42 -#: src/podkop/tabs/diagnostic/initController.ts:416 +#: src/podkop/tabs/diagnostic/initController.ts:43 +#: src/podkop/tabs/diagnostic/initController.ts:417 msgid "unknown" msgstr "" @@ -948,7 +957,7 @@ msgstr "" msgid "Validation errors:" msgstr "" -#: src/podkop/tabs/diagnostic/initController.ts:255 +#: src/podkop/tabs/diagnostic/initController.ts:256 #: src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:107 msgid "View logs" msgstr "" From 694e4ca35a31e2cca06d180b6c3af0a18768bae1 Mon Sep 17 00:00:00 2001 From: divocat Date: Sun, 26 Oct 2025 01:10:33 +0300 Subject: [PATCH 2/3] fix: remove extra console log --- .../src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts | 2 -- .../htdocs/luci-static/resources/view/podkop/main.js | 2 -- 2 files changed, 4 deletions(-) diff --git a/fe-app-podkop/src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts b/fe-app-podkop/src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts index d46cb47..9a2edf4 100644 --- a/fe-app-podkop/src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts +++ b/fe-app-podkop/src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts @@ -39,7 +39,6 @@ export async function runSectionsCheck() { const latencyGroup = await PodkopShellMethods.getClashApiGroupLatency( section.code, ); - console.log('Latency group', latencyGroup); const success = latencyGroup.success && !latencyGroup.data.message; @@ -63,7 +62,6 @@ export async function runSectionsCheck() { const latencyProxy = await PodkopShellMethods.getClashApiProxyLatency( section.code, ); - console.log('Latency proxy', latencyProxy); const success = latencyProxy.success && !latencyProxy.data.message; 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 ab1bc25..7147f63 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 @@ -3736,7 +3736,6 @@ async function runSectionsCheck() { const latencyGroup = await PodkopShellMethods.getClashApiGroupLatency( section.code ); - console.log("Latency group", latencyGroup); const success3 = latencyGroup.success && !latencyGroup.data.message; if (success3) { const latency2 = Object.values(latencyGroup.data).map((item) => item ? `${item}ms` : "n/a").join(" / "); @@ -3753,7 +3752,6 @@ async function runSectionsCheck() { const latencyProxy = await PodkopShellMethods.getClashApiProxyLatency( section.code ); - console.log("Latency proxy", latencyProxy); const success2 = latencyProxy.success && !latencyProxy.data.message; if (success2) { return { From e014396ae292ba5f807ee3134d4975d927b3de6b Mon Sep 17 00:00:00 2001 From: divocat Date: Sun, 26 Oct 2025 01:37:17 +0300 Subject: [PATCH 3/3] feat: extend selector checks displaying --- .../diagnostic/checks/runSectionsCheck.ts | 34 +++++++++++++++---- .../luci-static/resources/view/podkop/main.js | 25 +++++++++++--- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/fe-app-podkop/src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts b/fe-app-podkop/src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts index 9a2edf4..bd8e2bc 100644 --- a/fe-app-podkop/src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts +++ b/fe-app-podkop/src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts @@ -40,21 +40,43 @@ export async function runSectionsCheck() { section.code, ); + const selectedOutbound = section.outbounds.find( + (item) => item.selected, + ); + const isUrlTest = selectedOutbound?.type === 'URLTest'; + const success = latencyGroup.success && !latencyGroup.data.message; if (success) { - const latency = Object.values(latencyGroup.data) - .map((item) => (item ? `${item}ms` : 'n/a')) - .join(' / '); + if (isUrlTest) { + const latency = Object.values(latencyGroup.data) + .map((item) => (item ? `${item}ms` : 'n/a')) + .join(' / '); + + return { + success: true, + latency: `[${_('Fastest')}] ${latency}`, + }; + } + + const selectedProxyDelay = + latencyGroup.data?.[selectedOutbound?.code ?? '']; + + if (selectedProxyDelay) { + return { + success: true, + latency: `[${selectedOutbound?.code ?? ''}] ${selectedProxyDelay}ms`, + }; + } return { - success: true, - latency, + success: false, + latency: `[${selectedOutbound?.code ?? ''}] ${_('Not responding')}`, }; } return { - success: true, + success: false, latency: _('Not responding'), }; } 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 7147f63..37ccc9a 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 @@ -3736,16 +3736,33 @@ async function runSectionsCheck() { const latencyGroup = await PodkopShellMethods.getClashApiGroupLatency( section.code ); + const selectedOutbound = section.outbounds.find( + (item) => item.selected + ); + const isUrlTest = selectedOutbound?.type === "URLTest"; const success3 = latencyGroup.success && !latencyGroup.data.message; if (success3) { - const latency2 = Object.values(latencyGroup.data).map((item) => item ? `${item}ms` : "n/a").join(" / "); + if (isUrlTest) { + const latency2 = Object.values(latencyGroup.data).map((item) => item ? `${item}ms` : "n/a").join(" / "); + return { + success: true, + latency: `[${_("Fastest")}] ${latency2}` + }; + } + const selectedProxyDelay = latencyGroup.data?.[selectedOutbound?.code ?? ""]; + if (selectedProxyDelay) { + return { + success: true, + latency: `[${selectedOutbound?.code ?? ""}] ${selectedProxyDelay}ms` + }; + } return { - success: true, - latency: latency2 + success: false, + latency: `[${selectedOutbound?.code ?? ""}] ${_("Not responding")}` }; } return { - success: true, + success: false, latency: _("Not responding") }; }