Compare commits

..

12 Commits
0.7.2 ... 0.7.5

Author SHA1 Message Date
Kirill Sobakin
8a29e176f2 Merge pull request #232 from itdoginfo/fix/change_json_outbound_validation
small pack of fixes
2025-10-26 16:07:47 +03:00
divocat
9653310208 fix: update locales && possible fix of incorrect outdated 2025-10-26 14:58:09 +02:00
divocat
3540610c78 fix: potential fix of structuredClone for old browsers 2025-10-26 14:52:08 +02:00
divocat
fb54d62a7f feat: actualize json outbound validation 2025-10-26 14:46:39 +02:00
Kirill Sobakin
288b8d4cc2 Merge pull request #230 from itdoginfo/feat/diagnostic-outbound-check
Add outbound check to diagnostic
2025-10-26 09:27:09 +03:00
divocat
e014396ae2 feat: extend selector checks displaying 2025-10-26 01:37:17 +03:00
divocat
694e4ca35a fix: remove extra console log 2025-10-26 01:10:33 +03:00
divocat
788c539e16 feat: add outbounds checks to diagnostics 2025-10-26 01:09:24 +03:00
Kirill Sobakin
743cba8936 Merge pull request #229 from itdoginfo/fix/show-config
Fix masked config
2025-10-25 17:38:45 +03:00
Andrey Petelin
d1d703764c fix: mask outbound_json block and DNS/domain_resolver addresses in podkop config output 2025-10-25 19:27:01 +05:00
Kirill Sobakin
2efd415305 Merge pull request #226 from itdoginfo/fix/excluded_ips
Routing Excluded IPs
2025-10-24 15:34:57 +03:00
Andrey Petelin
407b19b3ed fix: read routing_excluded_ips as non-boolean string with config_get instead of config_get_bool 2025-10-24 17:32:35 +05:00
16 changed files with 422 additions and 154 deletions

View File

@@ -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"
]
},
@@ -395,17 +397,11 @@
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:278"
]
},
{
"call": "Downloading all lists via main Proxy/VPN",
"key": "Downloading all lists via main Proxy/VPN",
"places": [
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:270"
]
},
{
"call": "Downloading all lists via specific Proxy/VPN",
"key": "Downloading all lists via specific Proxy/VPN",
"places": [
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:270",
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:279"
]
},
@@ -512,19 +508,20 @@
"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"
]
},
{
"call": "Fastest",
"key": "Fastest",
"places": [
"src/podkop/methods/custom/getDashboardSections.ts:117"
"src/podkop/methods/custom/getDashboardSections.ts:117",
"src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:58"
]
},
{
@@ -545,7 +542,7 @@
"call": "Global check",
"key": "Global check",
"places": [
"src/podkop/tabs/diagnostic/initController.ts:221"
"src/podkop/tabs/diagnostic/initController.ts:222"
]
},
{
@@ -609,7 +606,7 @@
"call": "Invalid JSON format",
"key": "Invalid JSON format",
"places": [
"src/validators/validateOutboundJson.ts:19"
"src/validators/validateOutboundJson.ts:9"
]
},
{
@@ -805,7 +802,7 @@
"call": "Latest",
"key": "Latest",
"places": [
"src/podkop/tabs/diagnostic/initController.ts:452"
"src/podkop/tabs/diagnostic/initController.ts:453"
]
},
{
@@ -878,6 +875,15 @@
"src/podkop/tabs/diagnostic/partials/renderCheckSection.ts:189"
]
},
{
"call": "Not responding",
"key": "Not responding",
"places": [
"src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:74",
"src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:80",
"src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:99"
]
},
{
"call": "Not running",
"key": "Not running",
@@ -885,7 +891,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"
]
},
{
@@ -909,18 +916,11 @@
"../luci-app-podkop/htdocs/luci-static/resources/view/podkop/section.js:64"
]
},
{
"call": "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields",
"key": "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields",
"places": [
"src/validators/validateOutboundJson.ts:11"
]
},
{
"call": "Outdated",
"key": "Outdated",
"places": [
"src/podkop/tabs/diagnostic/initController.ts:442"
"src/podkop/tabs/diagnostic/initController.ts:443"
]
},
{
@@ -962,10 +962,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 +1247,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 +1474,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"
]
},
{
@@ -1576,7 +1577,7 @@
"src/validators/validateDomain.ts:13",
"src/validators/validateDomain.ts:30",
"src/validators/validateIp.ts:8",
"src/validators/validateOutboundJson.ts:17",
"src/validators/validateOutboundJson.ts:7",
"src/validators/validatePath.ts:16",
"src/validators/validateShadowsocksUrl.ts:95",
"src/validators/validateSocksUrl.ts:80",
@@ -1598,7 +1599,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"
]
},

View File

@@ -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-26 12:56+0200\n"
"PO-Revision-Date: 2025-10-26 12:56+0200\n"
"Last-Translator: divocat <divocatt@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\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 ""
@@ -248,9 +250,6 @@ msgid "Download Lists via specific proxy section"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:270
msgid "Downloading all lists via main Proxy/VPN"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:279
msgid "Downloading all lists via specific Proxy/VPN"
msgstr ""
@@ -312,16 +311,17 @@ 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 ""
#: src/podkop/methods/custom/getDashboardSections.ts:117
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:58
msgid "Fastest"
msgstr ""
@@ -333,7 +333,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 ""
@@ -370,7 +370,7 @@ msgstr ""
msgid "Invalid IP address"
msgstr ""
#: src/validators/validateOutboundJson.ts:19
#: src/validators/validateOutboundJson.ts:9
msgid "Invalid JSON format"
msgstr ""
@@ -482,7 +482,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 +526,17 @@ msgstr ""
msgid "Not implement yet"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:74
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:80
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:99
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 ""
@@ -545,11 +552,7 @@ msgstr ""
msgid "Outbound Configuration"
msgstr ""
#: src/validators/validateOutboundJson.ts:11
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 +576,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 +741,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 +872,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 ""
@@ -932,7 +936,7 @@ msgstr ""
#: src/validators/validateDomain.ts:13
#: src/validators/validateDomain.ts:30
#: src/validators/validateIp.ts:8
#: src/validators/validateOutboundJson.ts:17
#: src/validators/validateOutboundJson.ts:7
#: src/validators/validatePath.ts:16
#: src/validators/validateShadowsocksUrl.ts:95
#: src/validators/validateSocksUrl.ts:80
@@ -948,7 +952,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 ""

View File

@@ -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-26 14:56+0200\n"
"PO-Revision-Date: 2025-10-26 14:56+0200\n"
"Last-Translator: divocat\n"
"Language-Team: none\n"
"Language: ru\n"
@@ -182,9 +182,6 @@ msgstr "Скачивать списки через Proxy/VPN"
msgid "Download Lists via specific proxy section"
msgstr "Скачивать списки через выбранную секцию"
msgid "Downloading all lists via main Proxy/VPN"
msgstr "Загрузка всех списков через основной прокси/VPN"
msgid "Downloading all lists via specific Proxy/VPN"
msgstr "Загрузка всех списков через указанный прокси/VPN"
@@ -386,6 +383,9 @@ msgstr "Другие правила маркировки не найдены"
msgid "Not implement yet"
msgstr "Ещё не реализовано"
msgid "Not responding"
msgstr "Не отвечает"
msgid "Not running"
msgstr "Не запущено"
@@ -398,9 +398,6 @@ msgstr "Конфигурация Outbound"
msgid "Outbound Configuration"
msgstr "Конфигурация исходящего соединения"
msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields"
msgstr "JSON должен содержать поля \"type\", \"server\" и \"server_port\""
msgid "Outdated"
msgstr "Устаревшая"

View File

@@ -4,6 +4,9 @@
'require uci';
'require ui';
if (typeof structuredClone !== 'function')
globalThis.structuredClone = (obj) => JSON.parse(JSON.stringify(obj));
export * from './validators';
export * from './helpers';
export * from './podkop';

View File

@@ -29,15 +29,15 @@ export const PodkopShellMethods = {
Podkop.AvailableClashAPIMethods.GET_PROXIES,
]),
getClashApiProxyLatency: async (tag: string) =>
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY,
tag,
]),
callBaseMethod<Podkop.GetClashApiProxyLatency>(
Podkop.AvailableMethods.CLASH_API,
[Podkop.AvailableClashAPIMethods.GET_PROXY_LATENCY, tag],
),
getClashApiGroupLatency: async (tag: string) =>
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY,
tag,
]),
callBaseMethod<Podkop.GetClashApiGroupLatency>(
Podkop.AvailableMethods.CLASH_API,
[Podkop.AvailableClashAPIMethods.GET_GROUP_LATENCY, tag],
),
setClashApiGroupProxy: async (group: string, proxy: string) =>
callBaseMethod<unknown>(Podkop.AvailableMethods.CLASH_API, [
Podkop.AvailableClashAPIMethods.SET_GROUP_PROXY,

View File

@@ -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,
},

View File

@@ -0,0 +1,131 @@
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,
);
const selectedOutbound = section.outbounds.find(
(item) => item.selected,
);
const isUrlTest = selectedOutbound?.type === 'URLTest';
const success = latencyGroup.success && !latencyGroup.data.message;
if (success) {
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: false,
latency: `[${selectedOutbound?.code ?? ''}] ${_('Not responding')}`,
};
}
return {
success: false,
latency: _('Not responding'),
};
}
const latencyProxy = await PodkopShellMethods.getClashApiProxyLatency(
section.code,
);
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<IDiagnosticsChecksItem>;
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');
}
}

View File

@@ -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,

View File

@@ -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();
@@ -414,9 +415,9 @@ function renderDiagnosticSystemInfoWidget() {
function getPodkopVersionRow(): IRenderSystemInfoRow {
const loading = diagnosticsSystemInfo.loading;
const unknown = diagnosticsSystemInfo.podkop_version === _('unknown');
const hasActualVersion = Boolean(
diagnosticsSystemInfo.podkop_latest_version,
);
const hasActualVersion =
Boolean(diagnosticsSystemInfo.podkop_latest_version) &&
diagnosticsSystemInfo.podkop_latest_version !== 'unknown';
const version = normalizeCompiledVersion(
diagnosticsSystemInfo.podkop_version,
);
@@ -518,6 +519,8 @@ async function runChecks() {
await runNftCheck();
await runSectionsCheck();
await runFakeIPCheck();
} catch (e) {
logger.error('[DIAGNOSTIC]', 'runChecks - e', e);

View File

@@ -196,4 +196,11 @@ export namespace Podkop {
openwrt_version: string;
device_model: string;
}
export interface GetClashApiProxyLatency {
delay: number;
message?: string;
}
export type GetClashApiGroupLatency = Record<string, number>;
}

View File

@@ -1,18 +1,8 @@
import { ValidationResult } from './types';
// TODO refactor current validation and add tests
export function validateOutboundJson(value: string): ValidationResult {
try {
const parsed = JSON.parse(value);
if (!parsed.type || !parsed.server || !parsed.server_port) {
return {
valid: false,
message: _(
'Outbound JSON must contain at least "type", "server" and "server_port" fields',
),
};
}
JSON.parse(value);
return { valid: true, message: _('Valid') };
} catch {

View File

@@ -323,15 +323,7 @@ function validateVlessUrl(url) {
// src/validators/validateOutboundJson.ts
function validateOutboundJson(value) {
try {
const parsed = JSON.parse(value);
if (!parsed.type || !parsed.server || !parsed.server_port) {
return {
valid: false,
message: _(
'Outbound JSON must contain at least "type", "server" and "server_port" fields'
)
};
}
JSON.parse(value);
return { valid: true, message: _("Valid") };
} catch {
return { valid: false, message: _("Invalid JSON format") };
@@ -563,14 +555,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 +996,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 +1071,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 +1115,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 +3698,105 @@ 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
);
const selectedOutbound = section.outbounds.find(
(item) => item.selected
);
const isUrlTest = selectedOutbound?.type === "URLTest";
const success3 = latencyGroup.success && !latencyGroup.data.message;
if (success3) {
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: false,
latency: `[${selectedOutbound?.code ?? ""}] ${_("Not responding")}`
};
}
return {
success: false,
latency: _("Not responding")
};
}
const latencyProxy = await PodkopShellMethods.getClashApiProxyLatency(
section.code
);
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();
@@ -4032,9 +4144,7 @@ function renderDiagnosticSystemInfoWidget() {
function getPodkopVersionRow() {
const loading = diagnosticsSystemInfo.loading;
const unknown = diagnosticsSystemInfo.podkop_version === _("unknown");
const hasActualVersion = Boolean(
diagnosticsSystemInfo.podkop_latest_version
);
const hasActualVersion = Boolean(diagnosticsSystemInfo.podkop_latest_version) && diagnosticsSystemInfo.podkop_latest_version !== "unknown";
const version = normalizeCompiledVersion(
diagnosticsSystemInfo.podkop_version
);
@@ -4118,6 +4228,7 @@ async function runChecks() {
await runDnsCheck();
await runSingBoxCheck();
await runNftCheck();
await runSectionsCheck();
await runFakeIPCheck();
} catch (e) {
logger.error("[DIAGNOSTIC]", "runChecks - e", e);
@@ -4624,6 +4735,10 @@ function insertIf(condition, elements) {
function insertIfObj(condition, object) {
return condition ? object : {};
}
// src/main.ts
if (typeof structuredClone !== "function")
globalThis.structuredClone = (obj) => JSON.parse(JSON.stringify(obj));
return baseclass.extend({
ALLOWED_WITH_RUSSIA_INSIDE,
BOOTSTRAP_DNS_SERVER_OPTIONS,

View File

@@ -267,7 +267,7 @@ function createSettingsContent(section) {
form.Flag,
"download_lists_via_proxy",
_("Download Lists via Proxy/VPN"),
_("Downloading all lists via main Proxy/VPN"),
_("Downloading all lists via specific Proxy/VPN"),
);
o.default = "0";
o.rmempty = false;

View File

@@ -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-26 14:56+0200\n"
"PO-Revision-Date: 2025-10-26 14:56+0200\n"
"Last-Translator: divocat\n"
"Language-Team: none\n"
"Language: ru\n"
@@ -182,9 +182,6 @@ msgstr "Скачивать списки через Proxy/VPN"
msgid "Download Lists via specific proxy section"
msgstr "Скачивать списки через выбранную секцию"
msgid "Downloading all lists via main Proxy/VPN"
msgstr "Загрузка всех списков через основной прокси/VPN"
msgid "Downloading all lists via specific Proxy/VPN"
msgstr "Загрузка всех списков через указанный прокси/VPN"
@@ -386,6 +383,9 @@ msgstr "Другие правила маркировки не найдены"
msgid "Not implement yet"
msgstr "Ещё не реализовано"
msgid "Not responding"
msgstr "Не отвечает"
msgid "Not running"
msgstr "Не запущено"
@@ -398,9 +398,6 @@ msgstr "Конфигурация Outbound"
msgid "Outbound Configuration"
msgstr "Конфигурация исходящего соединения"
msgid "Outbound JSON must contain at least \"type\", \"server\" and \"server_port\" fields"
msgstr "JSON должен содержать поля \"type\", \"server\" и \"server_port\""
msgid "Outdated"
msgstr "Устаревшая"

View File

@@ -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-26 12:56+0200\n"
"PO-Revision-Date: 2025-10-26 12:56+0200\n"
"Last-Translator: divocat <divocatt@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\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 ""
@@ -248,9 +250,6 @@ msgid "Download Lists via specific proxy section"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:270
msgid "Downloading all lists via main Proxy/VPN"
msgstr ""
#: ../luci-app-podkop/htdocs/luci-static/resources/view/podkop/settings.js:279
msgid "Downloading all lists via specific Proxy/VPN"
msgstr ""
@@ -312,16 +311,17 @@ 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 ""
#: src/podkop/methods/custom/getDashboardSections.ts:117
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:58
msgid "Fastest"
msgstr ""
@@ -333,7 +333,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 ""
@@ -370,7 +370,7 @@ msgstr ""
msgid "Invalid IP address"
msgstr ""
#: src/validators/validateOutboundJson.ts:19
#: src/validators/validateOutboundJson.ts:9
msgid "Invalid JSON format"
msgstr ""
@@ -482,7 +482,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 +526,17 @@ msgstr ""
msgid "Not implement yet"
msgstr ""
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:74
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:80
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:99
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 ""
@@ -545,11 +552,7 @@ msgstr ""
msgid "Outbound Configuration"
msgstr ""
#: src/validators/validateOutboundJson.ts:11
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 +576,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 +741,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 +872,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 ""
@@ -932,7 +936,7 @@ msgstr ""
#: src/validators/validateDomain.ts:13
#: src/validators/validateDomain.ts:30
#: src/validators/validateIp.ts:8
#: src/validators/validateOutboundJson.ts:17
#: src/validators/validateOutboundJson.ts:7
#: src/validators/validatePath.ts:16
#: src/validators/validateShadowsocksUrl.ts:95
#: src/validators/validateSocksUrl.ts:80
@@ -948,7 +952,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 ""

View File

@@ -767,7 +767,7 @@ sing_box_configure_route() {
configure_common_reject_route_rule
local routing_excluded_ips
config_get_bool routing_excluded_ips "settings" "routing_excluded_ips"
config_get routing_excluded_ips "settings" "routing_excluded_ips"
if [ -n "$routing_excluded_ips" ]; then
rule_tag="$(gen_id)"
config=$(sing_box_cm_add_route_rule "$config" "$rule_tag" "$SB_TPROXY_INBOUND_TAG" "$SB_DIRECT_OUTBOUND_TAG")
@@ -1684,16 +1684,10 @@ show_config() {
tmp_config=$(mktemp)
sed -e 's/\(option proxy_string\).*/\1 '\''MASKED'\''/g' \
-e 's/\(option outbound_json\).*/\1 '\''MASKED'\''/g' \
-e 's/\(option second_proxy_string\).*/\1 '\''MASKED'\''/g' \
-e 's/\(option second_outbound_json\).*/\1 '\''MASKED'\''/g' \
-e 's/\(vless:\/\/[^@]*@\)/vless:\/\/MASKED@/g' \
-e 's/\(ss:\/\/[^@]*@\)/ss:\/\/MASKED@/g' \
-e 's/\(pbk=[^&]*\)/pbk=MASKED/g' \
-e 's/\(sid=[^&]*\)/sid=MASKED/g' \
-e 's/\(option dns_server '\''[^'\'']*\.dns\.nextdns\.io'\''\)/option dns_server '\''MASKED.dns.nextdns.io'\''/g' \
-e "s|\(option dns_server 'dns\.nextdns\.io\)/[^']*|\1/MASKED|" \
-e '/option outbound_json/,/^}/c\ option outbound_json '\''MASKED'\''' \
-e 's/\(list urltest_proxy_links\).*/\1 '\''MASKED'\''/g' \
-e "s@\\(option dns_server '[^/]*\\)/[^']*'@\\1/MASKED'@g" \
-e "s@\\(option domain_resolver_dns_server '[^/]*\\)/[^']*'@\\1/MASKED'@g" \
"$PODKOP_CONFIG" > "$tmp_config"
cat "$tmp_config"