Add subscription support adapted from podkop-evolution
Adapt subscription handling from yandexru45/podkop-evolution to the Podkop Plus rule-based proxy architecture.
This commit is contained in:
+179
-116
@@ -35,7 +35,7 @@
|
||||
"call": "A latency-tested group of proxy URLs for this section",
|
||||
"key": "A latency-tested group of proxy URLs for this section",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1731"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1879"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -49,15 +49,15 @@
|
||||
"call": "A manual group of proxy URLs for this section",
|
||||
"key": "A manual group of proxy URLs for this section",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1713"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1861"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Action",
|
||||
"key": "Action",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1551",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1583"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1631",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1663"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -71,21 +71,21 @@
|
||||
"call": "Add a section",
|
||||
"key": "Add a section",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:395"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:401"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Add URLs or local paths to .lst lists",
|
||||
"key": "Add URLs or local paths to .lst lists",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2130"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2297"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Add URLs or local paths to .srs / .json lists",
|
||||
"key": "Add URLs or local paths to .srs / .json lists",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2115"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2282"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -106,7 +106,7 @@
|
||||
"call": "An error occurred while saving the form:",
|
||||
"key": "An error occurred while saving the form:",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:142"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:148"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -114,21 +114,21 @@
|
||||
"key": "Applicable for SOCKS and Shadowsocks links",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:170",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1826"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1993"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "At least one valid domain must be specified.",
|
||||
"key": "At least one valid domain must be specified.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:836"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:916"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "At least one valid IP or subnet must be specified.",
|
||||
"key": "At least one valid IP or subnet must be specified.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:847"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:927"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -149,7 +149,7 @@
|
||||
"call": "Backend validation failed: %s",
|
||||
"key": "Backend validation failed: %s",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:938"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1018"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -191,7 +191,7 @@
|
||||
"call": "Built-in rule sets",
|
||||
"key": "Built-in rule sets",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2020"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2187"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -281,7 +281,7 @@
|
||||
"call": "Conditions",
|
||||
"key": "Conditions",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1539"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1619"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -295,21 +295,21 @@
|
||||
"call": "Configuration for Podkop Plus service",
|
||||
"key": "Configuration for Podkop Plus service",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:381"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:387"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Connection",
|
||||
"key": "Connection",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1668"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1749"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Connection Type",
|
||||
"key": "Connection Type",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1651"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1731"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -317,7 +317,7 @@
|
||||
"key": "Connection URL",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:19",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1654"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1734"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -338,7 +338,7 @@
|
||||
"call": "Dashboard",
|
||||
"key": "Dashboard",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:426"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:432"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -373,7 +373,7 @@
|
||||
"call": "Diagnostics",
|
||||
"key": "Diagnostics",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:414"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:420"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -409,7 +409,7 @@
|
||||
"call": "Dismiss",
|
||||
"key": "Dismiss",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:149"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:155"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -424,7 +424,7 @@
|
||||
"key": "DNS over HTTPS (DoH)",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:227",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1891",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2058",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/settings.js:21"
|
||||
]
|
||||
},
|
||||
@@ -433,7 +433,7 @@
|
||||
"key": "DNS over TLS (DoT)",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:228",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1892",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2059",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/settings.js:22"
|
||||
]
|
||||
},
|
||||
@@ -441,7 +441,7 @@
|
||||
"call": "DNS protocol",
|
||||
"key": "DNS protocol",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1889"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2056"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -469,7 +469,7 @@
|
||||
"call": "DNS server",
|
||||
"key": "DNS server",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1907"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2074"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -498,28 +498,28 @@
|
||||
"call": "Domain and IP Lists",
|
||||
"key": "Domain and IP Lists",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2129"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2296"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Domain keyword",
|
||||
"key": "Domain keyword",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1990"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2157"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Domain regex",
|
||||
"key": "Domain regex",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1997"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2164"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Domains",
|
||||
"key": "Domains",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1962"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2129"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -583,23 +583,23 @@
|
||||
"call": "Drag rows to change priority. The rule at the top is checked first.",
|
||||
"key": "Drag rows to change priority. The rule at the top is checked first.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:389"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:395"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Duplicate value",
|
||||
"key": "Duplicate value",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:369",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:384",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:404"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:449",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:464",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:484"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Edit",
|
||||
"key": "Edit",
|
||||
"call": "Edit rule action",
|
||||
"key": "Edit rule action",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:366"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:59"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -608,7 +608,7 @@
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:8",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/ruleset.js:10",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1541"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1621"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -622,7 +622,7 @@
|
||||
"call": "Enable a dedicated DNS resolver when this section uses an interface",
|
||||
"key": "Enable a dedicated DNS resolver when this section uses an interface",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1878"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2045"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -636,7 +636,7 @@
|
||||
"call": "Enable Mixed Proxy",
|
||||
"key": "Enable Mixed Proxy",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1929"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2096"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -665,46 +665,49 @@
|
||||
"key": "Enter a complete sing-box outbound object",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:52",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1691"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1772"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Enter the subscription URL to fetch proxy configurations from your provider",
|
||||
"key": "Enter the subscription URL to fetch proxy configurations from your provider",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1794"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Every 3 minutes",
|
||||
"key": "Every 3 minutes",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:103",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1752"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:103"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Every 30 seconds",
|
||||
"key": "Every 30 seconds",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:101",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1750"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:101"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Every 5 minutes",
|
||||
"key": "Every 5 minutes",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:104",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1753"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:104"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Every minute",
|
||||
"key": "Every minute",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:102",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1751"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:102"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Exact full domain",
|
||||
"key": "Exact full domain",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1976"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2143"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -732,14 +735,14 @@
|
||||
"call": "Expose this section as a local HTTP+SOCKS proxy",
|
||||
"key": "Expose this section as a local HTTP+SOCKS proxy",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1930"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2097"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "External nfqws config files bypass Podkop Plus queue management and explicit validation.",
|
||||
"key": "External nfqws config files bypass Podkop Plus queue management and explicit validation.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:999"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1079"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -766,6 +769,8 @@
|
||||
"key": "Fastest",
|
||||
"places": [
|
||||
"src/podkop/methods/custom/getDashboardSections.ts:188",
|
||||
"src/podkop/methods/custom/getDashboardSections.ts:220",
|
||||
"src/podkop/methods/custom/getDashboardSections.ts:257",
|
||||
"src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:59"
|
||||
]
|
||||
},
|
||||
@@ -790,6 +795,20 @@
|
||||
"src/podkop/tabs/diagnostic/initController.ts:251"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Group subscription proxies by country",
|
||||
"key": "Group subscription proxies by country",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1848"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Group subscription proxies by the country flag at the beginning of the outbound tag",
|
||||
"key": "Group subscription proxies by the country flag at the beginning of the outbound tag",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1849"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "How often this remote rule set should be refreshed",
|
||||
"key": "How often this remote rule set should be refreshed",
|
||||
@@ -801,7 +820,7 @@
|
||||
"call": "How to configure the proxy connection for this section",
|
||||
"key": "How to configure the proxy connection for this section",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1652"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1732"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -817,8 +836,8 @@
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:23",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:179",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1658",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1837"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1739",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2004"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -980,7 +999,7 @@
|
||||
"call": "Invalid port number. Must be between 1 and 65535",
|
||||
"key": "Invalid port number. Must be between 1 and 65535",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1957",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2124",
|
||||
"src/validators/validateShadowsocksUrl.ts:85"
|
||||
]
|
||||
},
|
||||
@@ -1164,7 +1183,7 @@
|
||||
"call": "IPs",
|
||||
"key": "IPs",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1969"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2136"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1194,7 +1213,7 @@
|
||||
"call": "List must be a direct .lst URL or a local .lst path",
|
||||
"key": "List must be a direct .lst URL or a local .lst path",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1504"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1584"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1236,42 +1255,42 @@
|
||||
"call": "Match destination IPs or subnets",
|
||||
"key": "Match destination IPs or subnets",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1970"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2137"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Match domains containing a substring",
|
||||
"key": "Match domains containing a substring",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1991"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2158"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Match domains including all subdomains",
|
||||
"key": "Match domains including all subdomains",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1963"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2130"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Match domains using a regular expression",
|
||||
"key": "Match domains using a regular expression",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1998"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2165"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Match only one exact full domain name",
|
||||
"key": "Match only one exact full domain name",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1977"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2144"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Match source IPs or subnets",
|
||||
"key": "Match source IPs or subnets",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2005"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2172"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1279,7 +1298,7 @@
|
||||
"key": "Maximum response time delta in milliseconds",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:114",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1764"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1929"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1293,7 +1312,7 @@
|
||||
"call": "Mixed Proxy Port",
|
||||
"key": "Mixed Proxy Port",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1941"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2108"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1308,7 +1327,7 @@
|
||||
"key": "Must be a number in the range of 50 - 1000",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:136",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1786"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1952"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1329,14 +1348,14 @@
|
||||
"call": "NFQWS Strategy",
|
||||
"key": "NFQWS Strategy",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1617"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1697"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "NFQWS strategy cannot be empty",
|
||||
"key": "NFQWS strategy cannot be empty",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1129"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1209"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1409,6 +1428,13 @@
|
||||
"src/helpers/withTimeout.ts:7"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Option \"%s\" contains an invalid input value.",
|
||||
"key": "Option \"%s\" contains an invalid input value.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:385"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Optional node used to download this remote rule set",
|
||||
"key": "Optional node used to download this remote rule set",
|
||||
@@ -1420,7 +1446,7 @@
|
||||
"call": "Optional values must be attached with '=' here; a separate token would be ignored by nfqws.",
|
||||
"key": "Optional values must be attached with '=' here; a separate token would be ignored by nfqws.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1207"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1287"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1429,8 +1455,8 @@
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:22",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:51",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1657",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1690"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1738",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1771"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1498,14 +1524,14 @@
|
||||
"call": "Podkop Plus manages the nfqws process lifecycle itself, so daemon mode is not allowed here.",
|
||||
"key": "Podkop Plus manages the nfqws process lifecycle itself, so daemon mode is not allowed here.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1017"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1097"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Podkop Plus Settings",
|
||||
"key": "Podkop Plus Settings",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:380"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:386"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1540,14 +1566,14 @@
|
||||
"call": "Port cannot be empty",
|
||||
"key": "Port cannot be empty",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1949"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2116"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Port for the local mixed proxy of this section",
|
||||
"key": "Port for the local mixed proxy of this section",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1942"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2109"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1575,7 +1601,7 @@
|
||||
"call": "Regional options cannot be used together",
|
||||
"key": "Regional options cannot be used together",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2059"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2226"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1596,7 +1622,7 @@
|
||||
"call": "Resolver for interface outbound",
|
||||
"key": "Resolver for interface outbound",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1877"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2044"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1610,14 +1636,14 @@
|
||||
"call": "Resource selection by hostname inside nfqws is not supported here; sing-box selects resources before NFQUEUE.",
|
||||
"key": "Resource selection by hostname inside nfqws is not supported here; sing-box selects resources before NFQUEUE.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1002"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1082"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Resource selection by IP or CIDR inside nfqws is not supported here; sing-box selects resources before NFQUEUE.",
|
||||
"key": "Resource selection by IP or CIDR inside nfqws is not supported here; sing-box selects resources before NFQUEUE.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1005"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1085"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1638,7 +1664,7 @@
|
||||
"call": "Rule set must be a direct .srs / .json URL or a local .srs / .json path",
|
||||
"key": "Rule set must be a direct .srs / .json URL or a local .srs / .json path",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1496"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1576"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1652,7 +1678,7 @@
|
||||
"call": "Rule sets",
|
||||
"key": "Rule sets",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2114"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2281"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1708,14 +1734,14 @@
|
||||
"call": "Russia inside restrictions",
|
||||
"key": "Russia inside restrictions",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2078"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2245"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Save error",
|
||||
"key": "Save error",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:141"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:147"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1729,28 +1755,28 @@
|
||||
"call": "Section",
|
||||
"key": "Section",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:394"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:400"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Section name",
|
||||
"key": "Section name",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1570"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1650"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Sections",
|
||||
"key": "Sections",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:388"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:394"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Select a predefined list for routing",
|
||||
"key": "Select a predefined list for routing",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2021"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2188"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1813,7 +1839,7 @@
|
||||
"call": "Selector connections",
|
||||
"key": "Selector connections",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1712"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1860"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1827,7 +1853,7 @@
|
||||
"call": "Service list",
|
||||
"key": "Service list",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2024"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2191"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1841,8 +1867,8 @@
|
||||
"call": "Settings",
|
||||
"key": "Settings",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:402",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1538"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:408",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1618"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1920,7 +1946,7 @@
|
||||
"call": "Source IPs",
|
||||
"key": "Source IPs",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2004"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2171"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1972,6 +1998,34 @@
|
||||
"src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts:59"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Subscription",
|
||||
"key": "Subscription",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1737"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Subscription update interval",
|
||||
"key": "Subscription update interval",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1813"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Subscription URL",
|
||||
"key": "Subscription URL",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1793"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Subscription URL cannot be empty",
|
||||
"key": "Subscription URL cannot be empty",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:395"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Successfully copied!",
|
||||
"key": "Successfully copied!",
|
||||
@@ -2011,7 +2065,7 @@
|
||||
"call": "The desync fwmark is managed by Podkop Plus for loop prevention and must not be overridden here.",
|
||||
"key": "The desync fwmark is managed by Podkop Plus for loop prevention and must not be overridden here.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1014"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1094"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2025,7 +2079,7 @@
|
||||
"call": "The NFQUEUE number is assigned by Podkop Plus for each rule and must not be overridden here.",
|
||||
"key": "The NFQUEUE number is assigned by Podkop Plus for each rule and must not be overridden here.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1011"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1091"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2039,28 +2093,28 @@
|
||||
"call": "This field must start a working nfqws strategy; --dry-run exits immediately and is not allowed here.",
|
||||
"key": "This field must start a working nfqws strategy; --dry-run exits immediately and is not allowed here.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1020"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1100"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "This field must start a working nfqws strategy; --version exits immediately and is not allowed here.",
|
||||
"key": "This field must start a working nfqws strategy; --version exits immediately and is not allowed here.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1023"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1103"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "This flag does not accept a value.",
|
||||
"key": "This flag does not accept a value.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1192"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1272"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "This option requires a value.",
|
||||
"key": "This option requires a value.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1223"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1303"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2124,14 +2178,14 @@
|
||||
"key": "UDP over TCP",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:169",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1825"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1992"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Unable to validate the NFQWS strategy through the backend parser.",
|
||||
"key": "Unable to validate the NFQWS strategy through the backend parser.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:934"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1014"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2145,7 +2199,7 @@
|
||||
"call": "Unexpected standalone token. Use explicit flags such as --name or --name=value.",
|
||||
"key": "Unexpected standalone token. Use explicit flags such as --name or --name=value.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1172"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1252"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2180,7 +2234,7 @@
|
||||
"call": "Unknown NFQWS flag.",
|
||||
"key": "Unknown NFQWS flag.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1183"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1263"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2216,14 +2270,14 @@
|
||||
"call": "URLTest connections",
|
||||
"key": "URLTest connections",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1730"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1878"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "URLTest interval",
|
||||
"key": "URLTest interval",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1748"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1896"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2244,7 +2298,7 @@
|
||||
"call": "URLTest tolerance",
|
||||
"key": "URLTest tolerance",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1763"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1928"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2259,7 +2313,7 @@
|
||||
"key": "URLTest URL",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:139",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1793"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1959"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2273,13 +2327,14 @@
|
||||
"call": "Use a network interface as the outbound for this section",
|
||||
"key": "Use a network interface as the outbound for this section",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1838"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2005"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Use sing-box duration format like 1d, 12h or 30m",
|
||||
"key": "Use sing-box duration format like 1d, 12h or 30m",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:374",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/settings.js:312"
|
||||
]
|
||||
},
|
||||
@@ -2287,9 +2342,17 @@
|
||||
"call": "Use sing-box duration format. Leave empty to disable automatic updates.",
|
||||
"key": "Use sing-box duration format. Leave empty to disable automatic updates.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1814",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/settings.js:283"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Use sing-box duration format. Leave empty to disable periodic URLTest checks.",
|
||||
"key": "Use sing-box duration format. Leave empty to disable periodic URLTest checks.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1897"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Valid",
|
||||
"key": "Valid",
|
||||
@@ -2314,9 +2377,9 @@
|
||||
"call": "Validation errors:",
|
||||
"key": "Validation errors:",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:376",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:396",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:400"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:456",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:476",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:480"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2331,7 +2394,7 @@
|
||||
"call": "Visible name of this section",
|
||||
"key": "Visible name of this section",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1571"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1651"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2339,28 +2402,28 @@
|
||||
"key": "vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:32",
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1669"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1750"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Warning: %s cannot be used together with %s. Previous selections have been removed.",
|
||||
"key": "Warning: %s cannot be used together with %s. Previous selections have been removed.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2061"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2228"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection.",
|
||||
"key": "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2080"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2247"
|
||||
]
|
||||
},
|
||||
{
|
||||
"call": "What Podkop Plus should do when this section matches",
|
||||
"key": "What Podkop Plus should do when this section matches",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1584"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1664"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2389,7 +2452,7 @@
|
||||
"call": "Zapret hostlist templates are not supported here because Podkop Plus does not expand them for per-rule NFQWS strategies.",
|
||||
"key": "Zapret hostlist templates are not supported here because Podkop Plus does not expand them for per-rule NFQWS strategies.",
|
||||
"places": [
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1008"
|
||||
"../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1088"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PODKOP PLUS package.
|
||||
# ushan0v <142658494+ushan0v@users.noreply.github.com>, 2026.
|
||||
# Podkop Plus <noreply@podkop.plus>, 2026.
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PODKOP PLUS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-01 20:07+0300\n"
|
||||
"PO-Revision-Date: 2026-05-01 20:07+0300\n"
|
||||
"Last-Translator: ushan0v <142658494+ushan0v@users.noreply.github.com>\n"
|
||||
"POT-Creation-Date: 2026-05-07 09:30+0300\n"
|
||||
"PO-Revision-Date: 2026-05-07 09:30+0300\n"
|
||||
"Last-Translator: Podkop Plus <noreply@podkop.plus>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -36,7 +36,7 @@ msgstr ""
|
||||
msgid "A latency-tested group of proxy URLs for this node"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1731
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1879
|
||||
msgid "A latency-tested group of proxy URLs for this section"
|
||||
msgstr ""
|
||||
|
||||
@@ -44,12 +44,12 @@ msgstr ""
|
||||
msgid "A manual group of proxy URLs for this node"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1713
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1861
|
||||
msgid "A manual group of proxy URLs for this section"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1551
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1583
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1631
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1663
|
||||
msgid "Action"
|
||||
msgstr ""
|
||||
|
||||
@@ -57,15 +57,15 @@ msgstr ""
|
||||
msgid "Active Connections"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:395
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:401
|
||||
msgid "Add a section"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2130
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2297
|
||||
msgid "Add URLs or local paths to .lst lists"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2115
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2282
|
||||
msgid "Add URLs or local paths to .srs / .json lists"
|
||||
msgstr ""
|
||||
|
||||
@@ -77,20 +77,20 @@ msgstr ""
|
||||
msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:142
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:148
|
||||
msgid "An error occurred while saving the form:"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:170
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1826
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1993
|
||||
msgid "Applicable for SOCKS and Shadowsocks links"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:836
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:916
|
||||
msgid "At least one valid domain must be specified."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:847
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:927
|
||||
msgid "At least one valid IP or subnet must be specified."
|
||||
msgstr ""
|
||||
|
||||
@@ -102,7 +102,7 @@ msgstr ""
|
||||
msgid "Available actions"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:938
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1018
|
||||
msgid "Backend validation failed: %s"
|
||||
msgstr ""
|
||||
|
||||
@@ -126,7 +126,7 @@ msgstr ""
|
||||
msgid "Browser is using FakeIP correctly"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2020
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2187
|
||||
msgid "Built-in rule sets"
|
||||
msgstr ""
|
||||
|
||||
@@ -183,7 +183,7 @@ msgstr ""
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1539
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1619
|
||||
msgid "Conditions"
|
||||
msgstr ""
|
||||
|
||||
@@ -191,20 +191,20 @@ msgstr ""
|
||||
msgid "Config File Path"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:381
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:387
|
||||
msgid "Configuration for Podkop Plus service"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1668
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1749
|
||||
msgid "Connection"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1651
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1731
|
||||
msgid "Connection Type"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:19
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1654
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1734
|
||||
msgid "Connection URL"
|
||||
msgstr ""
|
||||
|
||||
@@ -216,7 +216,7 @@ msgstr ""
|
||||
msgid "Currently unavailable"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:426
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:432
|
||||
msgid "Dashboard"
|
||||
msgstr ""
|
||||
|
||||
@@ -236,7 +236,7 @@ msgstr ""
|
||||
msgid "DHCP has DNS server"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:414
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:420
|
||||
msgid "Diagnostics"
|
||||
msgstr ""
|
||||
|
||||
@@ -257,7 +257,7 @@ msgstr ""
|
||||
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:149
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:155
|
||||
msgid "Dismiss"
|
||||
msgstr ""
|
||||
|
||||
@@ -266,18 +266,18 @@ msgid "DNS on router"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:227
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1891
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2058
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/settings.js:21
|
||||
msgid "DNS over HTTPS (DoH)"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:228
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1892
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2059
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/settings.js:22
|
||||
msgid "DNS over TLS (DoT)"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1889
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2056
|
||||
msgid "DNS protocol"
|
||||
msgstr ""
|
||||
|
||||
@@ -293,7 +293,7 @@ msgstr ""
|
||||
msgid "DNS Rewrite TTL"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1907
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2074
|
||||
msgid "DNS server"
|
||||
msgstr ""
|
||||
|
||||
@@ -310,19 +310,19 @@ msgstr ""
|
||||
msgid "Do not panic, everything can be fixed, just..."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2129
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2296
|
||||
msgid "Domain and IP Lists"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1990
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2157
|
||||
msgid "Domain keyword"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1997
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2164
|
||||
msgid "Domain regex"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1962
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2129
|
||||
msgid "Domains"
|
||||
msgstr ""
|
||||
|
||||
@@ -359,24 +359,23 @@ msgstr ""
|
||||
msgid "Downloading all lists via specific Proxy/VPN"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:389
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:395
|
||||
msgid "Drag rows to change priority. The rule at the top is checked first."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:369
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:384
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:404
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:449
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:464
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:484
|
||||
msgid "Duplicate value"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:366
|
||||
msgctxt "Rule row action"
|
||||
msgid "Edit"
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:59
|
||||
msgid "Edit rule action"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:8
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/ruleset.js:10
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1541
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1621
|
||||
msgid "Enable"
|
||||
msgstr ""
|
||||
|
||||
@@ -384,7 +383,7 @@ msgstr ""
|
||||
msgid "Enable a dedicated DNS resolver when this node uses an interface"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1878
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2045
|
||||
msgid "Enable a dedicated DNS resolver when this section uses an interface"
|
||||
msgstr ""
|
||||
|
||||
@@ -392,7 +391,7 @@ msgstr ""
|
||||
msgid "Enable autostart"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1929
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2096
|
||||
msgid "Enable Mixed Proxy"
|
||||
msgstr ""
|
||||
|
||||
@@ -409,31 +408,31 @@ msgid "Enable YACD WAN Access"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:52
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1691
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1772
|
||||
msgid "Enter a complete sing-box outbound object"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1794
|
||||
msgid "Enter the subscription URL to fetch proxy configurations from your provider"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:103
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1752
|
||||
msgid "Every 3 minutes"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:101
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1750
|
||||
msgid "Every 30 seconds"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:104
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1753
|
||||
msgid "Every 5 minutes"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:102
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1751
|
||||
msgid "Every minute"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1976
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2143
|
||||
msgid "Exact full domain"
|
||||
msgstr ""
|
||||
|
||||
@@ -449,11 +448,11 @@ msgstr ""
|
||||
msgid "Expecting: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1930
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2097
|
||||
msgid "Expose this section as a local HTTP+SOCKS proxy"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:999
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1079
|
||||
msgid "External nfqws config files bypass Podkop Plus queue management and explicit validation."
|
||||
msgstr ""
|
||||
|
||||
@@ -471,6 +470,8 @@ msgid "Failed to execute!"
|
||||
msgstr ""
|
||||
|
||||
#: src/podkop/methods/custom/getDashboardSections.ts:188
|
||||
#: src/podkop/methods/custom/getDashboardSections.ts:220
|
||||
#: src/podkop/methods/custom/getDashboardSections.ts:257
|
||||
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:59
|
||||
msgid "Fastest"
|
||||
msgstr ""
|
||||
@@ -487,11 +488,19 @@ msgstr ""
|
||||
msgid "Global check"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1848
|
||||
msgid "Group subscription proxies by country"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1849
|
||||
msgid "Group subscription proxies by the country flag at the beginning of the outbound tag"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/ruleset.js:87
|
||||
msgid "How often this remote rule set should be refreshed"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1652
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1732
|
||||
msgid "How to configure the proxy connection for this section"
|
||||
msgstr ""
|
||||
|
||||
@@ -501,8 +510,8 @@ msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:23
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:179
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1658
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1837
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1739
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2004
|
||||
msgid "Interface"
|
||||
msgstr ""
|
||||
|
||||
@@ -595,7 +604,7 @@ msgstr ""
|
||||
msgid "Invalid path format. Path must start with \"/\" and contain valid characters"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1957
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2124
|
||||
#: src/validators/validateShadowsocksUrl.ts:85
|
||||
msgid "Invalid port number. Must be between 1 and 65535"
|
||||
msgstr ""
|
||||
@@ -701,7 +710,7 @@ msgstr ""
|
||||
msgid "IP address 0.0.0.0 is not allowed"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1969
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2136
|
||||
msgid "IPs"
|
||||
msgstr ""
|
||||
|
||||
@@ -719,7 +728,7 @@ msgstr ""
|
||||
msgid "Latest"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1504
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1584
|
||||
msgid "List must be a direct .lst URL or a local .lst path"
|
||||
msgstr ""
|
||||
|
||||
@@ -743,32 +752,32 @@ msgstr ""
|
||||
msgid "Main DNS"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1970
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2137
|
||||
msgid "Match destination IPs or subnets"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1991
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2158
|
||||
msgid "Match domains containing a substring"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1963
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2130
|
||||
msgid "Match domains including all subdomains"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1998
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2165
|
||||
msgid "Match domains using a regular expression"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1977
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2144
|
||||
msgid "Match only one exact full domain name"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2005
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2172
|
||||
msgid "Match source IPs or subnets"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:114
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1764
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1929
|
||||
msgid "Maximum response time delta in milliseconds"
|
||||
msgstr ""
|
||||
|
||||
@@ -776,7 +785,7 @@ msgstr ""
|
||||
msgid "Memory Usage"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1941
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2108
|
||||
msgid "Mixed Proxy Port"
|
||||
msgstr ""
|
||||
|
||||
@@ -785,7 +794,7 @@ msgid "Monitored Interfaces"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:136
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1786
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1952
|
||||
msgid "Must be a number in the range of 50 - 1000"
|
||||
msgstr ""
|
||||
|
||||
@@ -797,11 +806,11 @@ msgstr ""
|
||||
msgid "NFQUEUE range overlaps with another rule"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1617
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1697
|
||||
msgid "NFQWS Strategy"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1129
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1209
|
||||
msgid "NFQWS strategy cannot be empty"
|
||||
msgstr ""
|
||||
|
||||
@@ -848,18 +857,22 @@ msgstr ""
|
||||
msgid "Operation timed out"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:385
|
||||
msgid "Option \"%s\" contains an invalid input value."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/ruleset.js:64
|
||||
msgid "Optional node used to download this remote rule set"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1207
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1287
|
||||
msgid "Optional values must be attached with '=' here; a separate token would be ignored by nfqws."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:22
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:51
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1657
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1690
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1738
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1771
|
||||
msgid "Outbound JSON"
|
||||
msgstr ""
|
||||
|
||||
@@ -900,11 +913,11 @@ msgstr ""
|
||||
msgid "Pending"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1017
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1097
|
||||
msgid "Podkop Plus manages the nfqws process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:380
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:386
|
||||
msgid "Podkop Plus Settings"
|
||||
msgstr ""
|
||||
|
||||
@@ -924,11 +937,11 @@ msgstr ""
|
||||
msgid "Podkop-managed nfqws runtime is ready"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1949
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2116
|
||||
msgid "Port cannot be empty"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1942
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2109
|
||||
msgid "Port for the local mixed proxy of this section"
|
||||
msgstr ""
|
||||
|
||||
@@ -944,7 +957,7 @@ msgstr ""
|
||||
msgid "Proxy traffic is routed via FakeIP"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2059
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2226
|
||||
msgid "Regional options cannot be used together"
|
||||
msgstr ""
|
||||
|
||||
@@ -956,7 +969,7 @@ msgstr ""
|
||||
msgid "Remote URL to a sing-box rule set"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1877
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2044
|
||||
msgid "Resolver for interface outbound"
|
||||
msgstr ""
|
||||
|
||||
@@ -964,11 +977,11 @@ msgstr ""
|
||||
msgid "Resolver For Interface Outbound"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1002
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1082
|
||||
msgid "Resource selection by hostname inside nfqws is not supported here; sing-box selects resources before NFQUEUE."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1005
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1085
|
||||
msgid "Resource selection by IP or CIDR inside nfqws is not supported here; sing-box selects resources before NFQUEUE."
|
||||
msgstr ""
|
||||
|
||||
@@ -980,7 +993,7 @@ msgstr ""
|
||||
msgid "Routing Excluded IPs"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1496
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1576
|
||||
msgid "Rule set must be a direct .srs / .json URL or a local .srs / .json path"
|
||||
msgstr ""
|
||||
|
||||
@@ -988,7 +1001,7 @@ msgstr ""
|
||||
msgid "Rule set URL"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2114
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2281
|
||||
msgid "Rule sets"
|
||||
msgstr ""
|
||||
|
||||
@@ -1020,11 +1033,11 @@ msgstr ""
|
||||
msgid "Run Diagnostic"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2078
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2245
|
||||
msgid "Russia inside restrictions"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:141
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:147
|
||||
msgid "Save error"
|
||||
msgstr ""
|
||||
|
||||
@@ -1032,19 +1045,19 @@ msgstr ""
|
||||
msgid "Secret key for authenticating remote access to YACD when WAN access is enabled."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:394
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:400
|
||||
msgid "Section"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1570
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1650
|
||||
msgid "Section name"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:388
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:394
|
||||
msgid "Sections"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2021
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2188
|
||||
msgid "Select a predefined list for routing"
|
||||
msgstr ""
|
||||
|
||||
@@ -1080,7 +1093,7 @@ msgstr ""
|
||||
msgid "Select the WAN interfaces to be monitored"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1712
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1860
|
||||
msgid "Selector connections"
|
||||
msgstr ""
|
||||
|
||||
@@ -1088,7 +1101,7 @@ msgstr ""
|
||||
msgid "Selector Links"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2024
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2191
|
||||
msgid "Service list"
|
||||
msgstr ""
|
||||
|
||||
@@ -1096,8 +1109,8 @@ msgstr ""
|
||||
msgid "Services info"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:402
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1538
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:408
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1618
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
@@ -1142,7 +1155,7 @@ msgstr ""
|
||||
msgid "Source file"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2004
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2171
|
||||
msgid "Source IPs"
|
||||
msgstr ""
|
||||
|
||||
@@ -1174,6 +1187,22 @@ msgstr ""
|
||||
msgid "Stop Podkop Plus"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1737
|
||||
msgid "Subscription"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1813
|
||||
msgid "Subscription update interval"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1793
|
||||
msgid "Subscription URL"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:395
|
||||
msgid "Subscription URL cannot be empty"
|
||||
msgstr ""
|
||||
|
||||
#: src/helpers/copyToClipboard.ts:10
|
||||
msgid "Successfully copied!"
|
||||
msgstr ""
|
||||
@@ -1194,7 +1223,7 @@ msgstr ""
|
||||
msgid "Test latency"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1014
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1094
|
||||
msgid "The desync fwmark is managed by Podkop Plus for loop prevention and must not be overridden here."
|
||||
msgstr ""
|
||||
|
||||
@@ -1202,7 +1231,7 @@ msgstr ""
|
||||
msgid "The DNS server used to look up the IP address of an upstream DNS server"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1011
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1091
|
||||
msgid "The NFQUEUE number is assigned by Podkop Plus for each rule and must not be overridden here."
|
||||
msgstr ""
|
||||
|
||||
@@ -1210,19 +1239,19 @@ msgstr ""
|
||||
msgid "There are rules using Zapret"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1020
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1100
|
||||
msgid "This field must start a working nfqws strategy; --dry-run exits immediately and is not allowed here."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1023
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1103
|
||||
msgid "This field must start a working nfqws strategy; --version exits immediately and is not allowed here."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1192
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1272
|
||||
msgid "This flag does not accept a value."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1223
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1303
|
||||
msgid "This option requires a value."
|
||||
msgstr ""
|
||||
|
||||
@@ -1259,11 +1288,11 @@ msgid "UDP (Unprotected DNS)"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:169
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1825
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1992
|
||||
msgid "UDP over TCP"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:934
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1014
|
||||
msgid "Unable to validate the NFQWS strategy through the backend parser."
|
||||
msgstr ""
|
||||
|
||||
@@ -1271,7 +1300,7 @@ msgstr ""
|
||||
msgid "Unexpected Podkop-managed nfqws runtime is running"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1172
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1252
|
||||
msgid "Unexpected standalone token. Use explicit flags such as --name or --name=value."
|
||||
msgstr ""
|
||||
|
||||
@@ -1294,7 +1323,7 @@ msgstr ""
|
||||
msgid "Unknown error"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1183
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1263
|
||||
msgid "Unknown NFQWS flag."
|
||||
msgstr ""
|
||||
|
||||
@@ -1315,11 +1344,11 @@ msgstr ""
|
||||
msgid "URL must use one of the following protocols:"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1730
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1878
|
||||
msgid "URLTest connections"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1748
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1896
|
||||
msgid "URLTest interval"
|
||||
msgstr ""
|
||||
|
||||
@@ -1331,7 +1360,7 @@ msgstr ""
|
||||
msgid "URLTest Links"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1763
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1928
|
||||
msgid "URLTest tolerance"
|
||||
msgstr ""
|
||||
|
||||
@@ -1340,7 +1369,7 @@ msgid "URLTest Tolerance"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:139
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1793
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1959
|
||||
msgid "URLTest URL"
|
||||
msgstr ""
|
||||
|
||||
@@ -1348,18 +1377,24 @@ msgstr ""
|
||||
msgid "Use a network interface as the outbound for this node"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1838
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2005
|
||||
msgid "Use a network interface as the outbound for this section"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:374
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/settings.js:312
|
||||
msgid "Use sing-box duration format like 1d, 12h or 30m"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1814
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/settings.js:283
|
||||
msgid "Use sing-box duration format. Leave empty to disable automatic updates."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1897
|
||||
msgid "Use sing-box duration format. Leave empty to disable periodic URLTest checks."
|
||||
msgstr ""
|
||||
|
||||
#: src/validators/validateDns.ts:14
|
||||
#: src/validators/validateDns.ts:18
|
||||
#: src/validators/validateDomain.ts:13
|
||||
@@ -1377,9 +1412,9 @@ msgstr ""
|
||||
msgid "Valid"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:376
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:396
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:400
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:456
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:476
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:480
|
||||
msgid "Validation errors:"
|
||||
msgstr ""
|
||||
|
||||
@@ -1388,24 +1423,24 @@ msgstr ""
|
||||
msgid "View logs"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1571
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1651
|
||||
msgid "Visible name of this section"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:32
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1669
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1750
|
||||
msgid "vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2061
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2228
|
||||
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2080
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2247
|
||||
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1584
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1664
|
||||
msgid "What Podkop Plus should do when this section matches"
|
||||
msgstr ""
|
||||
|
||||
@@ -1422,7 +1457,7 @@ msgstr ""
|
||||
msgid "Zapret (provider not available)"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1008
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1088
|
||||
msgid "Zapret hostlist templates are not supported here because Podkop Plus does not expand them for per-rule NFQWS strategies."
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# RU translations for PODKOP PLUS package.
|
||||
# Copyright (C) 2026 THE PODKOP PLUS COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PODKOP PLUS package.
|
||||
# ushan0v, 2026.
|
||||
# Automatically generated, 2026.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PODKOP PLUS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-01 23:07+0300\n"
|
||||
"PO-Revision-Date: 2026-05-01 23:07+0300\n"
|
||||
"Last-Translator: ushan0v\n"
|
||||
"POT-Creation-Date: 2026-05-07 12:30+0300\n"
|
||||
"PO-Revision-Date: 2026-05-07 12:30+0300\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -260,8 +260,7 @@ msgstr "Перетаскивайте строки, чтобы изменить
|
||||
msgid "Duplicate value"
|
||||
msgstr "Дублирующееся значение"
|
||||
|
||||
msgctxt "Rule row action"
|
||||
msgid "Edit"
|
||||
msgid "Edit rule action"
|
||||
msgstr "Изменить"
|
||||
|
||||
msgid "Enable"
|
||||
@@ -291,6 +290,9 @@ msgstr "Включить доступ YACD WAN"
|
||||
msgid "Enter a complete sing-box outbound object"
|
||||
msgstr "Введите полный объект outbound sing-box"
|
||||
|
||||
msgid "Enter the subscription URL to fetch proxy configurations from your provider"
|
||||
msgstr "Введите URL подписки для получения конфигураций прокси от провайдера"
|
||||
|
||||
msgid "Every 3 minutes"
|
||||
msgstr "Каждые 3 минуты"
|
||||
|
||||
@@ -339,6 +341,12 @@ msgstr "Получить глобальную проверку"
|
||||
msgid "Global check"
|
||||
msgstr "Глобальная проверка"
|
||||
|
||||
msgid "Group subscription proxies by country"
|
||||
msgstr "Группировать прокси подписки по странам"
|
||||
|
||||
msgid "Group subscription proxies by the country flag at the beginning of the outbound tag"
|
||||
msgstr "Группирует прокси подписки по флагу страны в начале тега outbound"
|
||||
|
||||
msgid "How often this remote rule set should be refreshed"
|
||||
msgstr "Как часто обновлять этот удалённый набор правил"
|
||||
|
||||
@@ -597,6 +605,9 @@ msgstr "Открыть страницу проекта"
|
||||
msgid "Operation timed out"
|
||||
msgstr "Время ожидания истекло"
|
||||
|
||||
msgid "Option \"%s\" contains an invalid input value."
|
||||
msgstr ""
|
||||
|
||||
msgid "Optional node used to download this remote rule set"
|
||||
msgstr "Необязательный узел, через который скачивается этот удалённый набор правил"
|
||||
|
||||
@@ -834,6 +845,18 @@ msgstr "Запустить Podkop Plus"
|
||||
msgid "Stop Podkop Plus"
|
||||
msgstr "Остановить Podkop Plus"
|
||||
|
||||
msgid "Subscription"
|
||||
msgstr "Подписка"
|
||||
|
||||
msgid "Subscription update interval"
|
||||
msgstr "Интервал обновления подписки"
|
||||
|
||||
msgid "Subscription URL"
|
||||
msgstr "URL подписки"
|
||||
|
||||
msgid "Subscription URL cannot be empty"
|
||||
msgstr "URL подписки не может быть пустым"
|
||||
|
||||
msgid "Successfully copied!"
|
||||
msgstr "Успешно скопировано!"
|
||||
|
||||
@@ -966,6 +989,9 @@ msgstr "Используйте формат длительности sing-box,
|
||||
msgid "Use sing-box duration format. Leave empty to disable automatic updates."
|
||||
msgstr "Используйте формат длительности sing-box. Оставьте поле пустым, чтобы отключить автоматическое обновление."
|
||||
|
||||
msgid "Use sing-box duration format. Leave empty to disable periodic URLTest checks."
|
||||
msgstr "Используйте формат длительности sing-box. Оставьте поле пустым, чтобы отключить периодические проверки URLTest."
|
||||
|
||||
msgid "Valid"
|
||||
msgstr "Валидно"
|
||||
|
||||
|
||||
@@ -195,6 +195,83 @@ export async function getDashboardSections(): Promise<IGetDashboardSectionsRespo
|
||||
};
|
||||
}
|
||||
|
||||
if (proxyConfigType === 'subscription') {
|
||||
const selector = proxies.find(
|
||||
(proxy) => proxy.code === `${section['.name']}-out`,
|
||||
);
|
||||
const fallbackUrltest = proxies.find(
|
||||
(proxy) => proxy.code === `${section['.name']}-urltest-out`,
|
||||
);
|
||||
|
||||
const selectorOutbounds = (selector?.value?.all ?? []).flatMap(
|
||||
(code) => {
|
||||
const item = proxies.find((proxy) => proxy.code === code);
|
||||
if (!item) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const isDefaultFastest =
|
||||
item.code === `${section['.name']}-urltest-out`;
|
||||
|
||||
return [
|
||||
{
|
||||
code: item.code,
|
||||
displayName: isDefaultFastest
|
||||
? _('Fastest')
|
||||
: item?.value?.name || '',
|
||||
latency: item?.value?.history?.[0]?.delay || 0,
|
||||
type: item?.value?.type || '',
|
||||
selected: selector?.value?.now === item.code,
|
||||
},
|
||||
];
|
||||
},
|
||||
);
|
||||
|
||||
const outbounds = [
|
||||
...selectorOutbounds.filter(
|
||||
(item) => item.type?.toLowerCase() === 'urltest',
|
||||
),
|
||||
...selectorOutbounds.filter(
|
||||
(item) => item.type?.toLowerCase() !== 'urltest',
|
||||
),
|
||||
];
|
||||
|
||||
if (outbounds.length === 0 && fallbackUrltest) {
|
||||
const fallbackOutbounds = (fallbackUrltest?.value?.all ?? [])
|
||||
.map((code) => proxies.find((item) => item.code === code))
|
||||
.map((item) => ({
|
||||
code: item?.code || '',
|
||||
displayName: item?.value?.name || '',
|
||||
latency: item?.value?.history?.[0]?.delay || 0,
|
||||
type: item?.value?.type || '',
|
||||
selected: selector?.value?.now === item?.code,
|
||||
}));
|
||||
|
||||
return {
|
||||
withTagSelect: true,
|
||||
code: selector?.code || section['.name'],
|
||||
displayName,
|
||||
outbounds: [
|
||||
{
|
||||
code: fallbackUrltest?.code || '',
|
||||
displayName: _('Fastest'),
|
||||
latency: fallbackUrltest?.value?.history?.[0]?.delay || 0,
|
||||
type: fallbackUrltest?.value?.type || '',
|
||||
selected: selector?.value?.now === fallbackUrltest?.code,
|
||||
},
|
||||
...fallbackOutbounds,
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
withTagSelect: true,
|
||||
code: selector?.code || section['.name'],
|
||||
displayName,
|
||||
outbounds,
|
||||
};
|
||||
}
|
||||
|
||||
if (proxyConfigType === 'interface') {
|
||||
const outbound = proxies.find(
|
||||
(proxy) => proxy.code === `${section['.name']}-out`,
|
||||
|
||||
@@ -94,4 +94,6 @@ export const PodkopShellMethods = {
|
||||
callBaseMethod<Podkop.GetSystemInfo>(
|
||||
Podkop.AvailableMethods.GET_SYSTEM_INFO,
|
||||
),
|
||||
subscriptionUpdate: async () =>
|
||||
callBaseMethod<unknown>(Podkop.AvailableMethods.SUBSCRIPTION_UPDATE),
|
||||
};
|
||||
|
||||
@@ -69,6 +69,7 @@ export namespace Podkop {
|
||||
CHECK_LOGS = 'check_logs',
|
||||
CHECK_SING_BOX_LOGS = 'check_sing_box_logs',
|
||||
GET_SYSTEM_INFO = 'get_system_info',
|
||||
SUBSCRIPTION_UPDATE = 'subscription_update',
|
||||
}
|
||||
|
||||
export enum AvailableClashAPIMethods {
|
||||
@@ -100,7 +101,8 @@ export namespace Podkop {
|
||||
| 'selector'
|
||||
| 'url'
|
||||
| 'outbound'
|
||||
| 'interface';
|
||||
| 'interface'
|
||||
| 'subscription';
|
||||
|
||||
export interface ConfigSection {
|
||||
'.name': string;
|
||||
@@ -117,6 +119,11 @@ export namespace Podkop {
|
||||
nfqws_opt?: string;
|
||||
selector_proxy_links?: string[];
|
||||
urltest_proxy_links?: string[];
|
||||
subscription_url?: string;
|
||||
subscription_update_interval?: string;
|
||||
subscription_update_interval_disabled?: '0' | '1';
|
||||
subscription_group_by_countries?: '0' | '1';
|
||||
urltest_check_interval_disabled?: '0' | '1';
|
||||
outbound_json?: string;
|
||||
interface?: string;
|
||||
yacd_secret_key?: string;
|
||||
|
||||
@@ -8,6 +8,9 @@ const validUrls = [
|
||||
['With query', 'https://example.com/?q=test'],
|
||||
['With port', 'http://example.com:8080'],
|
||||
['With subdomain', 'https://sub.example.com'],
|
||||
['IPv4 host', 'http://127.0.0.1/podkop-subscription-test.json'],
|
||||
['IPv4 host with port', 'http://192.168.1.1:8080/sub'],
|
||||
['localhost host', 'http://localhost/sub'],
|
||||
];
|
||||
|
||||
const invalidUrls = [
|
||||
@@ -17,6 +20,7 @@ const invalidUrls = [
|
||||
['Unsupported protocol (ws)', 'ws://example.com'],
|
||||
['Empty string', ''],
|
||||
['Without tld', 'https://google'],
|
||||
['Invalid IPv4 host', 'http://999.0.0.1/sub'],
|
||||
];
|
||||
|
||||
describe('validateUrl', () => {
|
||||
|
||||
@@ -21,7 +21,14 @@ export function validateUrl(
|
||||
|
||||
const regex = new RegExp(
|
||||
`^(?:${protocols.map((p) => p.replace(':', '')).join('|')})://` +
|
||||
`(?:[A-Za-z0-9-]+\\.)+[A-Za-z]{2,}(?::\\d+)?(?:/[^\\s]*)?$`,
|
||||
`(?:` +
|
||||
`(?:[A-Za-z0-9-]+\\.)+[A-Za-z]{2,}` +
|
||||
`|` +
|
||||
`(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}` +
|
||||
`|` +
|
||||
`localhost` +
|
||||
`)` +
|
||||
`(?::\\d+)?(?:/[^\\s]*)?$`,
|
||||
);
|
||||
|
||||
if (regex.test(url)) {
|
||||
|
||||
@@ -68,7 +68,7 @@ function validateUrl(url, protocols = ["http:", "https:"]) {
|
||||
message: _("URL must use one of the following protocols:") + " " + protocols.join(", ")
|
||||
};
|
||||
const regex = new RegExp(
|
||||
`^(?:${protocols.map((p) => p.replace(":", "")).join("|")})://(?:[A-Za-z0-9-]+\\.)+[A-Za-z]{2,}(?::\\d+)?(?:/[^\\s]*)?$`
|
||||
`^(?:${protocols.map((p) => p.replace(":", "")).join("|")})://(?:(?:[A-Za-z0-9-]+\\.)+[A-Za-z]{2,}|(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}|localhost)(?::\\d+)?(?:/[^\\s]*)?$`
|
||||
);
|
||||
if (regex.test(url)) {
|
||||
return { valid: true, message: _("Valid") };
|
||||
@@ -745,6 +745,7 @@ var Podkop;
|
||||
AvailableMethods2["CHECK_LOGS"] = "check_logs";
|
||||
AvailableMethods2["CHECK_SING_BOX_LOGS"] = "check_sing_box_logs";
|
||||
AvailableMethods2["GET_SYSTEM_INFO"] = "get_system_info";
|
||||
AvailableMethods2["SUBSCRIPTION_UPDATE"] = "subscription_update";
|
||||
})(AvailableMethods = Podkop2.AvailableMethods || (Podkop2.AvailableMethods = {}));
|
||||
let AvailableClashAPIMethods;
|
||||
((AvailableClashAPIMethods2) => {
|
||||
@@ -826,7 +827,8 @@ var PodkopShellMethods = {
|
||||
checkSingBoxLogs: async () => callBaseMethod(Podkop.AvailableMethods.CHECK_SING_BOX_LOGS),
|
||||
getSystemInfo: async () => callBaseMethod(
|
||||
Podkop.AvailableMethods.GET_SYSTEM_INFO
|
||||
)
|
||||
),
|
||||
subscriptionUpdate: async () => callBaseMethod(Podkop.AvailableMethods.SUBSCRIPTION_UPDATE)
|
||||
};
|
||||
|
||||
// src/podkop/methods/custom/getDashboardSections.ts
|
||||
@@ -979,6 +981,70 @@ async function getDashboardSections() {
|
||||
]
|
||||
};
|
||||
}
|
||||
if (proxyConfigType === "subscription") {
|
||||
const selector = proxies.find(
|
||||
(proxy) => proxy.code === `${section[".name"]}-out`
|
||||
);
|
||||
const fallbackUrltest = proxies.find(
|
||||
(proxy) => proxy.code === `${section[".name"]}-urltest-out`
|
||||
);
|
||||
const selectorOutbounds = (selector?.value?.all ?? []).flatMap(
|
||||
(code) => {
|
||||
const item = proxies.find((proxy) => proxy.code === code);
|
||||
if (!item) {
|
||||
return [];
|
||||
}
|
||||
const isDefaultFastest = item.code === `${section[".name"]}-urltest-out`;
|
||||
return [
|
||||
{
|
||||
code: item.code,
|
||||
displayName: isDefaultFastest ? _("Fastest") : item?.value?.name || "",
|
||||
latency: item?.value?.history?.[0]?.delay || 0,
|
||||
type: item?.value?.type || "",
|
||||
selected: selector?.value?.now === item.code
|
||||
}
|
||||
];
|
||||
}
|
||||
);
|
||||
const outbounds = [
|
||||
...selectorOutbounds.filter(
|
||||
(item) => item.type?.toLowerCase() === "urltest"
|
||||
),
|
||||
...selectorOutbounds.filter(
|
||||
(item) => item.type?.toLowerCase() !== "urltest"
|
||||
)
|
||||
];
|
||||
if (outbounds.length === 0 && fallbackUrltest) {
|
||||
const fallbackOutbounds = (fallbackUrltest?.value?.all ?? []).map((code) => proxies.find((item) => item.code === code)).map((item) => ({
|
||||
code: item?.code || "",
|
||||
displayName: item?.value?.name || "",
|
||||
latency: item?.value?.history?.[0]?.delay || 0,
|
||||
type: item?.value?.type || "",
|
||||
selected: selector?.value?.now === item?.code
|
||||
}));
|
||||
return {
|
||||
withTagSelect: true,
|
||||
code: selector?.code || section[".name"],
|
||||
displayName,
|
||||
outbounds: [
|
||||
{
|
||||
code: fallbackUrltest?.code || "",
|
||||
displayName: _("Fastest"),
|
||||
latency: fallbackUrltest?.value?.history?.[0]?.delay || 0,
|
||||
type: fallbackUrltest?.value?.type || "",
|
||||
selected: selector?.value?.now === fallbackUrltest?.code
|
||||
},
|
||||
...fallbackOutbounds
|
||||
]
|
||||
};
|
||||
}
|
||||
return {
|
||||
withTagSelect: true,
|
||||
code: selector?.code || section[".name"],
|
||||
displayName,
|
||||
outbounds
|
||||
};
|
||||
}
|
||||
if (proxyConfigType === "interface") {
|
||||
const outbound = proxies.find(
|
||||
(proxy) => proxy.code === `${section[".name"]}-out`
|
||||
|
||||
@@ -55,6 +55,12 @@ function renderSectionAdd(sectionRef, extra_class) {
|
||||
return el;
|
||||
}
|
||||
|
||||
function getRuleEditButtonText() {
|
||||
const label = _("Edit rule action");
|
||||
|
||||
return label === "Edit rule action" ? "Edit" : label;
|
||||
}
|
||||
|
||||
function repaintRuleRowColors() {
|
||||
const container = document.getElementById(`cbi-${CBI_PREFIX}-rule`);
|
||||
if (!container) {
|
||||
@@ -363,7 +369,7 @@ function configureGridSection(sectionRef, type, title, addTitle) {
|
||||
return form.TableSection.prototype.renderRowActions.call(
|
||||
this,
|
||||
section_id,
|
||||
_("Edit", "Rule row action"),
|
||||
getRuleEditButtonText(),
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -325,6 +325,86 @@ function validateKeyword(_section_id, value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function isSingBoxDuration(value) {
|
||||
return /^([0-9]+(?:\.[0-9]+)?(?:ns|us|ms|s|m|h|d))+$/.test(value);
|
||||
}
|
||||
|
||||
function readDurationOptionWithDefault(section_id, key, defaultValue) {
|
||||
if (uci.get(UCI_PACKAGE, section_id, `${key}_disabled`) === "1") {
|
||||
return "";
|
||||
}
|
||||
|
||||
const rawValue = uci.get(UCI_PACKAGE, section_id, key);
|
||||
|
||||
if (rawValue == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return `${rawValue}`;
|
||||
}
|
||||
|
||||
function writeOptionalDurationOption(section_id, key, value) {
|
||||
const normalized = value ? `${value}`.trim() : "";
|
||||
const disabledKey = `${key}_disabled`;
|
||||
|
||||
if (normalized.length) {
|
||||
uci.set(UCI_PACKAGE, section_id, key, normalized);
|
||||
uci.unset(UCI_PACKAGE, section_id, disabledKey);
|
||||
} else {
|
||||
uci.unset(UCI_PACKAGE, section_id, key);
|
||||
uci.set(UCI_PACKAGE, section_id, disabledKey, "1");
|
||||
}
|
||||
}
|
||||
|
||||
function removeOptionalDurationOption(section_id, key) {
|
||||
writeOptionalDurationOption(section_id, key, "");
|
||||
}
|
||||
|
||||
function validateOptionalSingBoxDuration(value) {
|
||||
const normalized = value ? `${value}`.trim() : "";
|
||||
|
||||
if (!normalized.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isSingBoxDuration(normalized)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return _("Use sing-box duration format like 1d, 12h or 30m");
|
||||
}
|
||||
|
||||
function parseRequiredValueOnSave(section_id) {
|
||||
const active = this.isActive(section_id);
|
||||
|
||||
if (active && !this.isValid(section_id)) {
|
||||
const title = this.stripTags(this.title).trim();
|
||||
const error = this.getValidationError(section_id);
|
||||
return Promise.reject(
|
||||
new TypeError(
|
||||
`${_("Option \"%s\" contains an invalid input value.").format(title || this.option)} ${error}`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (active) {
|
||||
const formValue = this.formvalue(section_id);
|
||||
const normalized = formValue ? `${formValue}`.trim() : "";
|
||||
|
||||
if (!normalized.length) {
|
||||
return Promise.reject(new TypeError(_("Subscription URL cannot be empty")));
|
||||
}
|
||||
|
||||
return Promise.resolve(this.write(section_id, normalized));
|
||||
}
|
||||
|
||||
if (!this.retain) {
|
||||
return Promise.resolve(this.remove(section_id));
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
function getDuplicateTextListErrors(values, normalizeValue, duplicateMessage) {
|
||||
const seen = new Set();
|
||||
const duplicates = [];
|
||||
@@ -472,12 +552,35 @@ function applyTextareaInputAttributes(textarea) {
|
||||
textarea.style.resize = "vertical";
|
||||
textarea.style.maxWidth = "100%";
|
||||
|
||||
const getRowsMinHeight = () => {
|
||||
const rows = Number.parseInt(textarea.getAttribute("rows") || "0", 10);
|
||||
if (!rows || typeof window === "undefined") {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const style = window.getComputedStyle(textarea);
|
||||
const fontSize = Number.parseFloat(style.fontSize) || 16;
|
||||
const lineHeight =
|
||||
Number.parseFloat(style.lineHeight) || Math.ceil(fontSize * 1.2);
|
||||
const verticalPadding =
|
||||
(Number.parseFloat(style.paddingTop) || 0) +
|
||||
(Number.parseFloat(style.paddingBottom) || 0);
|
||||
const verticalBorder =
|
||||
(Number.parseFloat(style.borderTopWidth) || 0) +
|
||||
(Number.parseFloat(style.borderBottomWidth) || 0);
|
||||
|
||||
return Math.ceil(rows * lineHeight + verticalPadding + verticalBorder);
|
||||
};
|
||||
|
||||
const applyMinHeight = () => {
|
||||
const storedMinHeight = Number.parseFloat(
|
||||
textarea.getAttribute("data-pdk-default-min-height") || "0",
|
||||
);
|
||||
const nextMinHeight =
|
||||
storedMinHeight > 0 ? storedMinHeight : textarea.offsetHeight;
|
||||
const nextMinHeight = Math.max(
|
||||
storedMinHeight,
|
||||
textarea.offsetHeight,
|
||||
getRowsMinHeight(),
|
||||
);
|
||||
|
||||
if (nextMinHeight > 0) {
|
||||
if (storedMinHeight <= 0) {
|
||||
@@ -500,9 +603,14 @@ function applyTextareaInputAttributes(textarea) {
|
||||
typeof window.requestAnimationFrame === "function"
|
||||
) {
|
||||
window.requestAnimationFrame(() => {
|
||||
applyMinHeight();
|
||||
if (!applyMinHeight()) {
|
||||
window.setTimeout(applyMinHeight, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
textarea.addEventListener("focus", applyMinHeight);
|
||||
textarea.addEventListener("pointerdown", applyMinHeight);
|
||||
}
|
||||
|
||||
function syncAnnotatedTextareaOverlay(textarea, wrapper, overlay) {
|
||||
@@ -1654,6 +1762,7 @@ function createSectionContent(section) {
|
||||
o.value("url", _("Connection URL"));
|
||||
o.value("selector", "Selector");
|
||||
o.value("urltest", "URLTest");
|
||||
o.value("subscription", _("Subscription"));
|
||||
o.value("outbound", _("Outbound JSON"));
|
||||
o.value("interface", _("Interface"));
|
||||
o.default = "url";
|
||||
@@ -1705,6 +1814,73 @@ function createSectionContent(section) {
|
||||
};
|
||||
configureTextareaOption(o);
|
||||
|
||||
o = section.taboption(
|
||||
"settings",
|
||||
form.Value,
|
||||
"subscription_url",
|
||||
_("Subscription URL"),
|
||||
_("Enter the subscription URL to fetch proxy configurations from your provider"),
|
||||
);
|
||||
o.depends({ action: "proxy", proxy_config_type: "subscription" });
|
||||
o.rmempty = true;
|
||||
o.modalonly = true;
|
||||
o.parse = parseRequiredValueOnSave;
|
||||
o.validate = function (_section_id, value) {
|
||||
if (!value || value.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const validation = main.validateUrl(value);
|
||||
return validation.valid ? true : validation.message;
|
||||
};
|
||||
|
||||
o = section.taboption(
|
||||
"settings",
|
||||
form.Value,
|
||||
"subscription_update_interval",
|
||||
_("Subscription update interval"),
|
||||
_("Use sing-box duration format. Leave empty to disable automatic updates."),
|
||||
);
|
||||
o.default = "1h";
|
||||
o.placeholder = "1h";
|
||||
o.rmempty = true;
|
||||
o.forcewrite = true;
|
||||
o.retain = true;
|
||||
o.depends({ action: "proxy", proxy_config_type: "subscription" });
|
||||
o.modalonly = true;
|
||||
o.cfgvalue = function (section_id) {
|
||||
return readDurationOptionWithDefault(
|
||||
section_id,
|
||||
"subscription_update_interval",
|
||||
"1h",
|
||||
);
|
||||
};
|
||||
o.write = function (section_id, value) {
|
||||
writeOptionalDurationOption(
|
||||
section_id,
|
||||
"subscription_update_interval",
|
||||
value,
|
||||
);
|
||||
};
|
||||
o.remove = function (section_id) {
|
||||
removeOptionalDurationOption(section_id, "subscription_update_interval");
|
||||
};
|
||||
o.validate = function (_section_id, value) {
|
||||
return validateOptionalSingBoxDuration(value);
|
||||
};
|
||||
|
||||
o = section.taboption(
|
||||
"settings",
|
||||
form.Flag,
|
||||
"subscription_group_by_countries",
|
||||
_("Group subscription proxies by country"),
|
||||
_("Group subscription proxies by the country flag at the beginning of the outbound tag"),
|
||||
);
|
||||
o.default = "0";
|
||||
o.rmempty = false;
|
||||
o.depends({ action: "proxy", proxy_config_type: "subscription" });
|
||||
o.modalonly = true;
|
||||
|
||||
o = section.taboption(
|
||||
"settings",
|
||||
form.DynamicList,
|
||||
@@ -1743,18 +1919,35 @@ function createSectionContent(section) {
|
||||
|
||||
o = section.taboption(
|
||||
"settings",
|
||||
form.ListValue,
|
||||
form.Value,
|
||||
"urltest_check_interval",
|
||||
_("URLTest interval"),
|
||||
_("Use sing-box duration format. Leave empty to disable periodic URLTest checks."),
|
||||
);
|
||||
o.value("30s", _("Every 30 seconds"));
|
||||
o.value("1m", _("Every minute"));
|
||||
o.value("3m", _("Every 3 minutes"));
|
||||
o.value("5m", _("Every 5 minutes"));
|
||||
o.default = "3m";
|
||||
o.rmempty = false;
|
||||
o.placeholder = "3m";
|
||||
o.rmempty = true;
|
||||
o.forcewrite = true;
|
||||
o.retain = true;
|
||||
o.depends({ action: "proxy", proxy_config_type: "urltest" });
|
||||
o.depends({ action: "proxy", proxy_config_type: "subscription" });
|
||||
o.modalonly = true;
|
||||
o.cfgvalue = function (section_id) {
|
||||
return readDurationOptionWithDefault(
|
||||
section_id,
|
||||
"urltest_check_interval",
|
||||
"3m",
|
||||
);
|
||||
};
|
||||
o.write = function (section_id, value) {
|
||||
writeOptionalDurationOption(section_id, "urltest_check_interval", value);
|
||||
};
|
||||
o.remove = function (section_id) {
|
||||
removeOptionalDurationOption(section_id, "urltest_check_interval");
|
||||
};
|
||||
o.validate = function (_section_id, value) {
|
||||
return validateOptionalSingBoxDuration(value);
|
||||
};
|
||||
|
||||
o = section.taboption(
|
||||
"settings",
|
||||
@@ -1766,6 +1959,7 @@ function createSectionContent(section) {
|
||||
o.default = "50";
|
||||
o.rmempty = false;
|
||||
o.depends({ action: "proxy", proxy_config_type: "urltest" });
|
||||
o.depends({ action: "proxy", proxy_config_type: "subscription" });
|
||||
o.modalonly = true;
|
||||
o.validate = function (_section_id, value) {
|
||||
if (!value || value.length === 0) {
|
||||
@@ -1808,6 +2002,7 @@ function createSectionContent(section) {
|
||||
o.default = "https://www.gstatic.com/generate_204";
|
||||
o.rmempty = false;
|
||||
o.depends({ action: "proxy", proxy_config_type: "urltest" });
|
||||
o.depends({ action: "proxy", proxy_config_type: "subscription" });
|
||||
o.modalonly = true;
|
||||
o.validate = function (_section_id, value) {
|
||||
if (!value || value.length === 0) {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# RU translations for PODKOP PLUS package.
|
||||
# Copyright (C) 2026 THE PODKOP PLUS COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PODKOP PLUS package.
|
||||
# ushan0v, 2026.
|
||||
# Automatically generated, 2026.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PODKOP PLUS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-01 23:07+0300\n"
|
||||
"PO-Revision-Date: 2026-05-01 23:07+0300\n"
|
||||
"Last-Translator: ushan0v\n"
|
||||
"POT-Creation-Date: 2026-05-07 12:30+0300\n"
|
||||
"PO-Revision-Date: 2026-05-07 12:30+0300\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -260,8 +260,7 @@ msgstr "Перетаскивайте строки, чтобы изменить
|
||||
msgid "Duplicate value"
|
||||
msgstr "Дублирующееся значение"
|
||||
|
||||
msgctxt "Rule row action"
|
||||
msgid "Edit"
|
||||
msgid "Edit rule action"
|
||||
msgstr "Изменить"
|
||||
|
||||
msgid "Enable"
|
||||
@@ -291,6 +290,9 @@ msgstr "Включить доступ YACD WAN"
|
||||
msgid "Enter a complete sing-box outbound object"
|
||||
msgstr "Введите полный объект outbound sing-box"
|
||||
|
||||
msgid "Enter the subscription URL to fetch proxy configurations from your provider"
|
||||
msgstr "Введите URL подписки для получения конфигураций прокси от провайдера"
|
||||
|
||||
msgid "Every 3 minutes"
|
||||
msgstr "Каждые 3 минуты"
|
||||
|
||||
@@ -339,6 +341,12 @@ msgstr "Получить глобальную проверку"
|
||||
msgid "Global check"
|
||||
msgstr "Глобальная проверка"
|
||||
|
||||
msgid "Group subscription proxies by country"
|
||||
msgstr "Группировать прокси подписки по странам"
|
||||
|
||||
msgid "Group subscription proxies by the country flag at the beginning of the outbound tag"
|
||||
msgstr "Группирует прокси подписки по флагу страны в начале тега outbound"
|
||||
|
||||
msgid "How often this remote rule set should be refreshed"
|
||||
msgstr "Как часто обновлять этот удалённый набор правил"
|
||||
|
||||
@@ -597,6 +605,9 @@ msgstr "Открыть страницу проекта"
|
||||
msgid "Operation timed out"
|
||||
msgstr "Время ожидания истекло"
|
||||
|
||||
msgid "Option \"%s\" contains an invalid input value."
|
||||
msgstr ""
|
||||
|
||||
msgid "Optional node used to download this remote rule set"
|
||||
msgstr "Необязательный узел, через который скачивается этот удалённый набор правил"
|
||||
|
||||
@@ -834,6 +845,18 @@ msgstr "Запустить Podkop Plus"
|
||||
msgid "Stop Podkop Plus"
|
||||
msgstr "Остановить Podkop Plus"
|
||||
|
||||
msgid "Subscription"
|
||||
msgstr "Подписка"
|
||||
|
||||
msgid "Subscription update interval"
|
||||
msgstr "Интервал обновления подписки"
|
||||
|
||||
msgid "Subscription URL"
|
||||
msgstr "URL подписки"
|
||||
|
||||
msgid "Subscription URL cannot be empty"
|
||||
msgstr "URL подписки не может быть пустым"
|
||||
|
||||
msgid "Successfully copied!"
|
||||
msgstr "Успешно скопировано!"
|
||||
|
||||
@@ -966,6 +989,9 @@ msgstr "Используйте формат длительности sing-box,
|
||||
msgid "Use sing-box duration format. Leave empty to disable automatic updates."
|
||||
msgstr "Используйте формат длительности sing-box. Оставьте поле пустым, чтобы отключить автоматическое обновление."
|
||||
|
||||
msgid "Use sing-box duration format. Leave empty to disable periodic URLTest checks."
|
||||
msgstr "Используйте формат длительности sing-box. Оставьте поле пустым, чтобы отключить периодические проверки URLTest."
|
||||
|
||||
msgid "Valid"
|
||||
msgstr "Валидно"
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) 2026 THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PODKOP PLUS package.
|
||||
# ushan0v <142658494+ushan0v@users.noreply.github.com>, 2026.
|
||||
# Podkop Plus <noreply@podkop.plus>, 2026.
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PODKOP PLUS\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-05-01 20:07+0300\n"
|
||||
"PO-Revision-Date: 2026-05-01 20:07+0300\n"
|
||||
"Last-Translator: ushan0v <142658494+ushan0v@users.noreply.github.com>\n"
|
||||
"POT-Creation-Date: 2026-05-07 09:30+0300\n"
|
||||
"PO-Revision-Date: 2026-05-07 09:30+0300\n"
|
||||
"Last-Translator: Podkop Plus <noreply@podkop.plus>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -36,7 +36,7 @@ msgstr ""
|
||||
msgid "A latency-tested group of proxy URLs for this node"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1731
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1879
|
||||
msgid "A latency-tested group of proxy URLs for this section"
|
||||
msgstr ""
|
||||
|
||||
@@ -44,12 +44,12 @@ msgstr ""
|
||||
msgid "A manual group of proxy URLs for this node"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1713
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1861
|
||||
msgid "A manual group of proxy URLs for this section"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1551
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1583
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1631
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1663
|
||||
msgid "Action"
|
||||
msgstr ""
|
||||
|
||||
@@ -57,15 +57,15 @@ msgstr ""
|
||||
msgid "Active Connections"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:395
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:401
|
||||
msgid "Add a section"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2130
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2297
|
||||
msgid "Add URLs or local paths to .lst lists"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2115
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2282
|
||||
msgid "Add URLs or local paths to .srs / .json lists"
|
||||
msgstr ""
|
||||
|
||||
@@ -77,20 +77,20 @@ msgstr ""
|
||||
msgid "Allows access to YACD from the WAN. Make sure to open the appropriate port in your firewall."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:142
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:148
|
||||
msgid "An error occurred while saving the form:"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:170
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1826
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1993
|
||||
msgid "Applicable for SOCKS and Shadowsocks links"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:836
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:916
|
||||
msgid "At least one valid domain must be specified."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:847
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:927
|
||||
msgid "At least one valid IP or subnet must be specified."
|
||||
msgstr ""
|
||||
|
||||
@@ -102,7 +102,7 @@ msgstr ""
|
||||
msgid "Available actions"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:938
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1018
|
||||
msgid "Backend validation failed: %s"
|
||||
msgstr ""
|
||||
|
||||
@@ -126,7 +126,7 @@ msgstr ""
|
||||
msgid "Browser is using FakeIP correctly"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2020
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2187
|
||||
msgid "Built-in rule sets"
|
||||
msgstr ""
|
||||
|
||||
@@ -183,7 +183,7 @@ msgstr ""
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1539
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1619
|
||||
msgid "Conditions"
|
||||
msgstr ""
|
||||
|
||||
@@ -191,20 +191,20 @@ msgstr ""
|
||||
msgid "Config File Path"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:381
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:387
|
||||
msgid "Configuration for Podkop Plus service"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1668
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1749
|
||||
msgid "Connection"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1651
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1731
|
||||
msgid "Connection Type"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:19
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1654
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1734
|
||||
msgid "Connection URL"
|
||||
msgstr ""
|
||||
|
||||
@@ -216,7 +216,7 @@ msgstr ""
|
||||
msgid "Currently unavailable"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:426
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:432
|
||||
msgid "Dashboard"
|
||||
msgstr ""
|
||||
|
||||
@@ -236,7 +236,7 @@ msgstr ""
|
||||
msgid "DHCP has DNS server"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:414
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:420
|
||||
msgid "Diagnostics"
|
||||
msgstr ""
|
||||
|
||||
@@ -257,7 +257,7 @@ msgstr ""
|
||||
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:149
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:155
|
||||
msgid "Dismiss"
|
||||
msgstr ""
|
||||
|
||||
@@ -266,18 +266,18 @@ msgid "DNS on router"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:227
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1891
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2058
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/settings.js:21
|
||||
msgid "DNS over HTTPS (DoH)"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:228
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1892
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2059
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/settings.js:22
|
||||
msgid "DNS over TLS (DoT)"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1889
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2056
|
||||
msgid "DNS protocol"
|
||||
msgstr ""
|
||||
|
||||
@@ -293,7 +293,7 @@ msgstr ""
|
||||
msgid "DNS Rewrite TTL"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1907
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2074
|
||||
msgid "DNS server"
|
||||
msgstr ""
|
||||
|
||||
@@ -310,19 +310,19 @@ msgstr ""
|
||||
msgid "Do not panic, everything can be fixed, just..."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2129
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2296
|
||||
msgid "Domain and IP Lists"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1990
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2157
|
||||
msgid "Domain keyword"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1997
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2164
|
||||
msgid "Domain regex"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1962
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2129
|
||||
msgid "Domains"
|
||||
msgstr ""
|
||||
|
||||
@@ -359,24 +359,23 @@ msgstr ""
|
||||
msgid "Downloading all lists via specific Proxy/VPN"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:389
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:395
|
||||
msgid "Drag rows to change priority. The rule at the top is checked first."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:369
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:384
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:404
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:449
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:464
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:484
|
||||
msgid "Duplicate value"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:366
|
||||
msgctxt "Rule row action"
|
||||
msgid "Edit"
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:59
|
||||
msgid "Edit rule action"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:8
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/ruleset.js:10
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1541
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1621
|
||||
msgid "Enable"
|
||||
msgstr ""
|
||||
|
||||
@@ -384,7 +383,7 @@ msgstr ""
|
||||
msgid "Enable a dedicated DNS resolver when this node uses an interface"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1878
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2045
|
||||
msgid "Enable a dedicated DNS resolver when this section uses an interface"
|
||||
msgstr ""
|
||||
|
||||
@@ -392,7 +391,7 @@ msgstr ""
|
||||
msgid "Enable autostart"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1929
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2096
|
||||
msgid "Enable Mixed Proxy"
|
||||
msgstr ""
|
||||
|
||||
@@ -409,31 +408,31 @@ msgid "Enable YACD WAN Access"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:52
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1691
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1772
|
||||
msgid "Enter a complete sing-box outbound object"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1794
|
||||
msgid "Enter the subscription URL to fetch proxy configurations from your provider"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:103
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1752
|
||||
msgid "Every 3 minutes"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:101
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1750
|
||||
msgid "Every 30 seconds"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:104
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1753
|
||||
msgid "Every 5 minutes"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:102
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1751
|
||||
msgid "Every minute"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1976
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2143
|
||||
msgid "Exact full domain"
|
||||
msgstr ""
|
||||
|
||||
@@ -449,11 +448,11 @@ msgstr ""
|
||||
msgid "Expecting: %s"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1930
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2097
|
||||
msgid "Expose this section as a local HTTP+SOCKS proxy"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:999
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1079
|
||||
msgid "External nfqws config files bypass Podkop Plus queue management and explicit validation."
|
||||
msgstr ""
|
||||
|
||||
@@ -471,6 +470,8 @@ msgid "Failed to execute!"
|
||||
msgstr ""
|
||||
|
||||
#: src/podkop/methods/custom/getDashboardSections.ts:188
|
||||
#: src/podkop/methods/custom/getDashboardSections.ts:220
|
||||
#: src/podkop/methods/custom/getDashboardSections.ts:257
|
||||
#: src/podkop/tabs/diagnostic/checks/runSectionsCheck.ts:59
|
||||
msgid "Fastest"
|
||||
msgstr ""
|
||||
@@ -487,11 +488,19 @@ msgstr ""
|
||||
msgid "Global check"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1848
|
||||
msgid "Group subscription proxies by country"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1849
|
||||
msgid "Group subscription proxies by the country flag at the beginning of the outbound tag"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/ruleset.js:87
|
||||
msgid "How often this remote rule set should be refreshed"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1652
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1732
|
||||
msgid "How to configure the proxy connection for this section"
|
||||
msgstr ""
|
||||
|
||||
@@ -501,8 +510,8 @@ msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:23
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:179
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1658
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1837
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1739
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2004
|
||||
msgid "Interface"
|
||||
msgstr ""
|
||||
|
||||
@@ -595,7 +604,7 @@ msgstr ""
|
||||
msgid "Invalid path format. Path must start with \"/\" and contain valid characters"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1957
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2124
|
||||
#: src/validators/validateShadowsocksUrl.ts:85
|
||||
msgid "Invalid port number. Must be between 1 and 65535"
|
||||
msgstr ""
|
||||
@@ -701,7 +710,7 @@ msgstr ""
|
||||
msgid "IP address 0.0.0.0 is not allowed"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1969
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2136
|
||||
msgid "IPs"
|
||||
msgstr ""
|
||||
|
||||
@@ -719,7 +728,7 @@ msgstr ""
|
||||
msgid "Latest"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1504
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1584
|
||||
msgid "List must be a direct .lst URL or a local .lst path"
|
||||
msgstr ""
|
||||
|
||||
@@ -743,32 +752,32 @@ msgstr ""
|
||||
msgid "Main DNS"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1970
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2137
|
||||
msgid "Match destination IPs or subnets"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1991
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2158
|
||||
msgid "Match domains containing a substring"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1963
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2130
|
||||
msgid "Match domains including all subdomains"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1998
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2165
|
||||
msgid "Match domains using a regular expression"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1977
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2144
|
||||
msgid "Match only one exact full domain name"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2005
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2172
|
||||
msgid "Match source IPs or subnets"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:114
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1764
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1929
|
||||
msgid "Maximum response time delta in milliseconds"
|
||||
msgstr ""
|
||||
|
||||
@@ -776,7 +785,7 @@ msgstr ""
|
||||
msgid "Memory Usage"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1941
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2108
|
||||
msgid "Mixed Proxy Port"
|
||||
msgstr ""
|
||||
|
||||
@@ -785,7 +794,7 @@ msgid "Monitored Interfaces"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:136
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1786
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1952
|
||||
msgid "Must be a number in the range of 50 - 1000"
|
||||
msgstr ""
|
||||
|
||||
@@ -797,11 +806,11 @@ msgstr ""
|
||||
msgid "NFQUEUE range overlaps with another rule"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1617
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1697
|
||||
msgid "NFQWS Strategy"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1129
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1209
|
||||
msgid "NFQWS strategy cannot be empty"
|
||||
msgstr ""
|
||||
|
||||
@@ -848,18 +857,22 @@ msgstr ""
|
||||
msgid "Operation timed out"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:385
|
||||
msgid "Option \"%s\" contains an invalid input value."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/ruleset.js:64
|
||||
msgid "Optional node used to download this remote rule set"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1207
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1287
|
||||
msgid "Optional values must be attached with '=' here; a separate token would be ignored by nfqws."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:22
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:51
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1657
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1690
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1738
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1771
|
||||
msgid "Outbound JSON"
|
||||
msgstr ""
|
||||
|
||||
@@ -900,11 +913,11 @@ msgstr ""
|
||||
msgid "Pending"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1017
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1097
|
||||
msgid "Podkop Plus manages the nfqws process lifecycle itself, so daemon mode is not allowed here."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:380
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:386
|
||||
msgid "Podkop Plus Settings"
|
||||
msgstr ""
|
||||
|
||||
@@ -924,11 +937,11 @@ msgstr ""
|
||||
msgid "Podkop-managed nfqws runtime is ready"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1949
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2116
|
||||
msgid "Port cannot be empty"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1942
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2109
|
||||
msgid "Port for the local mixed proxy of this section"
|
||||
msgstr ""
|
||||
|
||||
@@ -944,7 +957,7 @@ msgstr ""
|
||||
msgid "Proxy traffic is routed via FakeIP"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2059
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2226
|
||||
msgid "Regional options cannot be used together"
|
||||
msgstr ""
|
||||
|
||||
@@ -956,7 +969,7 @@ msgstr ""
|
||||
msgid "Remote URL to a sing-box rule set"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1877
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2044
|
||||
msgid "Resolver for interface outbound"
|
||||
msgstr ""
|
||||
|
||||
@@ -964,11 +977,11 @@ msgstr ""
|
||||
msgid "Resolver For Interface Outbound"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1002
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1082
|
||||
msgid "Resource selection by hostname inside nfqws is not supported here; sing-box selects resources before NFQUEUE."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1005
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1085
|
||||
msgid "Resource selection by IP or CIDR inside nfqws is not supported here; sing-box selects resources before NFQUEUE."
|
||||
msgstr ""
|
||||
|
||||
@@ -980,7 +993,7 @@ msgstr ""
|
||||
msgid "Routing Excluded IPs"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1496
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1576
|
||||
msgid "Rule set must be a direct .srs / .json URL or a local .srs / .json path"
|
||||
msgstr ""
|
||||
|
||||
@@ -988,7 +1001,7 @@ msgstr ""
|
||||
msgid "Rule set URL"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2114
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2281
|
||||
msgid "Rule sets"
|
||||
msgstr ""
|
||||
|
||||
@@ -1020,11 +1033,11 @@ msgstr ""
|
||||
msgid "Run Diagnostic"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2078
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2245
|
||||
msgid "Russia inside restrictions"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:141
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:147
|
||||
msgid "Save error"
|
||||
msgstr ""
|
||||
|
||||
@@ -1032,19 +1045,19 @@ msgstr ""
|
||||
msgid "Secret key for authenticating remote access to YACD when WAN access is enabled."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:394
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:400
|
||||
msgid "Section"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1570
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1650
|
||||
msgid "Section name"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:388
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:394
|
||||
msgid "Sections"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2021
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2188
|
||||
msgid "Select a predefined list for routing"
|
||||
msgstr ""
|
||||
|
||||
@@ -1080,7 +1093,7 @@ msgstr ""
|
||||
msgid "Select the WAN interfaces to be monitored"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1712
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1860
|
||||
msgid "Selector connections"
|
||||
msgstr ""
|
||||
|
||||
@@ -1088,7 +1101,7 @@ msgstr ""
|
||||
msgid "Selector Links"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2024
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2191
|
||||
msgid "Service list"
|
||||
msgstr ""
|
||||
|
||||
@@ -1096,8 +1109,8 @@ msgstr ""
|
||||
msgid "Services info"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:402
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1538
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/podkop.js:408
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1618
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
@@ -1142,7 +1155,7 @@ msgstr ""
|
||||
msgid "Source file"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2004
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2171
|
||||
msgid "Source IPs"
|
||||
msgstr ""
|
||||
|
||||
@@ -1174,6 +1187,22 @@ msgstr ""
|
||||
msgid "Stop Podkop Plus"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1737
|
||||
msgid "Subscription"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1813
|
||||
msgid "Subscription update interval"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1793
|
||||
msgid "Subscription URL"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:395
|
||||
msgid "Subscription URL cannot be empty"
|
||||
msgstr ""
|
||||
|
||||
#: src/helpers/copyToClipboard.ts:10
|
||||
msgid "Successfully copied!"
|
||||
msgstr ""
|
||||
@@ -1194,7 +1223,7 @@ msgstr ""
|
||||
msgid "Test latency"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1014
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1094
|
||||
msgid "The desync fwmark is managed by Podkop Plus for loop prevention and must not be overridden here."
|
||||
msgstr ""
|
||||
|
||||
@@ -1202,7 +1231,7 @@ msgstr ""
|
||||
msgid "The DNS server used to look up the IP address of an upstream DNS server"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1011
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1091
|
||||
msgid "The NFQUEUE number is assigned by Podkop Plus for each rule and must not be overridden here."
|
||||
msgstr ""
|
||||
|
||||
@@ -1210,19 +1239,19 @@ msgstr ""
|
||||
msgid "There are rules using Zapret"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1020
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1100
|
||||
msgid "This field must start a working nfqws strategy; --dry-run exits immediately and is not allowed here."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1023
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1103
|
||||
msgid "This field must start a working nfqws strategy; --version exits immediately and is not allowed here."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1192
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1272
|
||||
msgid "This flag does not accept a value."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1223
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1303
|
||||
msgid "This option requires a value."
|
||||
msgstr ""
|
||||
|
||||
@@ -1259,11 +1288,11 @@ msgid "UDP (Unprotected DNS)"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:169
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1825
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1992
|
||||
msgid "UDP over TCP"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:934
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1014
|
||||
msgid "Unable to validate the NFQWS strategy through the backend parser."
|
||||
msgstr ""
|
||||
|
||||
@@ -1271,7 +1300,7 @@ msgstr ""
|
||||
msgid "Unexpected Podkop-managed nfqws runtime is running"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1172
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1252
|
||||
msgid "Unexpected standalone token. Use explicit flags such as --name or --name=value."
|
||||
msgstr ""
|
||||
|
||||
@@ -1294,7 +1323,7 @@ msgstr ""
|
||||
msgid "Unknown error"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1183
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1263
|
||||
msgid "Unknown NFQWS flag."
|
||||
msgstr ""
|
||||
|
||||
@@ -1315,11 +1344,11 @@ msgstr ""
|
||||
msgid "URL must use one of the following protocols:"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1730
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1878
|
||||
msgid "URLTest connections"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1748
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1896
|
||||
msgid "URLTest interval"
|
||||
msgstr ""
|
||||
|
||||
@@ -1331,7 +1360,7 @@ msgstr ""
|
||||
msgid "URLTest Links"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1763
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1928
|
||||
msgid "URLTest tolerance"
|
||||
msgstr ""
|
||||
|
||||
@@ -1340,7 +1369,7 @@ msgid "URLTest Tolerance"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:139
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1793
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1959
|
||||
msgid "URLTest URL"
|
||||
msgstr ""
|
||||
|
||||
@@ -1348,18 +1377,24 @@ msgstr ""
|
||||
msgid "Use a network interface as the outbound for this node"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1838
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2005
|
||||
msgid "Use a network interface as the outbound for this section"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:374
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/settings.js:312
|
||||
msgid "Use sing-box duration format like 1d, 12h or 30m"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1814
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/settings.js:283
|
||||
msgid "Use sing-box duration format. Leave empty to disable automatic updates."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1897
|
||||
msgid "Use sing-box duration format. Leave empty to disable periodic URLTest checks."
|
||||
msgstr ""
|
||||
|
||||
#: src/validators/validateDns.ts:14
|
||||
#: src/validators/validateDns.ts:18
|
||||
#: src/validators/validateDomain.ts:13
|
||||
@@ -1377,9 +1412,9 @@ msgstr ""
|
||||
msgid "Valid"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:376
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:396
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:400
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:456
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:476
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:480
|
||||
msgid "Validation errors:"
|
||||
msgstr ""
|
||||
|
||||
@@ -1388,24 +1423,24 @@ msgstr ""
|
||||
msgid "View logs"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1571
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1651
|
||||
msgid "Visible name of this section"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/node.js:32
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1669
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1750
|
||||
msgid "vless://, ss://, trojan://, socks4/5://, hy2/hysteria2:// links"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2061
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2228
|
||||
msgid "Warning: %s cannot be used together with %s. Previous selections have been removed."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2080
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:2247
|
||||
msgid "Warning: Russia inside can only be used with %s. %s already in Russia inside and have been removed from selection."
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1584
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1664
|
||||
msgid "What Podkop Plus should do when this section matches"
|
||||
msgstr ""
|
||||
|
||||
@@ -1422,7 +1457,7 @@ msgstr ""
|
||||
msgid "Zapret (provider not available)"
|
||||
msgstr ""
|
||||
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1008
|
||||
#: ../luci-app-podkop-plus/htdocs/luci-static/resources/view/podkop/section.js:1088
|
||||
msgid "Zapret hostlist templates are not supported here because Podkop Plus does not expand them for per-rule NFQWS strategies."
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -21,3 +21,16 @@ config settings 'settings'
|
||||
option exclude_ntp '0'
|
||||
option shutdown_correctly '0'
|
||||
#list routing_excluded_ips '192.168.1.3'
|
||||
|
||||
#config rule 'subscription_example'
|
||||
# option label 'Subscription'
|
||||
# option enabled '1'
|
||||
# option action 'proxy'
|
||||
# option proxy_config_type 'subscription'
|
||||
# option subscription_url 'https://example.com/api/sub'
|
||||
# option subscription_update_interval '1h'
|
||||
# option subscription_group_by_countries '0'
|
||||
# option urltest_check_interval '3m'
|
||||
# option urltest_tolerance '50'
|
||||
# option urltest_testing_url 'https://www.gstatic.com/generate_204'
|
||||
# list community_lists 'russia_inside'
|
||||
|
||||
+755
-24
@@ -39,7 +39,9 @@ PODKOP_RUNTIME_STATUS_FILE="$PODKOP_RUNTIME_STATE_DIR/status"
|
||||
PODKOP_SYSTEM_INFO_CACHE_FILE="$PODKOP_RUNTIME_STATE_DIR/system-info.json"
|
||||
PODKOP_RELOAD_STATE_FILE="$PODKOP_RUNTIME_STATE_DIR/reload-state"
|
||||
PODKOP_LIST_UPDATE_STATE_FILE="$PODKOP_RUNTIME_STATE_DIR/list-update.timestamp"
|
||||
PODKOP_SUBSCRIPTION_UPDATE_STATE_DIR="$PODKOP_RUNTIME_STATE_DIR/subscription-update"
|
||||
PODKOP_LIST_UPDATE_CRON_MARKER="# podkop-plus-list-update"
|
||||
PODKOP_SUBSCRIPTION_UPDATE_CRON_MARKER="# podkop-plus-subscription-update"
|
||||
# sing-box falls back to 1d when update_interval is empty, so use a large
|
||||
# duration to emulate disabled automatic refreshes for remote rule sets.
|
||||
SING_BOX_DISABLED_UPDATE_INTERVAL="876000h"
|
||||
@@ -55,7 +57,171 @@ config_load "$PODKOP_CONFIG_NAME"
|
||||
ensure_runtime_dirs() {
|
||||
mkdir -p "$TMP_SING_BOX_FOLDER"
|
||||
mkdir -p "$TMP_RULESET_FOLDER"
|
||||
mkdir -p "$TMP_SUBSCRIPTION_FOLDER"
|
||||
mkdir -p "$PODKOP_RUNTIME_STATE_DIR"
|
||||
mkdir -p "$PODKOP_SUBSCRIPTION_UPDATE_STATE_DIR"
|
||||
}
|
||||
|
||||
get_subscription_json_path() {
|
||||
local section="$1"
|
||||
|
||||
echo "$TMP_SUBSCRIPTION_FOLDER/${section}.json"
|
||||
}
|
||||
|
||||
get_subscription_url_cache_path() {
|
||||
local section="$1"
|
||||
|
||||
echo "$TMP_SUBSCRIPTION_FOLDER/${section}.url"
|
||||
}
|
||||
|
||||
get_subscription_update_timestamp_path() {
|
||||
local section="$1"
|
||||
|
||||
echo "$PODKOP_SUBSCRIPTION_UPDATE_STATE_DIR/${section}.timestamp"
|
||||
}
|
||||
|
||||
subscription_cache_is_usable() {
|
||||
local subscription_json_path="$1"
|
||||
|
||||
[ -s "$subscription_json_path" ] || return 1
|
||||
|
||||
validate_subscription_file "$subscription_json_path"
|
||||
}
|
||||
|
||||
wait_for_subscription_connectivity() {
|
||||
local section="$1"
|
||||
local subscription_url="$2"
|
||||
local service_proxy_address="$3"
|
||||
local attempts="${4:-12}"
|
||||
local wait="${5:-5}"
|
||||
local timeout="${6:-5}"
|
||||
local attempt
|
||||
|
||||
for attempt in $(seq 1 "$attempts"); do
|
||||
if check_subscription_connectivity "$subscription_url" "$service_proxy_address" 1 0 "$timeout"; then
|
||||
log "Subscription connectivity check passed for rule '$section'" "info"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Subscription source is unavailable for rule '$section' [$attempt/$attempts]" "warn"
|
||||
[ "$attempt" -lt "$attempts" ] && sleep "$wait"
|
||||
done
|
||||
|
||||
log "Subscription connectivity check failed for rule '$section' after $attempts attempts" "error"
|
||||
return 1
|
||||
}
|
||||
|
||||
download_subscription_into_cache() {
|
||||
local section="$1"
|
||||
local subscription_url="$2"
|
||||
local subscription_json_path="$3"
|
||||
local subscription_url_cache_path="$4"
|
||||
local service_proxy_address="$5"
|
||||
local tmpfile
|
||||
|
||||
mkdir -p "$TMP_SUBSCRIPTION_FOLDER"
|
||||
tmpfile="$(mktemp "$TMP_SUBSCRIPTION_FOLDER/${section}.download.XXXXXX")" || return 1
|
||||
|
||||
if ! download_subscription "$subscription_url" "$tmpfile" "$service_proxy_address" 3 2 10; then
|
||||
rm -f "$tmpfile"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! validate_subscription_file "$tmpfile"; then
|
||||
log "Downloaded subscription for rule '$section' is invalid" "error"
|
||||
rm -f "$tmpfile"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -f "$subscription_json_path" ] && cmp -s "$tmpfile" "$subscription_json_path"; then
|
||||
rm -f "$tmpfile"
|
||||
printf '%s' "$subscription_url" > "$subscription_url_cache_path"
|
||||
log "Subscription for rule '$section' is unchanged" "info"
|
||||
return 2
|
||||
fi
|
||||
|
||||
mv "$tmpfile" "$subscription_json_path" || {
|
||||
rm -f "$tmpfile"
|
||||
return 1
|
||||
}
|
||||
|
||||
printf '%s' "$subscription_url" > "$subscription_url_cache_path"
|
||||
return 0
|
||||
}
|
||||
|
||||
rule_is_subscription_proxy() {
|
||||
local section="$1"
|
||||
local action proxy_config_type
|
||||
|
||||
rule_is_enabled "$section" || return 1
|
||||
|
||||
action="$(get_rule_action "$section")"
|
||||
[ "$action" = "proxy" ] || return 1
|
||||
|
||||
proxy_config_type="$(get_proxy_config_type "$section")"
|
||||
[ "$proxy_config_type" = "subscription" ]
|
||||
}
|
||||
|
||||
prepare_subscription_cache_for_startup() {
|
||||
local section="$1"
|
||||
local subscription_url subscription_json_path subscription_url_cache_path cached_subscription_url
|
||||
local service_proxy_address had_usable_cache cache_needs_refresh
|
||||
|
||||
rule_is_subscription_proxy "$section" || return 0
|
||||
|
||||
config_get subscription_url "$section" "subscription_url"
|
||||
if [ -z "$subscription_url" ]; then
|
||||
log "Subscription URL is not set for rule '$section'. Aborted." "fatal"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
subscription_json_path="$(get_subscription_json_path "$section")"
|
||||
subscription_url_cache_path="$(get_subscription_url_cache_path "$section")"
|
||||
cached_subscription_url=""
|
||||
had_usable_cache=0
|
||||
cache_needs_refresh=0
|
||||
|
||||
if subscription_cache_is_usable "$subscription_json_path"; then
|
||||
had_usable_cache=1
|
||||
else
|
||||
rm -f "$subscription_json_path"
|
||||
fi
|
||||
|
||||
if [ -f "$subscription_url_cache_path" ]; then
|
||||
cached_subscription_url="$(cat "$subscription_url_cache_path" 2> /dev/null)"
|
||||
fi
|
||||
|
||||
if [ "$had_usable_cache" -eq 0 ] || [ "$cached_subscription_url" != "$subscription_url" ]; then
|
||||
cache_needs_refresh=1
|
||||
fi
|
||||
|
||||
[ "$cache_needs_refresh" -eq 0 ] && return 0
|
||||
|
||||
service_proxy_address="$(get_service_proxy_address 2>/dev/null || echo '')"
|
||||
|
||||
if wait_for_subscription_connectivity "$section" "$subscription_url" "$service_proxy_address"; then
|
||||
download_subscription_into_cache \
|
||||
"$section" "$subscription_url" "$subscription_json_path" "$subscription_url_cache_path" "$service_proxy_address"
|
||||
case "$?" in
|
||||
0 | 2) return 0 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ "$had_usable_cache" -eq 1 ]; then
|
||||
log "Keeping cached subscription for rule '$section' until a fresh download succeeds" "warn"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "No usable subscription cache for rule '$section'; startup cannot continue" "error"
|
||||
subscription_startup_blocked=1
|
||||
return 1
|
||||
}
|
||||
|
||||
prepare_subscription_caches_for_startup() {
|
||||
subscription_startup_blocked=0
|
||||
config_foreach prepare_subscription_cache_for_startup "rule"
|
||||
|
||||
[ "$subscription_startup_blocked" -eq 0 ]
|
||||
}
|
||||
|
||||
close_inherited_service_lock_fd() {
|
||||
@@ -288,7 +454,7 @@ append_sing_box_rule_signature() {
|
||||
local urltest_proxy_links udp_over_tcp urltest_check_interval urltest_tolerance urltest_testing_url
|
||||
config_get urltest_proxy_links "$section" "urltest_proxy_links"
|
||||
config_get_bool udp_over_tcp "$section" "enable_udp_over_tcp" 0
|
||||
config_get urltest_check_interval "$section" "urltest_check_interval" "3m"
|
||||
urltest_check_interval="$(get_urltest_check_interval_for_rule "$section")"
|
||||
config_get urltest_tolerance "$section" "urltest_tolerance" 50
|
||||
config_get urltest_testing_url "$section" "urltest_testing_url" "https://www.gstatic.com/generate_204"
|
||||
signature_add "rule.$section.urltest_proxy_links" "$urltest_proxy_links"
|
||||
@@ -310,6 +476,22 @@ append_sing_box_rule_signature() {
|
||||
signature_add "rule.$section.domain_resolver_dns_server" "$domain_resolver_dns_server"
|
||||
fi
|
||||
;;
|
||||
subscription)
|
||||
local subscription_url subscription_update_interval subscription_group_by_countries \
|
||||
urltest_check_interval urltest_tolerance urltest_testing_url
|
||||
config_get subscription_url "$section" "subscription_url"
|
||||
subscription_update_interval="$(get_subscription_update_interval_for_rule "$section")"
|
||||
config_get subscription_group_by_countries "$section" "subscription_group_by_countries"
|
||||
urltest_check_interval="$(get_urltest_check_interval_for_rule "$section")"
|
||||
config_get urltest_tolerance "$section" "urltest_tolerance" 50
|
||||
config_get urltest_testing_url "$section" "urltest_testing_url" "https://www.gstatic.com/generate_204"
|
||||
signature_add "rule.$section.subscription_url" "$subscription_url"
|
||||
signature_add "rule.$section.subscription_update_interval" "$subscription_update_interval"
|
||||
signature_add "rule.$section.subscription_group_by_countries" "$subscription_group_by_countries"
|
||||
signature_add "rule.$section.urltest_check_interval" "$urltest_check_interval"
|
||||
signature_add "rule.$section.urltest_tolerance" "$urltest_tolerance"
|
||||
signature_add "rule.$section.urltest_testing_url" "$urltest_testing_url"
|
||||
;;
|
||||
esac
|
||||
|
||||
config_get_bool mixed_proxy_enabled "$section" "mixed_proxy_enabled" 0
|
||||
@@ -499,6 +681,19 @@ build_list_update_signature() {
|
||||
signature_finish
|
||||
}
|
||||
|
||||
append_subscription_update_cron_signature() {
|
||||
local section="$1"
|
||||
local subscription_update_interval subscription_url
|
||||
|
||||
rule_is_subscription_proxy "$section" || return 0
|
||||
|
||||
config_get subscription_url "$section" "subscription_url"
|
||||
subscription_update_interval="$(get_subscription_update_interval_for_rule "$section")"
|
||||
|
||||
signature_add "subscription.$section.subscription_url" "$subscription_url"
|
||||
signature_add "subscription.$section.subscription_update_interval" "$subscription_update_interval"
|
||||
}
|
||||
|
||||
build_cron_signature() {
|
||||
local update_interval
|
||||
|
||||
@@ -506,6 +701,7 @@ build_cron_signature() {
|
||||
config_get update_interval "settings" "update_interval"
|
||||
signature_add "settings.update_interval" "$update_interval"
|
||||
config_foreach append_list_update_signature "rule"
|
||||
config_foreach append_subscription_update_cron_signature "rule"
|
||||
signature_finish
|
||||
}
|
||||
|
||||
@@ -531,6 +727,34 @@ get_settings_update_interval() {
|
||||
printf '%s\n' "$update_interval"
|
||||
}
|
||||
|
||||
get_duration_option_with_default_if_unset() {
|
||||
local section="$1"
|
||||
local option="$2"
|
||||
local default_value="$3"
|
||||
local disabled value
|
||||
|
||||
config_get_bool disabled "$section" "${option}_disabled" 0
|
||||
if [ "$disabled" -eq 1 ]; then
|
||||
printf '\n'
|
||||
return 0
|
||||
fi
|
||||
|
||||
config_get value "$section" "$option"
|
||||
if [ -n "$value" ]; then
|
||||
printf '%s\n' "$value"
|
||||
else
|
||||
printf '%s\n' "$default_value"
|
||||
fi
|
||||
}
|
||||
|
||||
get_subscription_update_interval_for_rule() {
|
||||
get_duration_option_with_default_if_unset "$1" "subscription_update_interval" "1h"
|
||||
}
|
||||
|
||||
get_urltest_check_interval_for_rule() {
|
||||
get_duration_option_with_default_if_unset "$1" "urltest_check_interval" "3m"
|
||||
}
|
||||
|
||||
get_remote_ruleset_update_interval() {
|
||||
local update_interval
|
||||
|
||||
@@ -596,6 +820,24 @@ has_list_update_sources() {
|
||||
[ "$RELOAD_LIST_SOURCES_PRESENT" -eq 1 ]
|
||||
}
|
||||
|
||||
enabled_rule_has_subscription_update_source() {
|
||||
local section="$1"
|
||||
local subscription_update_interval
|
||||
|
||||
rule_is_subscription_proxy "$section" || return 0
|
||||
|
||||
subscription_update_interval="$(get_subscription_update_interval_for_rule "$section")"
|
||||
[ -n "$subscription_update_interval" ] || return 0
|
||||
|
||||
RELOAD_SUBSCRIPTION_SOURCES_PRESENT=1
|
||||
}
|
||||
|
||||
has_subscription_update_sources() {
|
||||
RELOAD_SUBSCRIPTION_SOURCES_PRESENT=0
|
||||
config_foreach enabled_rule_has_subscription_update_source "rule"
|
||||
[ "$RELOAD_SUBSCRIPTION_SOURCES_PRESENT" -eq 1 ]
|
||||
}
|
||||
|
||||
enabled_rule_has_nft_list_sources() {
|
||||
local section="$1"
|
||||
local community_lists remote_subnet_lists domain_ip_lists
|
||||
@@ -648,22 +890,28 @@ refresh_list_update_cron() {
|
||||
|
||||
remove_cron_job
|
||||
|
||||
if ! has_list_update_sources; then
|
||||
return 0
|
||||
if has_list_update_sources; then
|
||||
update_interval="$(get_settings_update_interval)"
|
||||
if [ -z "$update_interval" ]; then
|
||||
log "Remote list auto-update is disabled"
|
||||
else
|
||||
cron_job="$(build_list_update_cron_job)" || return 1
|
||||
crontab -l 2> /dev/null | {
|
||||
cat
|
||||
echo "$cron_job"
|
||||
} | crontab -
|
||||
log "The cron job has been created: $cron_job"
|
||||
fi
|
||||
fi
|
||||
|
||||
update_interval="$(get_settings_update_interval)"
|
||||
if [ -z "$update_interval" ]; then
|
||||
log "Remote list auto-update is disabled"
|
||||
return 0
|
||||
if has_subscription_update_sources; then
|
||||
cron_job="$(build_subscription_update_cron_job)" || return 1
|
||||
crontab -l 2> /dev/null | {
|
||||
cat
|
||||
echo "$cron_job"
|
||||
} | crontab -
|
||||
log "The subscription cron job has been created: $cron_job"
|
||||
fi
|
||||
|
||||
cron_job="$(build_list_update_cron_job)" || return 1
|
||||
crontab -l 2> /dev/null | {
|
||||
cat
|
||||
echo "$cron_job"
|
||||
} | crontab -
|
||||
log "The cron job has been created: $cron_job"
|
||||
}
|
||||
|
||||
reload_sing_box_runtime() {
|
||||
@@ -690,7 +938,7 @@ get_rule_action() {
|
||||
|
||||
infer_rule_action_from_fields() {
|
||||
local section="$1"
|
||||
local connection_type proxy_config_type proxy_string selector_proxy_links urltest_proxy_links outbound_json interface \
|
||||
local connection_type proxy_config_type proxy_string selector_proxy_links urltest_proxy_links subscription_url outbound_json interface \
|
||||
nfqws_opt
|
||||
|
||||
config_get connection_type "$section" "connection_type"
|
||||
@@ -719,9 +967,10 @@ infer_rule_action_from_fields() {
|
||||
config_get outbound_json "$section" "outbound_json"
|
||||
config_get selector_proxy_links "$section" "selector_proxy_links"
|
||||
config_get urltest_proxy_links "$section" "urltest_proxy_links"
|
||||
config_get subscription_url "$section" "subscription_url"
|
||||
config_get proxy_string "$section" "proxy_string"
|
||||
if [ -n "$interface" ] || [ -n "$outbound_json" ] || [ -n "$selector_proxy_links" ] ||
|
||||
[ -n "$urltest_proxy_links" ] || [ -n "$proxy_string" ]; then
|
||||
[ -n "$urltest_proxy_links" ] || [ -n "$subscription_url" ] || [ -n "$proxy_string" ]; then
|
||||
echo "proxy"
|
||||
return 0
|
||||
fi
|
||||
@@ -750,7 +999,7 @@ get_proxy_config_type() {
|
||||
|
||||
infer_proxy_config_type_from_fields() {
|
||||
local section="$1"
|
||||
local connection_type interface outbound_json selector_proxy_links urltest_proxy_links proxy_string
|
||||
local connection_type interface outbound_json selector_proxy_links urltest_proxy_links subscription_url proxy_string
|
||||
|
||||
config_get connection_type "$section" "connection_type"
|
||||
if [ "$connection_type" = "vpn" ]; then
|
||||
@@ -782,6 +1031,12 @@ infer_proxy_config_type_from_fields() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
config_get subscription_url "$section" "subscription_url"
|
||||
if [ -n "$subscription_url" ]; then
|
||||
echo "subscription"
|
||||
return 0
|
||||
fi
|
||||
|
||||
config_get proxy_string "$section" "proxy_string"
|
||||
if [ -n "$proxy_string" ]; then
|
||||
echo "url"
|
||||
@@ -1033,18 +1288,19 @@ check_requirements() {
|
||||
|
||||
_check_outbound_node() {
|
||||
local section="$1"
|
||||
local proxy_string interface outbound_json selector_proxy_links urltest_proxy_links
|
||||
local proxy_string interface outbound_json selector_proxy_links urltest_proxy_links subscription_url
|
||||
|
||||
rule_is_enabled "$section" || return 0
|
||||
|
||||
config_get proxy_string "$section" "proxy_string"
|
||||
config_get selector_proxy_links "$section" "selector_proxy_links"
|
||||
config_get urltest_proxy_links "$section" "urltest_proxy_links"
|
||||
config_get subscription_url "$section" "subscription_url"
|
||||
config_get outbound_json "$section" "outbound_json"
|
||||
config_get interface "$section" "interface"
|
||||
|
||||
if [ -n "$proxy_string" ] || [ -n "$selector_proxy_links" ] || [ -n "$urltest_proxy_links" ] ||
|
||||
[ -n "$outbound_json" ] || [ -n "$interface" ]; then
|
||||
[ -n "$subscription_url" ] || [ -n "$outbound_json" ] || [ -n "$interface" ]; then
|
||||
section_exists=0
|
||||
fi
|
||||
}
|
||||
@@ -1074,6 +1330,10 @@ start_main() {
|
||||
sleep 1
|
||||
|
||||
ensure_runtime_dirs
|
||||
if ! prepare_subscription_caches_for_startup; then
|
||||
log "Subscription caches are not ready. Aborted." "fatal"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# base
|
||||
route_table_rule_mark
|
||||
@@ -1517,6 +1777,20 @@ validate_plain_domain_ip_list_reference() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
validate_sing_box_duration_option() {
|
||||
local value="$1"
|
||||
local label="$2"
|
||||
|
||||
[ -z "$value" ] && return 0
|
||||
|
||||
if duration_to_seconds "$value" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Invalid duration value for $label: $value. Use sing-box duration format like 1d, 12h or 30m. Aborted." "fatal"
|
||||
exit 1
|
||||
}
|
||||
|
||||
ruleset_kind_from_reference_hint() {
|
||||
local reference="$1"
|
||||
|
||||
@@ -1635,7 +1909,7 @@ detect_inline_ruleset_reference_kind() {
|
||||
|
||||
process_validate_rule() {
|
||||
local section="$1"
|
||||
local action
|
||||
local action proxy_config_type urltest_check_interval subscription_update_interval
|
||||
|
||||
rule_is_enabled "$section" || return 0
|
||||
|
||||
@@ -1660,6 +1934,21 @@ process_validate_rule() {
|
||||
validate_rule_nfqws_opt "$section"
|
||||
fi
|
||||
|
||||
if [ "$action" = "proxy" ]; then
|
||||
proxy_config_type="$(get_proxy_config_type "$section")"
|
||||
case "$proxy_config_type" in
|
||||
urltest | subscription)
|
||||
urltest_check_interval="$(get_urltest_check_interval_for_rule "$section")"
|
||||
validate_sing_box_duration_option "$urltest_check_interval" "rule.$section.urltest_check_interval"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$proxy_config_type" = "subscription" ]; then
|
||||
subscription_update_interval="$(get_subscription_update_interval_for_rule "$section")"
|
||||
validate_sing_box_duration_option "$subscription_update_interval" "rule.$section.subscription_update_interval"
|
||||
fi
|
||||
fi
|
||||
|
||||
config_list_foreach "$section" "community_lists" validate_service
|
||||
config_list_foreach "$section" "rule_set" validate_ruleset_reference
|
||||
config_list_foreach "$section" "domain_ip_lists" validate_plain_domain_ip_list_reference
|
||||
@@ -2215,8 +2504,14 @@ build_list_update_cron_job() {
|
||||
printf '%s %s list_update_if_due %s\n' "$cron_schedule" "$PODKOP_BIN" "$PODKOP_LIST_UPDATE_CRON_MARKER"
|
||||
}
|
||||
|
||||
build_subscription_update_cron_job() {
|
||||
printf '* * * * * %s subscription_update_if_due %s\n' "$PODKOP_BIN" "$PODKOP_SUBSCRIPTION_UPDATE_CRON_MARKER"
|
||||
}
|
||||
|
||||
remove_cron_job() {
|
||||
(crontab -l 2>/dev/null | grep -Fv "$PODKOP_LIST_UPDATE_CRON_MARKER") | crontab -
|
||||
(crontab -l 2>/dev/null |
|
||||
grep -Fv "$PODKOP_LIST_UPDATE_CRON_MARKER" |
|
||||
grep -Fv "$PODKOP_SUBSCRIPTION_UPDATE_CRON_MARKER") | crontab -
|
||||
log "The cron job removed"
|
||||
}
|
||||
|
||||
@@ -2448,6 +2743,182 @@ list_update() {
|
||||
[ "$update_status" -eq 0 ] || return 1
|
||||
}
|
||||
|
||||
read_subscription_update_timestamp() {
|
||||
local section="$1"
|
||||
|
||||
sed -n '1p' "$(get_subscription_update_timestamp_path "$section")" 2>/dev/null
|
||||
}
|
||||
|
||||
write_subscription_update_timestamp() {
|
||||
local section="$1"
|
||||
local timestamp="$2"
|
||||
|
||||
mkdir -p "$PODKOP_SUBSCRIPTION_UPDATE_STATE_DIR"
|
||||
printf '%s\n' "$timestamp" > "$(get_subscription_update_timestamp_path "$section")"
|
||||
}
|
||||
|
||||
subscription_update_section_is_due() {
|
||||
local section="$1"
|
||||
local update_interval interval_seconds now last_run
|
||||
|
||||
update_interval="$(get_subscription_update_interval_for_rule "$section")"
|
||||
[ -n "$update_interval" ] || return 1
|
||||
|
||||
interval_seconds="$(duration_to_seconds "$update_interval")" || {
|
||||
log "Invalid subscription_update_interval value for rule '$section': $update_interval" "error"
|
||||
return 2
|
||||
}
|
||||
|
||||
now="$(date +%s 2>/dev/null)"
|
||||
last_run="$(read_subscription_update_timestamp "$section")"
|
||||
|
||||
case "$now" in
|
||||
'' | *[!0-9]*) return 2 ;;
|
||||
esac
|
||||
|
||||
case "$last_run" in
|
||||
'' | *[!0-9]*) last_run=0 ;;
|
||||
esac
|
||||
|
||||
[ "$last_run" -le 0 ] || [ $((now - last_run)) -ge "$interval_seconds" ]
|
||||
}
|
||||
|
||||
subscription_update_section() {
|
||||
local section="$1"
|
||||
local force="$2"
|
||||
local subscription_url subscription_json_path subscription_url_cache_path service_proxy_address update_result
|
||||
local outbounds_count now
|
||||
|
||||
rule_is_subscription_proxy "$section" || return 3
|
||||
|
||||
if [ "$force" -eq 0 ]; then
|
||||
subscription_update_section_is_due "$section"
|
||||
case "$?" in
|
||||
0) ;;
|
||||
1) return 3 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
config_get subscription_url "$section" "subscription_url"
|
||||
if [ -z "$subscription_url" ]; then
|
||||
echolog "Subscription URL is not set for rule '$section'"
|
||||
return 1
|
||||
fi
|
||||
|
||||
mkdir -p "$TMP_SUBSCRIPTION_FOLDER"
|
||||
subscription_json_path="$(get_subscription_json_path "$section")"
|
||||
subscription_url_cache_path="$(get_subscription_url_cache_path "$section")"
|
||||
service_proxy_address="$(get_service_proxy_address 2>/dev/null || echo '')"
|
||||
|
||||
echolog "Updating subscription for rule '$section'..."
|
||||
|
||||
if ! wait_for_subscription_connectivity "$section" "$subscription_url" "$service_proxy_address" 6 5 5; then
|
||||
echolog "Failed to download subscription for rule '$section'"
|
||||
return 1
|
||||
fi
|
||||
|
||||
download_subscription_into_cache \
|
||||
"$section" "$subscription_url" "$subscription_json_path" "$subscription_url_cache_path" "$service_proxy_address"
|
||||
update_result=$?
|
||||
|
||||
now="$(date +%s 2>/dev/null)"
|
||||
case "$now" in
|
||||
'' | *[!0-9]*) ;;
|
||||
*) write_subscription_update_timestamp "$section" "$now" ;;
|
||||
esac
|
||||
|
||||
case "$update_result" in
|
||||
0)
|
||||
outbounds_count=$(jq -r '[.outbounds[] | select(
|
||||
.type != "selector" and
|
||||
.type != "urltest" and
|
||||
.type != "direct" and
|
||||
.type != "dns" and
|
||||
.type != "block"
|
||||
)] | length' "$subscription_json_path" 2>/dev/null)
|
||||
echolog "Subscription updated for rule '$section': $outbounds_count outbounds"
|
||||
return 0
|
||||
;;
|
||||
2)
|
||||
echolog "Subscription for rule '$section' is unchanged"
|
||||
return 2
|
||||
;;
|
||||
*)
|
||||
echolog "Failed to download subscription for rule '$section'"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
subscription_update_handler() {
|
||||
local section="$1"
|
||||
local result
|
||||
|
||||
subscription_update_section "$section" "$SUBSCRIPTION_UPDATE_FORCE"
|
||||
result=$?
|
||||
|
||||
case "$result" in
|
||||
0) SUBSCRIPTION_UPDATED_SECTIONS=$((SUBSCRIPTION_UPDATED_SECTIONS + 1)) ;;
|
||||
1) SUBSCRIPTION_FAILED_SECTIONS=$((SUBSCRIPTION_FAILED_SECTIONS + 1)) ;;
|
||||
2) SUBSCRIPTION_UNCHANGED_SECTIONS=$((SUBSCRIPTION_UNCHANGED_SECTIONS + 1)) ;;
|
||||
3) ;;
|
||||
esac
|
||||
}
|
||||
|
||||
subscription_update_common() {
|
||||
local force="$1"
|
||||
local restart_rc
|
||||
|
||||
config_load "$PODKOP_CONFIG_NAME"
|
||||
ensure_runtime_dirs
|
||||
|
||||
SUBSCRIPTION_UPDATE_FORCE="$force"
|
||||
SUBSCRIPTION_UPDATED_SECTIONS=0
|
||||
SUBSCRIPTION_FAILED_SECTIONS=0
|
||||
SUBSCRIPTION_UNCHANGED_SECTIONS=0
|
||||
|
||||
config_foreach subscription_update_handler "rule"
|
||||
|
||||
if [ "$SUBSCRIPTION_UPDATED_SECTIONS" -eq 0 ]; then
|
||||
if [ "$SUBSCRIPTION_FAILED_SECTIONS" -gt 0 ]; then
|
||||
echolog "Subscription update finished with errors; keeping the last working cache"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$SUBSCRIPTION_UNCHANGED_SECTIONS" -gt 0 ]; then
|
||||
echolog "Subscription update completed: no changes detected"
|
||||
else
|
||||
echolog "No subscription rules are due for update"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
echolog "Restarting Podkop Plus to apply updated subscriptions..."
|
||||
restart
|
||||
restart_rc=$?
|
||||
if [ "$restart_rc" -ne 0 ]; then
|
||||
echolog "Subscription was downloaded, but Podkop Plus restart failed"
|
||||
return "$restart_rc"
|
||||
fi
|
||||
|
||||
if [ "$SUBSCRIPTION_FAILED_SECTIONS" -gt 0 ]; then
|
||||
echolog "Subscription update applied for changed rules; failed rules kept their previous cache"
|
||||
else
|
||||
echolog "Subscription update completed"
|
||||
fi
|
||||
}
|
||||
|
||||
subscription_update_if_due() {
|
||||
echolog "Starting due subscription update..."
|
||||
subscription_update_common 0
|
||||
}
|
||||
|
||||
subscription_update() {
|
||||
echolog "Starting subscription update..."
|
||||
subscription_update_common 1
|
||||
}
|
||||
|
||||
# sing-box funcs
|
||||
sing_box_configure_service() {
|
||||
local sing_box_enabled sing_box_user sing_box_config_path sing_box_conffile
|
||||
@@ -2521,6 +2992,88 @@ sing_box_configure_outbounds() {
|
||||
config_foreach configure_outbound_handler "rule"
|
||||
}
|
||||
|
||||
sing_box_get_unique_outbound_tag() {
|
||||
local config="$1"
|
||||
local base_tag="$2"
|
||||
local candidate="$base_tag"
|
||||
local tag_suffix=1
|
||||
|
||||
while printf '%s' "$config" | jq -e --arg tag "$candidate" '.outbounds[]? | select(.tag == $tag)' > /dev/null 2>&1; do
|
||||
candidate="${base_tag}-${tag_suffix}"
|
||||
tag_suffix=$((tag_suffix + 1))
|
||||
done
|
||||
|
||||
echo "$candidate"
|
||||
}
|
||||
|
||||
sing_box_build_subscription_country_groups() {
|
||||
local subscription_outbound_tags_json="$1"
|
||||
|
||||
printf '%s' "$subscription_outbound_tags_json" | jq -c '
|
||||
def is_regional_indicator: . >= 127462 and . <= 127487;
|
||||
def extract_country_flag:
|
||||
(. | explode) as $codepoints
|
||||
| if ($codepoints | length) >= 2
|
||||
and ($codepoints[0] | is_regional_indicator)
|
||||
and ($codepoints[1] | is_regional_indicator)
|
||||
then ($codepoints[0:2] | implode)
|
||||
else ""
|
||||
end;
|
||||
|
||||
(if type == "array" then . else [] end) as $tags
|
||||
| reduce $tags[] as $tag (
|
||||
{country_order: [], country_groups: {}, ungrouped: []};
|
||||
($tag | extract_country_flag) as $country_flag
|
||||
| if $country_flag == "" then
|
||||
.ungrouped += [$tag]
|
||||
else
|
||||
.country_groups[$country_flag] = ((.country_groups[$country_flag] // []) + [$tag])
|
||||
| if (.country_order | index($country_flag)) == null then
|
||||
.country_order += [$country_flag]
|
||||
else
|
||||
.
|
||||
end
|
||||
end
|
||||
)
|
||||
' 2>/dev/null
|
||||
}
|
||||
|
||||
is_truthy_option() {
|
||||
local value="$1"
|
||||
|
||||
case "$value" in
|
||||
1 | true | TRUE | True | on | ON | yes | YES | enabled | ENABLED)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
get_urltest_check_interval_for_config() {
|
||||
local section="$1"
|
||||
local urltest_check_interval
|
||||
|
||||
urltest_check_interval="$(get_urltest_check_interval_for_rule "$section")"
|
||||
if [ -n "$urltest_check_interval" ]; then
|
||||
printf '%s\n' "$urltest_check_interval"
|
||||
else
|
||||
printf '%s\n' "$SING_BOX_DISABLED_UPDATE_INTERVAL"
|
||||
fi
|
||||
}
|
||||
|
||||
get_urltest_idle_timeout_for_config() {
|
||||
local section="$1"
|
||||
local urltest_check_interval
|
||||
|
||||
urltest_check_interval="$(get_urltest_check_interval_for_rule "$section")"
|
||||
if [ -z "$urltest_check_interval" ]; then
|
||||
printf '%s\n' "$SING_BOX_DISABLED_UPDATE_INTERVAL"
|
||||
else
|
||||
printf '\n'
|
||||
fi
|
||||
}
|
||||
|
||||
configure_outbound_handler() {
|
||||
local section="$1"
|
||||
local action proxy_config_type
|
||||
@@ -2601,10 +3154,11 @@ configure_outbound_handler() {
|
||||
;;
|
||||
urltest)
|
||||
local urltest_proxy_links udp_over_tcp i urltest_tag selector_tag outbound_tag outbound_tags urltest_outbounds \
|
||||
selector_outbounds urltest_check_interval urltest_tolerance urltest_testing_url
|
||||
selector_outbounds urltest_check_interval urltest_idle_timeout urltest_tolerance urltest_testing_url
|
||||
config_get urltest_proxy_links "$section" "urltest_proxy_links"
|
||||
config_get udp_over_tcp "$section" "enable_udp_over_tcp"
|
||||
config_get urltest_check_interval "$section" "urltest_check_interval" "3m"
|
||||
urltest_check_interval="$(get_urltest_check_interval_for_config "$section")"
|
||||
urltest_idle_timeout="$(get_urltest_idle_timeout_for_config "$section")"
|
||||
config_get urltest_tolerance "$section" "urltest_tolerance" 50
|
||||
config_get urltest_testing_url "$section" "urltest_testing_url" "https://www.gstatic.com/generate_204"
|
||||
|
||||
@@ -2630,10 +3184,177 @@ configure_outbound_handler() {
|
||||
urltest_outbounds="$(comma_string_to_json_array "$outbound_tags")"
|
||||
selector_outbounds="$(comma_string_to_json_array "$outbound_tags,$urltest_tag")"
|
||||
config="$(sing_box_cm_add_urltest_outbound "$config" "$urltest_tag" "$urltest_outbounds" \
|
||||
"$urltest_testing_url" "$urltest_check_interval" "$urltest_tolerance")"
|
||||
"$urltest_testing_url" "$urltest_check_interval" "$urltest_tolerance" "$urltest_idle_timeout")"
|
||||
config="$(sing_box_cm_add_selector_outbound "$config" "$selector_tag" "$selector_outbounds" "$urltest_tag")"
|
||||
return 0
|
||||
;;
|
||||
subscription)
|
||||
local subscription_url subscription_json_path subscription_url_cache_path cached_subscription_url \
|
||||
should_download had_usable_cache service_proxy_address urltest_tag selector_tag urltest_outbounds \
|
||||
selector_outbounds urltest_check_interval urltest_idle_timeout urltest_tolerance urltest_testing_url \
|
||||
subscription_group_by_countries_raw subscription_group_by_countries subscription_outbound_tags_json \
|
||||
update_result
|
||||
|
||||
config_get subscription_url "$section" "subscription_url"
|
||||
urltest_check_interval="$(get_urltest_check_interval_for_config "$section")"
|
||||
urltest_idle_timeout="$(get_urltest_idle_timeout_for_config "$section")"
|
||||
config_get urltest_tolerance "$section" "urltest_tolerance" 50
|
||||
config_get urltest_testing_url "$section" "urltest_testing_url" "https://www.gstatic.com/generate_204"
|
||||
config_get subscription_group_by_countries_raw "$section" "subscription_group_by_countries" ""
|
||||
if [ -z "$subscription_group_by_countries_raw" ]; then
|
||||
config_get subscription_group_by_countries_raw "$section" "group_by_countries" ""
|
||||
fi
|
||||
|
||||
if is_truthy_option "$subscription_group_by_countries_raw"; then
|
||||
subscription_group_by_countries=1
|
||||
else
|
||||
subscription_group_by_countries=0
|
||||
fi
|
||||
|
||||
if [ -z "$subscription_url" ]; then
|
||||
log "Subscription URL is not set for rule '$section'. Aborted." "fatal"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$TMP_SUBSCRIPTION_FOLDER"
|
||||
subscription_json_path="$(get_subscription_json_path "$section")"
|
||||
subscription_url_cache_path="$(get_subscription_url_cache_path "$section")"
|
||||
cached_subscription_url=""
|
||||
should_download=0
|
||||
had_usable_cache=0
|
||||
|
||||
if subscription_cache_is_usable "$subscription_json_path"; then
|
||||
had_usable_cache=1
|
||||
else
|
||||
rm -f "$subscription_json_path"
|
||||
should_download=1
|
||||
fi
|
||||
|
||||
if [ -f "$subscription_url_cache_path" ]; then
|
||||
cached_subscription_url="$(cat "$subscription_url_cache_path" 2>/dev/null)"
|
||||
fi
|
||||
|
||||
if [ "$cached_subscription_url" != "$subscription_url" ]; then
|
||||
if [ -n "$cached_subscription_url" ]; then
|
||||
log "Subscription URL changed for rule '$section'" "warn"
|
||||
fi
|
||||
|
||||
if [ "$had_usable_cache" -eq 0 ]; then
|
||||
should_download=1
|
||||
else
|
||||
log "Using cached subscription for rule '$section' until a fresh download succeeds" "warn"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$should_download" -eq 1 ]; then
|
||||
log "Downloading subscription for rule '$section'"
|
||||
service_proxy_address="$(get_service_proxy_address 2>/dev/null || echo '')"
|
||||
|
||||
if wait_for_subscription_connectivity "$section" "$subscription_url" "$service_proxy_address" 6 5 5; then
|
||||
download_subscription_into_cache \
|
||||
"$section" "$subscription_url" "$subscription_json_path" "$subscription_url_cache_path" "$service_proxy_address"
|
||||
update_result="$?"
|
||||
else
|
||||
update_result=1
|
||||
fi
|
||||
|
||||
case "$update_result" in
|
||||
0 | 2) ;;
|
||||
*)
|
||||
if [ "$had_usable_cache" -eq 1 ]; then
|
||||
log "Failed to refresh subscription for rule '$section', continuing with cached data" "warn"
|
||||
else
|
||||
log "Failed to download subscription for rule '$section'. Aborted." "fatal"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if ! sing_box_cf_add_subscription_outbounds "$config" "$section" "$subscription_json_path" > /dev/null; then
|
||||
log "No proxy outbounds found in subscription for rule '$section'. Aborted." "fatal"
|
||||
exit 1
|
||||
fi
|
||||
config="$SING_BOX_CF_LAST_CONFIG"
|
||||
|
||||
if [ -z "$SUBSCRIPTION_OUTBOUND_TAGS" ]; then
|
||||
log "No proxy outbounds found in subscription for rule '$section'. Aborted." "fatal"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
subscription_outbound_tags_json="$SUBSCRIPTION_OUTBOUND_TAGS_JSON"
|
||||
if [ -z "$subscription_outbound_tags_json" ] || [ "$subscription_outbound_tags_json" = "[]" ]; then
|
||||
subscription_outbound_tags_json="$(comma_string_to_json_array "$SUBSCRIPTION_OUTBOUND_TAGS")"
|
||||
fi
|
||||
|
||||
selector_tag="$(get_outbound_tag_by_section "$section")"
|
||||
|
||||
if [ "$subscription_group_by_countries" -eq 1 ]; then
|
||||
local grouping_json country_flag country_group_outbounds country_group_tag selector_outbounds_json \
|
||||
selector_default ungrouped_outbounds_json
|
||||
|
||||
grouping_json="$(sing_box_build_subscription_country_groups "$subscription_outbound_tags_json")"
|
||||
if [ -z "$grouping_json" ]; then
|
||||
log "Failed to build grouped subscription outbounds for rule '$section'. Aborted." "fatal"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
selector_outbounds_json="[]"
|
||||
for country_flag in $(echo "$grouping_json" | jq -r '.country_order[]' 2>/dev/null); do
|
||||
country_group_outbounds="$(echo "$grouping_json" | jq -c --arg country_flag "$country_flag" '.country_groups[$country_flag] // []' 2>/dev/null)"
|
||||
if [ -z "$country_group_outbounds" ] || [ "$country_group_outbounds" = "[]" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
country_group_tag="$(sing_box_get_unique_outbound_tag "$config" "$country_flag Fastest")"
|
||||
config="$(sing_box_cm_add_urltest_outbound "$config" "$country_group_tag" "$country_group_outbounds" \
|
||||
"$urltest_testing_url" "$urltest_check_interval" "$urltest_tolerance" "$urltest_idle_timeout")"
|
||||
|
||||
selector_outbounds_json=$(
|
||||
printf '%s' "$selector_outbounds_json" | jq -ac --arg tag "$country_group_tag" '. + [$tag]' 2>/dev/null
|
||||
)
|
||||
done
|
||||
|
||||
[ -n "$selector_outbounds_json" ] || selector_outbounds_json="[]"
|
||||
|
||||
ungrouped_outbounds_json="$(echo "$grouping_json" | jq -c '.ungrouped // []' 2>/dev/null)"
|
||||
if [ -n "$ungrouped_outbounds_json" ] && [ "$ungrouped_outbounds_json" != "[]" ]; then
|
||||
selector_outbounds_json=$(
|
||||
jq -acn --argjson selector "$selector_outbounds_json" --argjson ungrouped "$ungrouped_outbounds_json" \
|
||||
'$selector + $ungrouped' 2>/dev/null
|
||||
)
|
||||
fi
|
||||
|
||||
if [ -z "$selector_outbounds_json" ] || [ "$selector_outbounds_json" = "[]" ]; then
|
||||
log "No selector outbounds available after grouping subscription outbounds for rule '$section'. Aborted." "fatal"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
selector_default="$(echo "$selector_outbounds_json" | jq -r '.[0] // ""' 2>/dev/null)"
|
||||
if [ -z "$selector_default" ] || [ "$selector_default" = "null" ]; then
|
||||
log "Unable to determine default selector outbound for rule '$section'. Aborted." "fatal"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
config="$(sing_box_cm_add_selector_outbound "$config" "$selector_tag" "$selector_outbounds_json" "$selector_default" "true")"
|
||||
else
|
||||
urltest_tag="$(get_outbound_tag_by_section "$section-urltest")"
|
||||
urltest_outbounds="$subscription_outbound_tags_json"
|
||||
selector_outbounds=$(
|
||||
jq -acn --argjson outbounds "$subscription_outbound_tags_json" --arg tag "$urltest_tag" \
|
||||
'$outbounds + [$tag]' 2>/dev/null
|
||||
)
|
||||
if [ -z "$selector_outbounds" ]; then
|
||||
log "Failed to build selector outbounds for subscription rule '$section'. Aborted." "fatal"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
config="$(sing_box_cm_add_urltest_outbound "$config" "$urltest_tag" "$urltest_outbounds" \
|
||||
"$urltest_testing_url" "$urltest_check_interval" "$urltest_tolerance" "$urltest_idle_timeout")"
|
||||
config="$(sing_box_cm_add_selector_outbound "$config" "$selector_tag" "$selector_outbounds" "$urltest_tag" "true")"
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
interface)
|
||||
local interface_name domain_resolver_enabled domain_resolver_dns_type domain_resolver_dns_server \
|
||||
domain_resolver_dns_server_address outbound_tag domain_resolver_tag dns_domain_resolver
|
||||
@@ -4379,6 +5100,7 @@ show_config() {
|
||||
tmp_config=$(mktemp)
|
||||
|
||||
sed -e 's/\(option proxy_string\).*/\1 '\''MASKED'\''/g' \
|
||||
-e 's/\(option subscription_url\).*/\1 '\''MASKED'\''/g' \
|
||||
-e '/option outbound_json/,/^}/c\ option outbound_json '\''MASKED'\''' \
|
||||
-e 's/\(list urltest_proxy_links\).*/\1 '\''MASKED'\''/g' \
|
||||
-e 's/\(list selector_proxy_links\).*/\1 '\''MASKED'\''/g' \
|
||||
@@ -5574,6 +6296,9 @@ Available commands:
|
||||
main Run main Podkop Plus process
|
||||
list_update Update remote lists
|
||||
list_update_if_due Update remote lists only when the configured interval has elapsed
|
||||
subscription_update Update subscription proxies
|
||||
subscription_update_if_due
|
||||
Update subscription proxies only when per-rule intervals have elapsed
|
||||
check_proxy Check proxy connectivity
|
||||
check_nft Check NFT rules
|
||||
check_nft_rules Check NFT rules status
|
||||
@@ -5632,6 +6357,12 @@ list_update)
|
||||
list_update_if_due)
|
||||
list_update_if_due
|
||||
;;
|
||||
subscription_update)
|
||||
subscription_update
|
||||
;;
|
||||
subscription_update_if_due)
|
||||
subscription_update_if_due
|
||||
;;
|
||||
check_proxy)
|
||||
check_proxy
|
||||
;;
|
||||
|
||||
@@ -20,6 +20,7 @@ CHECK_PROXY_IP_DOMAIN="ip.podkop.fyi"
|
||||
FAKEIP_TEST_DOMAIN="fakeip.podkop.fyi"
|
||||
TMP_SING_BOX_FOLDER="/tmp/sing-box"
|
||||
TMP_RULESET_FOLDER="$TMP_SING_BOX_FOLDER/rulesets"
|
||||
TMP_SUBSCRIPTION_FOLDER="$TMP_SING_BOX_FOLDER/subscriptions"
|
||||
CLOUDFLARE_OCTETS="8.47 162.159 188.114" # Endpoints https://github.com/ampetelin/warp-endpoint-checker
|
||||
JQ_REQUIRED_VERSION="1.7.1"
|
||||
COREUTILS_BASE64_REQUIRED_VERSION="9.7"
|
||||
|
||||
@@ -275,6 +275,149 @@ download_to_file() {
|
||||
done
|
||||
}
|
||||
|
||||
get_device_model() {
|
||||
local model=""
|
||||
|
||||
if [ -f /tmp/sysinfo/model ]; then
|
||||
model="$(cat /tmp/sysinfo/model 2>/dev/null)"
|
||||
fi
|
||||
|
||||
echo "${model:-OpenWrt Router}"
|
||||
}
|
||||
|
||||
get_kernel_version() {
|
||||
uname -r
|
||||
}
|
||||
|
||||
get_sing_box_version() {
|
||||
local version=""
|
||||
|
||||
if command -v sing-box >/dev/null 2>&1; then
|
||||
version="$(sing-box version 2>/dev/null | head -1 | awk '{print $NF}')"
|
||||
fi
|
||||
|
||||
echo "${version:-1.0}"
|
||||
}
|
||||
|
||||
generate_hwid() {
|
||||
local mac="" model="" raw_hash=""
|
||||
|
||||
if [ -f /sys/class/net/eth0/address ]; then
|
||||
mac="$(cat /sys/class/net/eth0/address 2>/dev/null)"
|
||||
elif [ -f /sys/class/net/br-lan/address ]; then
|
||||
mac="$(cat /sys/class/net/br-lan/address 2>/dev/null)"
|
||||
fi
|
||||
|
||||
model="$(get_device_model)"
|
||||
raw_hash="$(printf '%s-%s' "$mac" "$model" | md5sum | cut -c1-16)"
|
||||
|
||||
printf '%s-%s-%s-%s' \
|
||||
"$(echo "$raw_hash" | cut -c1-4)" \
|
||||
"$(echo "$raw_hash" | cut -c5-8)" \
|
||||
"$(echo "$raw_hash" | cut -c9-12)" \
|
||||
"$(echo "$raw_hash" | cut -c13-16)"
|
||||
}
|
||||
|
||||
download_subscription() {
|
||||
local url="$1"
|
||||
local filepath="$2"
|
||||
local http_proxy_address="$3"
|
||||
local retries="${4:-3}"
|
||||
local wait="${5:-2}"
|
||||
local timeout="${6:-10}"
|
||||
local tmpfile attempt
|
||||
|
||||
tmpfile="${filepath}.part.$$"
|
||||
rm -f "$tmpfile"
|
||||
|
||||
for attempt in $(seq 1 "$retries"); do
|
||||
if [ -n "$http_proxy_address" ]; then
|
||||
http_proxy="http://$http_proxy_address" https_proxy="http://$http_proxy_address" \
|
||||
wget -T "$timeout" -O "$tmpfile" \
|
||||
--header "User-Agent: singbox/$(get_sing_box_version)" \
|
||||
--header "X-HWID: $(generate_hwid)" \
|
||||
--header "X-Device-OS: OpenWrt Linux" \
|
||||
--header "X-Device-Model: $(get_device_model)" \
|
||||
--header "X-Ver-OS: $(get_kernel_version)" \
|
||||
--header "Accept-Language: ru-RU,en,*" \
|
||||
--header "X-Device-Locale: EN" \
|
||||
"$url"
|
||||
else
|
||||
wget -T "$timeout" -O "$tmpfile" \
|
||||
--header "User-Agent: singbox/$(get_sing_box_version)" \
|
||||
--header "X-HWID: $(generate_hwid)" \
|
||||
--header "X-Device-OS: OpenWrt Linux" \
|
||||
--header "X-Device-Model: $(get_device_model)" \
|
||||
--header "X-Ver-OS: $(get_kernel_version)" \
|
||||
--header "Accept-Language: ru-RU,en,*" \
|
||||
--header "X-Device-Locale: EN" \
|
||||
"$url"
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ] && [ -s "$tmpfile" ]; then
|
||||
mv "$tmpfile" "$filepath"
|
||||
return 0
|
||||
fi
|
||||
|
||||
rm -f "$tmpfile"
|
||||
log "Attempt $attempt/$retries to download subscription failed" "warn"
|
||||
sleep "$wait"
|
||||
done
|
||||
|
||||
rm -f "$tmpfile"
|
||||
return 1
|
||||
}
|
||||
|
||||
check_subscription_connectivity() {
|
||||
local url="$1"
|
||||
local http_proxy_address="$2"
|
||||
local retries="${3:-3}"
|
||||
local wait="${4:-2}"
|
||||
local timeout="${5:-5}"
|
||||
local attempt
|
||||
|
||||
for attempt in $(seq 1 "$retries"); do
|
||||
if [ -n "$http_proxy_address" ]; then
|
||||
http_proxy="http://$http_proxy_address" https_proxy="http://$http_proxy_address" \
|
||||
wget -q -T "$timeout" -O /dev/null \
|
||||
--header "User-Agent: singbox/$(get_sing_box_version)" \
|
||||
--header "X-HWID: $(generate_hwid)" \
|
||||
--header "X-Device-OS: OpenWrt Linux" \
|
||||
--header "X-Device-Model: $(get_device_model)" \
|
||||
--header "X-Ver-OS: $(get_kernel_version)" \
|
||||
--header "Accept-Language: ru-RU,en,*" \
|
||||
--header "X-Device-Locale: EN" \
|
||||
"$url" && return 0
|
||||
else
|
||||
wget -q -T "$timeout" -O /dev/null \
|
||||
--header "User-Agent: singbox/$(get_sing_box_version)" \
|
||||
--header "X-HWID: $(generate_hwid)" \
|
||||
--header "X-Device-OS: OpenWrt Linux" \
|
||||
--header "X-Device-Model: $(get_device_model)" \
|
||||
--header "X-Ver-OS: $(get_kernel_version)" \
|
||||
--header "Accept-Language: ru-RU,en,*" \
|
||||
--header "X-Device-Locale: EN" \
|
||||
"$url" && return 0
|
||||
fi
|
||||
|
||||
[ "$attempt" -lt "$retries" ] && sleep "$wait"
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
validate_subscription_file() {
|
||||
local filepath="$1"
|
||||
|
||||
[ -s "$filepath" ] || return 1
|
||||
|
||||
jq -e '
|
||||
type == "object" and
|
||||
(.outbounds | type == "array") and
|
||||
((.outbounds | length) > 0)
|
||||
' "$filepath" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
# Converts Windows-style line endings (CRLF) to Unix-style (LF)
|
||||
convert_crlf_to_lf() {
|
||||
local filepath="$1"
|
||||
|
||||
@@ -328,3 +328,129 @@ sing_box_cf_add_single_key_reject_rule() {
|
||||
|
||||
echo "$config"
|
||||
}
|
||||
|
||||
sing_box_cf_add_subscription_outbounds() {
|
||||
local config="$1"
|
||||
local section="$2"
|
||||
local subscription_json_path="$3"
|
||||
|
||||
SUBSCRIPTION_OUTBOUND_TAGS=""
|
||||
SUBSCRIPTION_OUTBOUND_TAGS_JSON="[]"
|
||||
SUBSCRIPTION_OUTBOUND_NAMES=""
|
||||
SING_BOX_CF_LAST_CONFIG="$config"
|
||||
|
||||
if [ ! -f "$subscription_json_path" ]; then
|
||||
log "Subscription JSON file not found: $subscription_json_path" "error"
|
||||
echo "$config"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local outbounds_count
|
||||
outbounds_count=$(jq -r '[.outbounds[] | select(
|
||||
.type != "selector" and
|
||||
.type != "urltest" and
|
||||
.type != "direct" and
|
||||
.type != "dns" and
|
||||
.type != "block"
|
||||
)] | length' "$subscription_json_path" 2>/dev/null)
|
||||
|
||||
if [ -z "$outbounds_count" ] || [ "$outbounds_count" -eq 0 ]; then
|
||||
log "No proxy outbounds found in subscription JSON" "error"
|
||||
echo "$config"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Found $outbounds_count proxy outbounds in subscription" "info"
|
||||
|
||||
local i added_count
|
||||
local outbound_json display_name outbound_tag outbound_type outbound_tls_enabled preferred_tag base_tag tag_suffix
|
||||
i=1
|
||||
added_count=0
|
||||
|
||||
while [ "$i" -le "$outbounds_count" ]; do
|
||||
outbound_json=$(jq -c "[.outbounds[] | select(
|
||||
.type != \"selector\" and
|
||||
.type != \"urltest\" and
|
||||
.type != \"direct\" and
|
||||
.type != \"dns\" and
|
||||
.type != \"block\"
|
||||
)][$i - 1]" "$subscription_json_path" 2>/dev/null)
|
||||
|
||||
if [ -z "$outbound_json" ] || [ "$outbound_json" = "null" ]; then
|
||||
i=$((i + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
display_name=$(echo "$outbound_json" | jq -r '.remark // .tag // "server-'"$i"'"' 2>/dev/null)
|
||||
outbound_type=$(echo "$outbound_json" | jq -r '.type // ""' 2>/dev/null)
|
||||
outbound_tls_enabled=$(echo "$outbound_json" | jq -r '.tls.enabled // false' 2>/dev/null)
|
||||
|
||||
if [ "$outbound_type" = "shadowsocks" ] && [ "$outbound_tls_enabled" = "true" ]; then
|
||||
log "Skip unsupported Shadowsocks outbound with tls: '$display_name'" "warn"
|
||||
i=$((i + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
preferred_tag=$(echo "$outbound_json" | jq -r '.tag // .remark // "server-'"$i"'"' 2>/dev/null)
|
||||
if [ -z "$preferred_tag" ] || [ "$preferred_tag" = "null" ]; then
|
||||
preferred_tag="server-$i"
|
||||
fi
|
||||
|
||||
base_tag="$preferred_tag"
|
||||
outbound_tag="$base_tag"
|
||||
tag_suffix=1
|
||||
while printf '%s' "$config" | jq -e --arg tag "$outbound_tag" '.outbounds[]? | select(.tag == $tag)' > /dev/null 2>&1; do
|
||||
outbound_tag="${base_tag}-${tag_suffix}"
|
||||
tag_suffix=$((tag_suffix + 1))
|
||||
done
|
||||
|
||||
local clean_outbound updated_config validation_tmp
|
||||
clean_outbound=$(echo "$outbound_json" | jq -c 'del(.tag) | del(.remark)' 2>/dev/null)
|
||||
updated_config=$(sing_box_cm_add_raw_outbound "$config" "$outbound_tag" "$clean_outbound" 2>/dev/null)
|
||||
|
||||
if [ -z "$updated_config" ]; then
|
||||
log "Skip invalid outbound from subscription: '$display_name'" "warn"
|
||||
i=$((i + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
validation_tmp="$(mktemp)"
|
||||
sing_box_cm_save_config_to_file "$updated_config" "$validation_tmp"
|
||||
if ! sing-box -c "$validation_tmp" check > /dev/null 2>&1; then
|
||||
rm -f "$validation_tmp"
|
||||
log "Skip unsupported outbound for current sing-box: '$display_name'" "warn"
|
||||
i=$((i + 1))
|
||||
continue
|
||||
fi
|
||||
rm -f "$validation_tmp"
|
||||
|
||||
config="$updated_config"
|
||||
|
||||
if [ -z "$SUBSCRIPTION_OUTBOUND_TAGS" ]; then
|
||||
SUBSCRIPTION_OUTBOUND_TAGS="$outbound_tag"
|
||||
else
|
||||
SUBSCRIPTION_OUTBOUND_TAGS="$SUBSCRIPTION_OUTBOUND_TAGS,$outbound_tag"
|
||||
fi
|
||||
|
||||
SUBSCRIPTION_OUTBOUND_TAGS_JSON=$(
|
||||
printf '%s' "$SUBSCRIPTION_OUTBOUND_TAGS_JSON" | jq -ac --arg tag "$outbound_tag" '. + [$tag]' 2>/dev/null
|
||||
)
|
||||
if [ -z "$SUBSCRIPTION_OUTBOUND_TAGS_JSON" ]; then
|
||||
SUBSCRIPTION_OUTBOUND_TAGS_JSON="[]"
|
||||
fi
|
||||
|
||||
if [ -z "$SUBSCRIPTION_OUTBOUND_NAMES" ]; then
|
||||
SUBSCRIPTION_OUTBOUND_NAMES="$display_name"
|
||||
else
|
||||
SUBSCRIPTION_OUTBOUND_NAMES="$(printf '%s\n%s' "$SUBSCRIPTION_OUTBOUND_NAMES" "$display_name")"
|
||||
fi
|
||||
|
||||
added_count=$((added_count + 1))
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
log "Added $added_count subscription outbounds for rule '$section'" "info"
|
||||
SING_BOX_CF_LAST_CONFIG="$config"
|
||||
|
||||
echo "$config"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user