Update On Sat Mar 8 19:28:42 CET 2025

This commit is contained in:
github-action[bot]
2025-03-08 19:28:43 +01:00
parent fa938fb553
commit bf5deb3b6d
61 changed files with 2575 additions and 1157 deletions
+1
View File
@@ -935,3 +935,4 @@ Update On Tue Mar 4 19:36:12 CET 2025
Update On Wed Mar 5 19:38:24 CET 2025
Update On Thu Mar 6 19:35:59 CET 2025
Update On Fri Mar 7 19:34:47 CET 2025
Update On Sat Mar 8 19:28:33 CET 2025
+18 -18
View File
@@ -1541,9 +1541,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]]
name = "bytes"
version = "1.10.0"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
dependencies = [
"serde",
]
@@ -1644,7 +1644,7 @@ checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924"
dependencies = [
"camino",
"cargo-platform",
"semver 1.0.25",
"semver 1.0.26",
"serde",
"serde_json",
"thiserror 2.0.12",
@@ -1988,7 +1988,7 @@ dependencies = [
"rust-i18n",
"rustc_version",
"seahash",
"semver 1.0.25",
"semver 1.0.26",
"serde",
"serde_json",
"serde_yaml_ng",
@@ -2914,9 +2914,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "dyn-clone"
version = "1.0.18"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feeef44e73baff3a26d371801df019877a9866a8c493d315ab00177843314f35"
checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005"
[[package]]
name = "earcutr"
@@ -5039,9 +5039,9 @@ dependencies = [
[[package]]
name = "interprocess"
version = "2.2.2"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "894148491d817cb36b6f778017b8ac46b17408d522dd90f539d677ea938362eb"
checksum = "d941b405bd2322993887859a8ee6ac9134945a24ec5ec763a8a962fc64dfec2d"
dependencies = [
"doctest-file",
"futures-core",
@@ -5530,7 +5530,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
dependencies = [
"cfg-if",
"windows-targets 0.52.6",
"windows-targets 0.48.5",
]
[[package]]
@@ -8909,7 +8909,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver 1.0.25",
"semver 1.0.26",
]
[[package]]
@@ -9156,9 +9156,9 @@ dependencies = [
[[package]]
name = "semver"
version = "1.0.25"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03"
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
dependencies = [
"serde",
]
@@ -10005,7 +10005,7 @@ dependencies = [
"rust_decimal",
"rustls",
"rustls-pki-types",
"semver 1.0.25",
"semver 1.0.26",
"serde",
"serde-content",
"serde_json",
@@ -10087,7 +10087,7 @@ dependencies = [
"rust-stemmers",
"rust_decimal",
"scrypt",
"semver 1.0.25",
"semver 1.0.26",
"serde",
"serde-content",
"serde_json",
@@ -10418,7 +10418,7 @@ dependencies = [
"heck 0.5.0",
"json-patch",
"schemars",
"semver 1.0.25",
"semver 1.0.26",
"serde",
"serde_json",
"tauri-utils",
@@ -10441,7 +10441,7 @@ dependencies = [
"png",
"proc-macro2",
"quote",
"semver 1.0.25",
"semver 1.0.26",
"serde",
"serde_json",
"sha2 0.10.8",
@@ -10655,7 +10655,7 @@ dependencies = [
"osakit",
"percent-encoding",
"reqwest",
"semver 1.0.25",
"semver 1.0.26",
"serde",
"serde_json",
"tar",
@@ -10767,7 +10767,7 @@ dependencies = [
"quote",
"regex",
"schemars",
"semver 1.0.25",
"semver 1.0.26",
"serde",
"serde-untagged",
"serde_json",
@@ -46,7 +46,7 @@
"react-split-grid": "1.0.4",
"react-use": "17.6.0",
"swr": "2.3.3",
"virtua": "0.40.1",
"virtua": "0.40.3",
"vite-bundle-visualizer": "1.2.1"
},
"devDependencies": {
@@ -79,7 +79,7 @@
"filesize": "10.1.6",
"meta-json-schema": "1.19.3",
"monaco-yaml": "5.3.1",
"nanoid": "5.1.2",
"nanoid": "5.1.3",
"sass-embedded": "1.85.1",
"shiki": "2.5.0",
"unplugin-auto-import": "19.1.1",
+1 -1
View File
@@ -65,7 +65,7 @@
"@tauri-apps/cli": "2.3.1",
"@types/fs-extra": "11.0.4",
"@types/lodash-es": "4.17.12",
"@types/node": "22.13.9",
"@types/node": "22.13.10",
"@typescript-eslint/eslint-plugin": "8.25.0",
"@typescript-eslint/parser": "8.25.0",
"autoprefixer": "10.4.20",
+80 -80
View File
@@ -20,7 +20,7 @@ importers:
devDependencies:
'@commitlint/cli':
specifier: 19.7.1
version: 19.7.1(@types/node@22.13.9)(typescript@5.8.2)
version: 19.7.1(@types/node@22.13.10)(typescript@5.8.2)
'@commitlint/config-conventional':
specifier: 19.7.1
version: 19.7.1
@@ -43,8 +43,8 @@ importers:
specifier: 4.17.12
version: 4.17.12
'@types/node':
specifier: 22.13.9
version: 22.13.9
specifier: 22.13.10
version: 22.13.10
'@typescript-eslint/eslint-plugin':
specifier: 8.25.0
version: 8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)
@@ -104,7 +104,7 @@ importers:
version: 16.0.0
knip:
specifier: 5.45.0
version: 5.45.0(@types/node@22.13.9)(typescript@5.8.2)
version: 5.45.0(@types/node@22.13.10)(typescript@5.8.2)
lint-staged:
specifier: 15.4.3
version: 15.4.3
@@ -317,8 +317,8 @@ importers:
specifier: 2.3.3
version: 2.3.3(react@19.0.0)
virtua:
specifier: 0.40.1
version: 0.40.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
specifier: 0.40.3
version: 0.40.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
vite-bundle-visualizer:
specifier: 1.2.1
version: 1.2.1(rollup@4.34.3)
@@ -349,7 +349,7 @@ importers:
version: 1.112.18(@tanstack/react-router@1.112.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(csstype@3.1.3)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@tanstack/router-plugin':
specifier: 1.112.19
version: 1.112.19(@tanstack/react-router@1.112.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
version: 1.112.19(@tanstack/react-router@1.112.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
'@tauri-apps/plugin-clipboard-manager':
specifier: 2.2.1
version: 2.2.1
@@ -385,13 +385,13 @@ importers:
version: 13.12.2
'@vitejs/plugin-legacy':
specifier: 6.0.2
version: 6.0.2(terser@5.36.0)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
version: 6.0.2(terser@5.36.0)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
'@vitejs/plugin-react':
specifier: 4.3.4
version: 4.3.4(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
version: 4.3.4(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
'@vitejs/plugin-react-swc':
specifier: 3.8.0
version: 3.8.0(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
version: 3.8.0(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
change-case:
specifier: 5.4.4
version: 5.4.4
@@ -411,8 +411,8 @@ importers:
specifier: 5.3.1
version: 5.3.1(monaco-editor@0.52.2)
nanoid:
specifier: 5.1.2
version: 5.1.2
specifier: 5.1.3
version: 5.1.3
sass-embedded:
specifier: 1.85.1
version: 1.85.1
@@ -430,19 +430,19 @@ importers:
version: 13.12.0
vite:
specifier: 6.2.1
version: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
version: 6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite-plugin-html:
specifier: 3.2.2
version: 3.2.2(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
version: 3.2.2(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
vite-plugin-sass-dts:
specifier: 1.3.31
version: 1.3.31(postcss@8.5.3)(prettier@3.5.2)(sass-embedded@1.85.1)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
version: 1.3.31(postcss@8.5.3)(prettier@3.5.2)(sass-embedded@1.85.1)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
vite-plugin-svgr:
specifier: 4.3.0
version: 4.3.0(rollup@4.34.3)(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
version: 4.3.0(rollup@4.34.3)(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
vite-tsconfig-paths:
specifier: 5.1.4
version: 5.1.4(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
version: 5.1.4(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
zod:
specifier: 3.24.2
version: 3.24.2
@@ -478,7 +478,7 @@ importers:
version: 19.0.10
'@vitejs/plugin-react':
specifier: 4.3.4
version: 4.3.4(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
version: 4.3.4(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
ahooks:
specifier: 3.8.4
version: 3.8.4(react@19.0.0)
@@ -508,10 +508,10 @@ importers:
version: 4.0.9
vite:
specifier: 6.2.1
version: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
version: 6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite-tsconfig-paths:
specifier: 5.1.4
version: 5.1.4(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
version: 5.1.4(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
devDependencies:
'@emotion/react':
specifier: 11.14.0
@@ -536,7 +536,7 @@ importers:
version: 5.1.0(typescript@5.8.2)
vite-plugin-dts:
specifier: 4.5.3
version: 4.5.3(@types/node@22.13.9)(rollup@4.34.3)(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
version: 4.5.3(@types/node@22.13.10)(rollup@4.34.3)(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))
scripts:
dependencies:
@@ -3122,8 +3122,8 @@ packages:
'@types/node@22.10.1':
resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==}
'@types/node@22.13.9':
resolution: {integrity: sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==}
'@types/node@22.13.10':
resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==}
'@types/parse-json@4.0.2':
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
@@ -6069,8 +6069,8 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
nanoid@5.1.2:
resolution: {integrity: sha512-b+CiXQCNMUGe0Ri64S9SXFcP9hogjAJ2Rd6GdVxhPLRm7mhGaM7VgOvCAJ1ZshfHbqVDI3uqTI5C8/GaKuLI7g==}
nanoid@5.1.3:
resolution: {integrity: sha512-zAbEOEr7u2CbxwoMRlz/pNSpRP0FdAU4pRaYunCdEezWohXFs+a0Xw7RfkKaezMsmSM1vttcLthJtwRnVtOfHQ==}
engines: {node: ^18 || >=20}
hasBin: true
@@ -7843,8 +7843,8 @@ packages:
vfile@6.0.1:
resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==}
virtua@0.40.1:
resolution: {integrity: sha512-xZcbBduTv7ajBqCQFkInRdcAU1TK/Os9ljHpMUcAOVVGY1aezJSW9PXr92+TwBfFm+DTvxV1CXcViWzl7UXaNA==}
virtua@0.40.3:
resolution: {integrity: sha512-rfl6VohBFoT0U64fVdOGag2p0D+YZbki7HQ5bjFZObStWBaWjjataIHFDjl4KuSr3yHBMgGd/+Va7W4Z2Y0LRg==}
peerDependencies:
react: '>=16.14.0'
react-dom: '>=16.14.0'
@@ -9006,11 +9006,11 @@ snapshots:
'@bufbuild/protobuf@2.2.3': {}
'@commitlint/cli@19.7.1(@types/node@22.13.9)(typescript@5.8.2)':
'@commitlint/cli@19.7.1(@types/node@22.13.10)(typescript@5.8.2)':
dependencies:
'@commitlint/format': 19.5.0
'@commitlint/lint': 19.7.1
'@commitlint/load': 19.6.1(@types/node@22.13.9)(typescript@5.8.2)
'@commitlint/load': 19.6.1(@types/node@22.13.10)(typescript@5.8.2)
'@commitlint/read': 19.5.0
'@commitlint/types': 19.5.0
tinyexec: 0.3.1
@@ -9057,7 +9057,7 @@ snapshots:
'@commitlint/rules': 19.6.0
'@commitlint/types': 19.5.0
'@commitlint/load@19.6.1(@types/node@22.13.9)(typescript@5.8.2)':
'@commitlint/load@19.6.1(@types/node@22.13.10)(typescript@5.8.2)':
dependencies:
'@commitlint/config-validator': 19.5.0
'@commitlint/execute-rule': 19.5.0
@@ -9065,7 +9065,7 @@ snapshots:
'@commitlint/types': 19.5.0
chalk: 5.4.1
cosmiconfig: 9.0.0(typescript@5.8.2)
cosmiconfig-typescript-loader: 6.1.0(@types/node@22.13.9)(cosmiconfig@9.0.0(typescript@5.8.2))(typescript@5.8.2)
cosmiconfig-typescript-loader: 6.1.0(@types/node@22.13.10)(cosmiconfig@9.0.0(typescript@5.8.2))(typescript@5.8.2)
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
lodash.uniq: 4.5.0
@@ -9490,23 +9490,23 @@ snapshots:
'@material/material-color-utilities@0.3.0': {}
'@microsoft/api-extractor-model@7.30.3(@types/node@22.13.9)':
'@microsoft/api-extractor-model@7.30.3(@types/node@22.13.10)':
dependencies:
'@microsoft/tsdoc': 0.15.1
'@microsoft/tsdoc-config': 0.17.1
'@rushstack/node-core-library': 5.11.0(@types/node@22.13.9)
'@rushstack/node-core-library': 5.11.0(@types/node@22.13.10)
transitivePeerDependencies:
- '@types/node'
'@microsoft/api-extractor@7.51.0(@types/node@22.13.9)':
'@microsoft/api-extractor@7.51.0(@types/node@22.13.10)':
dependencies:
'@microsoft/api-extractor-model': 7.30.3(@types/node@22.13.9)
'@microsoft/api-extractor-model': 7.30.3(@types/node@22.13.10)
'@microsoft/tsdoc': 0.15.1
'@microsoft/tsdoc-config': 0.17.1
'@rushstack/node-core-library': 5.11.0(@types/node@22.13.9)
'@rushstack/node-core-library': 5.11.0(@types/node@22.13.10)
'@rushstack/rig-package': 0.5.3
'@rushstack/terminal': 0.15.0(@types/node@22.13.9)
'@rushstack/ts-command-line': 4.23.5(@types/node@22.13.9)
'@rushstack/terminal': 0.15.0(@types/node@22.13.10)
'@rushstack/ts-command-line': 4.23.5(@types/node@22.13.10)
lodash: 4.17.21
minimatch: 3.0.8
resolve: 1.22.8
@@ -10176,7 +10176,7 @@ snapshots:
'@rtsao/scc@1.1.0': {}
'@rushstack/node-core-library@5.11.0(@types/node@22.13.9)':
'@rushstack/node-core-library@5.11.0(@types/node@22.13.10)':
dependencies:
ajv: 8.13.0
ajv-draft-04: 1.0.0(ajv@8.13.0)
@@ -10187,23 +10187,23 @@ snapshots:
resolve: 1.22.8
semver: 7.5.4
optionalDependencies:
'@types/node': 22.13.9
'@types/node': 22.13.10
'@rushstack/rig-package@0.5.3':
dependencies:
resolve: 1.22.8
strip-json-comments: 3.1.1
'@rushstack/terminal@0.15.0(@types/node@22.13.9)':
'@rushstack/terminal@0.15.0(@types/node@22.13.10)':
dependencies:
'@rushstack/node-core-library': 5.11.0(@types/node@22.13.9)
'@rushstack/node-core-library': 5.11.0(@types/node@22.13.10)
supports-color: 8.1.1
optionalDependencies:
'@types/node': 22.13.9
'@types/node': 22.13.10
'@rushstack/ts-command-line@4.23.5(@types/node@22.13.9)':
'@rushstack/ts-command-line@4.23.5(@types/node@22.13.10)':
dependencies:
'@rushstack/terminal': 0.15.0(@types/node@22.13.9)
'@rushstack/terminal': 0.15.0(@types/node@22.13.10)
'@types/argparse': 1.0.38
argparse: 1.0.10
string-argv: 0.3.2
@@ -10520,7 +10520,7 @@ snapshots:
optionalDependencies:
'@tanstack/react-router': 1.112.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
'@tanstack/router-plugin@1.112.19(@tanstack/react-router@1.112.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))':
'@tanstack/router-plugin@1.112.19(@tanstack/react-router@1.112.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))':
dependencies:
'@babel/core': 7.26.9
'@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.9)
@@ -10541,7 +10541,7 @@ snapshots:
zod: 3.24.2
optionalDependencies:
'@tanstack/react-router': 1.112.18(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite: 6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
transitivePeerDependencies:
- supports-color
@@ -10694,12 +10694,12 @@ snapshots:
dependencies:
'@types/http-cache-semantics': 4.0.4
'@types/keyv': 3.1.4
'@types/node': 22.13.9
'@types/node': 22.13.10
'@types/responselike': 1.0.3
'@types/conventional-commits-parser@5.0.0':
dependencies:
'@types/node': 22.13.9
'@types/node': 22.13.10
'@types/d3-array@3.2.1': {}
@@ -10835,7 +10835,7 @@ snapshots:
'@types/fs-extra@11.0.4':
dependencies:
'@types/jsonfile': 6.1.4
'@types/node': 22.13.9
'@types/node': 22.13.10
'@types/geojson@7946.0.14': {}
@@ -10853,11 +10853,11 @@ snapshots:
'@types/jsonfile@6.1.4':
dependencies:
'@types/node': 22.13.9
'@types/node': 22.13.10
'@types/keyv@3.1.4':
dependencies:
'@types/node': 22.13.9
'@types/node': 22.13.10
'@types/lodash-es@4.17.12':
dependencies:
@@ -10877,7 +10877,7 @@ snapshots:
dependencies:
undici-types: 6.20.0
'@types/node@22.13.9':
'@types/node@22.13.10':
dependencies:
undici-types: 6.20.0
@@ -10907,7 +10907,7 @@ snapshots:
'@types/responselike@1.0.3':
dependencies:
'@types/node': 22.13.9
'@types/node': 22.13.10
'@types/retry@0.12.2': {}
@@ -10927,7 +10927,7 @@ snapshots:
'@types/yauzl@2.10.3':
dependencies:
'@types/node': 22.13.9
'@types/node': 22.13.10
optional: true
'@typescript-eslint/eslint-plugin@8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.21.0(jiti@2.4.2))(typescript@5.8.2)':
@@ -11046,7 +11046,7 @@ snapshots:
'@ungap/structured-clone@1.2.0': {}
'@vitejs/plugin-legacy@6.0.2(terser@5.36.0)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))':
'@vitejs/plugin-legacy@6.0.2(terser@5.36.0)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))':
dependencies:
'@babel/core': 7.26.9
'@babel/preset-env': 7.26.9(@babel/core@7.26.9)
@@ -11057,25 +11057,25 @@ snapshots:
regenerator-runtime: 0.14.1
systemjs: 6.15.1
terser: 5.36.0
vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite: 6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
transitivePeerDependencies:
- supports-color
'@vitejs/plugin-react-swc@3.8.0(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))':
'@vitejs/plugin-react-swc@3.8.0(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))':
dependencies:
'@swc/core': 1.10.15
vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite: 6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
transitivePeerDependencies:
- '@swc/helpers'
'@vitejs/plugin-react@4.3.4(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))':
'@vitejs/plugin-react@4.3.4(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0))':
dependencies:
'@babel/core': 7.26.0
'@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0)
'@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0)
'@types/babel__core': 7.20.5
react-refresh: 0.14.2
vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite: 6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
transitivePeerDependencies:
- supports-color
@@ -11718,9 +11718,9 @@ snapshots:
core-js@3.41.0: {}
cosmiconfig-typescript-loader@6.1.0(@types/node@22.13.9)(cosmiconfig@9.0.0(typescript@5.8.2))(typescript@5.8.2):
cosmiconfig-typescript-loader@6.1.0(@types/node@22.13.10)(cosmiconfig@9.0.0(typescript@5.8.2))(typescript@5.8.2):
dependencies:
'@types/node': 22.13.9
'@types/node': 22.13.10
cosmiconfig: 9.0.0(typescript@5.8.2)
jiti: 2.4.2
typescript: 5.8.2
@@ -13700,11 +13700,11 @@ snapshots:
kind-of@6.0.3: {}
knip@5.45.0(@types/node@22.13.9)(typescript@5.8.2):
knip@5.45.0(@types/node@22.13.10)(typescript@5.8.2):
dependencies:
'@nodelib/fs.walk': 3.0.1
'@snyk/github-codeowners': 1.1.0
'@types/node': 22.13.9
'@types/node': 22.13.10
easy-table: 1.2.0
enhanced-resolve: 5.18.1
fast-glob: 3.3.3
@@ -14305,7 +14305,7 @@ snapshots:
nanoid@3.3.8: {}
nanoid@5.1.2: {}
nanoid@5.1.3: {}
natural-compare@1.4.0: {}
@@ -16192,7 +16192,7 @@ snapshots:
unist-util-stringify-position: 4.0.0
vfile-message: 4.0.2
virtua@0.40.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
virtua@0.40.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
optionalDependencies:
react: 19.0.0
react-dom: 19.0.0(react@19.0.0)
@@ -16207,9 +16207,9 @@ snapshots:
- rollup
- supports-color
vite-plugin-dts@4.5.3(@types/node@22.13.9)(rollup@4.34.3)(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)):
vite-plugin-dts@4.5.3(@types/node@22.13.10)(rollup@4.34.3)(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)):
dependencies:
'@microsoft/api-extractor': 7.51.0(@types/node@22.13.9)
'@microsoft/api-extractor': 7.51.0(@types/node@22.13.10)
'@rollup/pluginutils': 5.1.4(rollup@4.34.3)
'@volar/typescript': 2.4.11
'@vue/language-core': 2.2.0(typescript@5.8.2)
@@ -16220,13 +16220,13 @@ snapshots:
magic-string: 0.30.17
typescript: 5.8.2
optionalDependencies:
vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite: 6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
transitivePeerDependencies:
- '@types/node'
- rollup
- supports-color
vite-plugin-html@3.2.2(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)):
vite-plugin-html@3.2.2(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)):
dependencies:
'@rollup/pluginutils': 4.2.1
colorette: 2.0.20
@@ -16240,45 +16240,45 @@ snapshots:
html-minifier-terser: 6.1.0
node-html-parser: 5.4.2
pathe: 0.2.0
vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite: 6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite-plugin-sass-dts@1.3.31(postcss@8.5.3)(prettier@3.5.2)(sass-embedded@1.85.1)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)):
vite-plugin-sass-dts@1.3.31(postcss@8.5.3)(prettier@3.5.2)(sass-embedded@1.85.1)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)):
dependencies:
postcss: 8.5.3
postcss-js: 4.0.1(postcss@8.5.3)
prettier: 3.5.2
sass-embedded: 1.85.1
vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite: 6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite-plugin-svgr@4.3.0(rollup@4.34.3)(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)):
vite-plugin-svgr@4.3.0(rollup@4.34.3)(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)):
dependencies:
'@rollup/pluginutils': 5.1.3(rollup@4.34.3)
'@svgr/core': 8.1.0(typescript@5.8.2)
'@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.8.2))
vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite: 6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
transitivePeerDependencies:
- rollup
- supports-color
- typescript
vite-tsconfig-paths@5.1.4(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)):
vite-tsconfig-paths@5.1.4(typescript@5.8.2)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)):
dependencies:
debug: 4.3.7
globrex: 0.1.2
tsconfck: 3.0.3(typescript@5.8.2)
optionalDependencies:
vite: 6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
vite: 6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0)
transitivePeerDependencies:
- supports-color
- typescript
vite@6.2.1(@types/node@22.13.9)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0):
vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.1)(sass-embedded@1.85.1)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.3)(yaml@2.7.0):
dependencies:
esbuild: 0.25.0
postcss: 8.5.3
rollup: 4.34.3
optionalDependencies:
'@types/node': 22.13.9
'@types/node': 22.13.10
fsevents: 2.3.3
jiti: 2.4.2
less: 4.2.0
+46 -7
View File
@@ -74,18 +74,57 @@ pub fn get_app_dir() -> CmdResult<String> {
#[tauri::command]
pub async fn download_icon_cache(url: String, name: String) -> CmdResult<String> {
let icon_cache_dir = wrap_err!(dirs::app_home_dir())?.join("icons").join("cache");
let icon_path = icon_cache_dir.join(name);
let icon_path = icon_cache_dir.join(&name);
// 如果文件已存在,直接返回路径
if icon_path.exists() {
return Ok(icon_path.to_string_lossy().to_string());
}
// 确保缓存目录存在
if !icon_cache_dir.exists() {
let _ = std::fs::create_dir_all(&icon_cache_dir);
}
if !icon_path.exists() {
let response = wrap_err!(reqwest::get(url).await)?;
let mut file = wrap_err!(std::fs::File::create(&icon_path))?;
let content = wrap_err!(response.bytes().await)?;
// 使用临时文件名来下载
let temp_path = icon_cache_dir.join(format!("{}.downloading", &name));
// 下载文件到临时位置
let response = wrap_err!(reqwest::get(url).await)?;
let content = wrap_err!(response.bytes().await)?;
// 写入临时文件
{
let mut file = match std::fs::File::create(&temp_path) {
Ok(file) => file,
Err(_) => {
if icon_path.exists() {
return Ok(icon_path.to_string_lossy().to_string());
} else {
return Err("Failed to create temporary file".into());
}
}
};
wrap_err!(std::io::copy(&mut content.as_ref(), &mut file))?;
}
// 再次检查目标文件是否已存在,避免重命名覆盖其他线程已完成的文件
if !icon_path.exists() {
// 使用原子重命名操作将临时文件移动到最终位置
match std::fs::rename(&temp_path, &icon_path) {
Ok(_) => {},
Err(_) => {
let _ = std::fs::remove_file(&temp_path);
if icon_path.exists() {
return Ok(icon_path.to_string_lossy().to_string());
}
}
}
} else {
let _ = std::fs::remove_file(&temp_path);
}
Ok(icon_path.to_string_lossy().to_string())
}
+154 -13
View File
@@ -1,10 +1,5 @@
use crate::{
config::*,
core::*,
feat,
wrap_err,
};
use super::CmdResult;
use crate::{config::*, core::*, feat, module::mihomo::MihomoManager, wrap_err};
use serde_yaml::Mapping;
/// 复制Clash环境变量
@@ -36,8 +31,11 @@ pub async fn patch_clash_mode(payload: String) -> CmdResult {
#[tauri::command]
pub async fn change_clash_core(clash_core: String) -> CmdResult<Option<String>> {
log::info!(target: "app", "changing core to {clash_core}");
match CoreManager::global().change_core(Some(clash_core.clone())).await {
match CoreManager::global()
.change_core(Some(clash_core.clone()))
.await
{
Ok(_) => {
log::info!(target: "app", "core changed to {clash_core}");
handle::Handle::notice_message("config_core::change_success", &clash_core);
@@ -65,11 +63,10 @@ pub async fn clash_api_get_proxy_delay(
name: String,
url: Option<String>,
timeout: i32,
) -> CmdResult<clash_api::DelayRes> {
match clash_api::get_proxy_delay(name, url, timeout).await {
Ok(res) => Ok(res),
Err(err) => Err(err.to_string()),
}
) -> CmdResult<serde_json::Value> {
MihomoManager::global()
.test_proxy_delay(&name, url, timeout)
.await
}
/// 测试URL延迟
@@ -77,3 +74,147 @@ pub async fn clash_api_get_proxy_delay(
pub async fn test_delay(url: String) -> CmdResult<u32> {
Ok(feat::test_delay(url).await.unwrap_or(10000u32))
}
/// 保存DNS配置到单独文件
#[tauri::command]
pub async fn save_dns_config(dns_config: Mapping) -> CmdResult {
use crate::utils::dirs;
use serde_yaml;
use std::fs;
// 获取DNS配置文件路径
let dns_path = dirs::app_home_dir()
.map_err(|e| e.to_string())?
.join("dns_config.yaml");
// 保存DNS配置到文件
let yaml_str = serde_yaml::to_string(&dns_config).map_err(|e| e.to_string())?;
fs::write(&dns_path, yaml_str).map_err(|e| e.to_string())?;
log::info!(target: "app", "DNS config saved to {:?}", dns_path);
Ok(())
}
/// 应用或撤销DNS配置
#[tauri::command]
pub fn apply_dns_config(apply: bool) -> CmdResult {
use crate::config::Config;
use crate::core::{handle, CoreManager};
use crate::utils::dirs;
use tauri::async_runtime;
// 使用spawn来处理异步操作
async_runtime::spawn(async move {
if apply {
// 读取DNS配置文件
let dns_path = match dirs::app_home_dir() {
Ok(path) => path.join("dns_config.yaml"),
Err(e) => {
log::error!(target: "app", "Failed to get home dir: {}", e);
return;
}
};
if !dns_path.exists() {
log::warn!(target: "app", "DNS config file not found");
return;
}
let dns_yaml = match std::fs::read_to_string(&dns_path) {
Ok(content) => content,
Err(e) => {
log::error!(target: "app", "Failed to read DNS config: {}", e);
return;
}
};
// 解析DNS配置并创建patch
let patch_config = match serde_yaml::from_str::<serde_yaml::Mapping>(&dns_yaml) {
Ok(config) => {
let mut patch = serde_yaml::Mapping::new();
patch.insert("dns".into(), config.into());
patch
}
Err(e) => {
log::error!(target: "app", "Failed to parse DNS config: {}", e);
return;
}
};
log::info!(target: "app", "Applying DNS config from file");
// 重新生成配置,确保DNS配置被正确应用
// 这里不调用patch_clash以避免将DNS配置写入config.yaml
Config::runtime()
.latest()
.patch_config(patch_config.clone());
// 首先重新生成配置
if let Err(err) = Config::generate().await {
log::error!(target: "app", "Failed to regenerate config with DNS: {}", err);
return;
}
// 然后应用新配置
if let Err(err) = CoreManager::global().update_config().await {
log::error!(target: "app", "Failed to apply config with DNS: {}", err);
} else {
log::info!(target: "app", "DNS config successfully applied");
handle::Handle::refresh_clash();
}
} else {
// 当关闭DNS设置时,不需要对配置进行任何修改
// 直接重新生成配置,让enhance函数自动跳过DNS配置的加载
log::info!(target: "app", "DNS settings disabled, regenerating config");
// 重新生成配置
if let Err(err) = Config::generate().await {
log::error!(target: "app", "Failed to regenerate config: {}", err);
return;
}
// 应用新配置
match CoreManager::global().update_config().await {
Ok(_) => {
log::info!(target: "app", "Config regenerated successfully");
handle::Handle::refresh_clash();
}
Err(err) => {
log::error!(target: "app", "Failed to apply regenerated config: {}", err);
}
}
}
});
Ok(())
}
/// 检查DNS配置文件是否存在
#[tauri::command]
pub fn check_dns_config_exists() -> CmdResult<bool> {
use crate::utils::dirs;
let dns_path = dirs::app_home_dir()
.map_err(|e| e.to_string())?
.join("dns_config.yaml");
Ok(dns_path.exists())
}
/// 获取DNS配置文件内容
#[tauri::command]
pub async fn get_dns_config_content() -> CmdResult<String> {
use crate::utils::dirs;
use std::fs;
let dns_path = dirs::app_home_dir()
.map_err(|e| e.to_string())?
.join("dns_config.yaml");
if !dns_path.exists() {
return Err("DNS config file not found".into());
}
let content = fs::read_to_string(&dns_path).map_err(|e| e.to_string())?;
Ok(content)
}
+1 -51
View File
@@ -38,56 +38,7 @@ impl IClashTemp {
tun.insert("strict-route".into(), false.into());
tun.insert("auto-detect-interface".into(), true.into());
tun.insert("dns-hijack".into(), vec!["any:53"].into());
// 添加默认的DNS配置
let mut dns = Mapping::new();
dns.insert("enable".into(), true.into());
dns.insert("listen".into(), ":53".into());
dns.insert("enhanced-mode".into(), "fake-ip".into());
dns.insert("fake-ip-range".into(), "198.18.0.1/16".into());
dns.insert("fake-ip-filter-mode".into(), "blacklist".into());
dns.insert("prefer-h3".into(), false.into());
dns.insert("respect-rules".into(), false.into());
dns.insert("use-hosts".into(), false.into());
dns.insert("use-system-hosts".into(), false.into());
// 添加fake-ip-filter
dns.insert("fake-ip-filter".into(), vec![
"*.lan", "*.local", "*.arpa", "time.*.com", "ntp.*.com", "time.*.com",
"+.market.xiaomi.com", "localhost.ptlogin2.qq.com", "*.msftncsi.com", "www.msftconnecttest.com"
].into());
// 添加nameserver相关配置
dns.insert("default-nameserver".into(), vec!["223.6.6.6", "8.8.8.8"].into());
dns.insert("nameserver".into(), vec![
"8.8.8.8", "https://doh.pub/dns-query", "https://dns.alidns.com/dns-query"
].into());
// 添加fallback配置
dns.insert("fallback".into(), vec![
"https://dns.alidns.com/dns-query", "https://dns.google/dns-query", "https://cloudflare-dns.com/dns-query"
].into());
// 添加proxy-server-nameserver
dns.insert("proxy-server-nameserver".into(), vec![
"https://doh.pub/dns-query", "https://dns.alidns.com/dns-query"
].into());
// 添加direct-nameserver
dns.insert("direct-nameserver".into(), Vec::<String>::new().into());
dns.insert("direct-nameserver-follow-policy".into(), false.into());
// 添加nameserver-policy (空对象)
dns.insert("nameserver-policy".into(), Mapping::new().into());
// 添加fallback-filter
let mut fallback_filter = Mapping::new();
fallback_filter.insert("geoip".into(), true.into());
fallback_filter.insert("geoip-code".into(), "CN".into());
fallback_filter.insert("ipcidr".into(), vec!["240.0.0.0/4", "0.0.0.0/32"].into());
fallback_filter.insert("domain".into(), vec!["+.google.com", "+.facebook.com", "+.youtube.com"].into());
dns.insert("fallback-filter".into(), fallback_filter.into());
#[cfg(not(target_os = "windows"))]
map.insert("redir-port".into(), 7895.into());
#[cfg(target_os = "linux")]
@@ -104,7 +55,6 @@ impl IClashTemp {
cors_map.insert("allow-origins".into(), vec!["*"].into());
map.insert("secret".into(), "".into());
map.insert("tun".into(), tun.into());
map.insert("dns".into(), dns.into());
map.insert("external-controller-cors".into(), cors_map.into());
map.insert("unified-delay".into(), true.into());
Self(map)
@@ -70,6 +70,9 @@ pub struct IVerge {
/// enable proxy guard
pub enable_proxy_guard: Option<bool>,
/// enable dns settings - this controls whether dns_config.yaml is applied
pub enable_dns_settings: Option<bool>,
/// always use default bypass
pub use_default_bypass: Option<bool>,
@@ -287,6 +290,7 @@ impl IVerge {
enable_tray_speed: Some(true),
enable_global_hotkey: Some(true),
enable_lite_mode: Some(false),
enable_dns_settings: Some(true),
..Self::default()
}
}
@@ -369,6 +373,7 @@ impl IVerge {
patch!(webdav_password);
patch!(enable_tray_speed);
patch!(enable_lite_mode);
patch!(enable_dns_settings);
}
/// 在初始化前尝试拿到单例端口的值
@@ -458,6 +463,7 @@ pub struct IVergeResponse {
pub webdav_password: Option<String>,
pub enable_tray_speed: Option<bool>,
pub enable_lite_mode: Option<bool>,
pub enable_dns_settings: Option<bool>,
}
impl From<IVerge> for IVergeResponse {
@@ -521,6 +527,7 @@ impl From<IVerge> for IVergeResponse {
webdav_password: verge.webdav_password,
enable_tray_speed: verge.enable_tray_speed,
enable_lite_mode: verge.enable_lite_mode,
enable_dns_settings: verge.enable_dns_settings,
}
}
}
+5 -145
View File
@@ -1,9 +1,4 @@
use crate::config::Config;
use anyhow::{bail, Result};
use reqwest::header::HeaderMap;
use serde::{Deserialize, Serialize};
use serde_yaml::Mapping;
use std::collections::HashMap;
use anyhow::Result;
#[derive(Debug, Clone, Default, PartialEq)]
pub struct Rate {
@@ -11,146 +6,11 @@ pub struct Rate {
pub down: u64,
}
/// PUT /configs
/// path 是绝对路径
pub async fn put_configs(path: &str) -> Result<()> {
let (url, headers) = clash_client_info()?;
let url = format!("{url}/configs?force=true");
let mut data = HashMap::new();
data.insert("path", path);
let client = reqwest::ClientBuilder::new().no_proxy().build()?;
let builder = client.put(&url).headers(headers).json(&data);
let response = builder.send().await?;
match response.status().as_u16() {
204 => Ok(()),
status => {
let body = response.text().await?;
// print!("failed to put configs with status \"{}\"\n{}\n{}", status, url, body);
bail!("failed to put configs with status \"{status}\"\n{url}\n{body}");
}
}
}
/// PATCH /configs
pub async fn patch_configs(config: &Mapping) -> Result<()> {
let (url, headers) = clash_client_info()?;
let url = format!("{url}/configs");
let client = reqwest::ClientBuilder::new().no_proxy().build()?;
let builder = client.patch(&url).headers(headers.clone()).json(config);
builder.send().await?;
Ok(())
}
#[derive(Default, Debug, Clone, Deserialize, Serialize)]
pub struct DelayRes {
delay: u64,
}
/// GET /proxies/{name}/delay
/// 获取代理延迟
pub async fn get_proxy_delay(
name: String,
test_url: Option<String>,
timeout: i32,
) -> Result<DelayRes> {
let (url, headers) = clash_client_info()?;
let url = format!("{url}/proxies/{name}/delay");
let default_url = "http://cp.cloudflare.com/generate_204";
let test_url = test_url
.map(|s| if s.is_empty() { default_url.into() } else { s })
.unwrap_or(default_url.into());
let client = reqwest::ClientBuilder::new().no_proxy().build()?;
let builder = client
.get(&url)
.headers(headers)
.query(&[("timeout", &format!("{timeout}")), ("url", &test_url)]);
let response = builder.send().await?;
Ok(response.json::<DelayRes>().await?)
}
/// 根据clash info获取clash服务地址和请求头
pub fn clash_client_info() -> Result<(String, HeaderMap)> {
let client = { Config::clash().data().get_client_info() };
let server = format!("http://{}", client.server);
let mut headers = HeaderMap::new();
headers.insert("Content-Type", "application/json".parse()?);
if let Some(secret) = client.secret {
let secret = format!("Bearer {}", secret).parse()?;
headers.insert("Authorization", secret);
}
Ok((server, headers))
}
/// 缩短clash的日志
#[allow(dead_code)]
pub fn parse_log(log: String) -> String {
if log.starts_with("time=") && log.len() > 33 {
return (log[33..]).to_owned();
}
if log.len() > 9 {
return (log[9..]).to_owned();
}
log
}
#[allow(dead_code)]
pub fn parse_check_output(log: String) -> String {
let t = log.find("time=");
let m = log.find("msg=");
let mr = log.rfind('"');
if let (Some(_), Some(m), Some(mr)) = (t, m, mr) {
let e = match log.find("level=error msg=") {
Some(e) => e + 17,
None => m + 5,
};
if mr > m {
return (log[e..mr]).to_owned();
}
}
let l = log.find("error=");
let r = log.find("path=").or(Some(log.len()));
if let (Some(l), Some(r)) = (l, r) {
return (log[(l + 6)..(r - 1)]).to_owned();
}
log
}
#[cfg(target_os = "macos")]
pub fn get_traffic_ws_url() -> Result<String> {
let (url, _) = clash_client_info()?;
use crate::module::mihomo::MihomoManager;
let (url, _) = MihomoManager::get_clash_client_info().unwrap();
let ws_url = url.replace("http://", "ws://") + "/traffic";
Ok(ws_url)
}
#[test]
fn test_parse_check_output() {
let str1 = r#"xxxx\n time="2022-11-18T20:42:58+08:00" level=error msg="proxy 0: 'alpn' expected type 'string', got unconvertible type '[]interface {}'""#;
//let str2 = r#"20:43:49 ERR [Config] configuration file test failed error=proxy 0: unsupport proxy type: hysteria path=xxx"#;
let str3 = r#"
"time="2022-11-18T21:38:01+08:00" level=info msg="Start initial configuration in progress"
time="2022-11-18T21:38:01+08:00" level=error msg="proxy 0: 'alpn' expected type 'string', got unconvertible type '[]interface {}'"
configuration file xxx\n
"#;
let res1 = parse_check_output(str1.into());
// let res2 = parse_check_output(str2.into());
let res3 = parse_check_output(str3.into());
assert_eq!(res1, res3);
}
}
+101 -83
View File
@@ -1,13 +1,13 @@
use crate::config::*;
use crate::core::{clash_api, handle, service};
#[cfg(target_os = "macos")]
use crate::core::tray::Tray;
use crate::core::{handle, service};
use crate::log_err;
use crate::module::mihomo::MihomoManager;
use crate::utils::{dirs, help};
use anyhow::{bail, Result};
use once_cell::sync::OnceCell;
use serde_yaml::Mapping;
use std::{sync::Arc, time::Duration, path::PathBuf};
use std::{path::PathBuf, sync::Arc, time::Duration};
use tauri_plugin_shell::ShellExt;
use tokio::sync::Mutex;
use tokio::time::sleep;
@@ -54,12 +54,14 @@ impl CoreManager {
}
// 关闭tun模式
let mut disable = Mapping::new();
let mut tun = Mapping::new();
tun.insert("enable".into(), false.into());
disable.insert("tun".into(), tun.into());
// Create a JSON object to disable TUN mode
let disable = serde_json::json!({
"tun": {
"enable": false
}
});
log::debug!(target: "app", "disable tun mode");
log_err!(clash_api::patch_configs(&disable).await);
log_err!(MihomoManager::global().patch_configs(disable).await);
// 服务模式
if service::check_service().await.is_ok() {
@@ -78,7 +80,7 @@ impl CoreManager {
// 如果没有使用服务,尝试停止sidecar进程
self.stop_sidecar_process();
}
*running = false;
Ok(())
}
@@ -111,7 +113,7 @@ impl CoreManager {
match service::run_core_by_service(&config_path).await {
Ok(_) => {
log::info!(target: "app", "core started successfully in service mode");
},
}
Err(err) => {
// 服务启动失败,尝试sidecar模式
log::warn!(target: "app", "failed to start core in service mode: {}", err);
@@ -138,28 +140,30 @@ impl CoreManager {
async fn run_core_by_sidecar(&self, config_path: &PathBuf) -> Result<()> {
let clash_core = { Config::verge().latest().clash_core.clone() };
let clash_core = clash_core.unwrap_or("verge-mihomo".into());
log::info!(target: "app", "starting core {} in sidecar mode", clash_core);
let app_handle = handle::Handle::global().app_handle().ok_or(anyhow::anyhow!("failed to get app handle"))?;
let app_handle = handle::Handle::global()
.app_handle()
.ok_or(anyhow::anyhow!("failed to get app handle"))?;
// 获取配置目录
let config_dir = dirs::app_home_dir()?;
let config_path_str = dirs::path_to_str(config_path)?;
// 启动核心进程并转入后台运行
let (_, child) = app_handle
.shell()
.sidecar(clash_core)?
.args(["-d", dirs::path_to_str(&config_dir)?, "-f", config_path_str])
.spawn()?;
// 保存进程ID以便后续管理
handle::Handle::global().set_core_process(child);
// 等待短暂时间确保启动成功
sleep(Duration::from_millis(300)).await;
log::info!(target: "app", "core started in sidecar mode");
Ok(())
}
@@ -201,10 +205,10 @@ impl CoreManager {
}
log::info!(target: "app", "change core to `{clash_core}`");
// 1. 先更新内核配置(但不应用)
Config::verge().draft().clash_core = Some(clash_core);
// 2. 使用新内核验证配置
println!("[切换内核] 使用新内核验证配置");
match self.validate_config().await {
@@ -213,7 +217,7 @@ impl CoreManager {
// 3. 验证通过后,应用内核配置并重启
Config::verge().apply();
log_err!(Config::verge().latest().save_file());
match self.restart_core().await {
Ok(_) => {
println!("[切换内核] 内核切换成功");
@@ -233,10 +237,11 @@ impl CoreManager {
Ok((false, error_msg)) => {
println!("[切换内核] 配置验证失败: {}", error_msg);
// 使用默认配置并继续切换内核
self.use_default_config("config_validate::core_change", &error_msg).await?;
self.use_default_config("config_validate::core_change", &error_msg)
.await?;
Config::verge().apply();
log_err!(Config::verge().latest().save_file());
match self.restart_core().await {
Ok(_) => {
println!("[切换内核] 内核切换成功(使用默认配置)");
@@ -266,13 +271,13 @@ impl CoreManager {
println!("[core配置验证] 应用正在退出,跳过验证");
return Ok((true, String::new()));
}
println!("[core配置验证] 开始验证配置文件: {}", config_path);
let clash_core = { Config::verge().latest().clash_core.clone() };
let clash_core = clash_core.unwrap_or("verge-mihomo".into());
println!("[core配置验证] 使用内核: {}", clash_core);
let app_handle = handle::Handle::global().app_handle().unwrap();
let test_dir = dirs::app_home_dir()?.join("test");
let test_dir = dirs::path_to_str(&test_dir)?;
@@ -289,14 +294,15 @@ impl CoreManager {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
// 检查进程退出状态和错误输出
let error_keywords = ["FATA", "fatal", "Parse config error", "level=fatal"];
let has_error = !output.status.success() || error_keywords.iter().any(|&kw| stderr.contains(kw));
let has_error =
!output.status.success() || error_keywords.iter().any(|&kw| stderr.contains(kw));
println!("\n[core配置验证] -------- 验证结果 --------");
println!("[core配置验证] 进程退出状态: {:?}", output.status);
if !stderr.is_empty() {
println!("[core配置验证] stderr输出:\n{}", stderr);
}
@@ -317,7 +323,7 @@ impl CoreManager {
};
println!("[core配置验证] -------- 验证结束 --------\n");
Ok((false, error_msg)) // 返回错误消息给调用者处理
Ok((false, error_msg)) // 返回错误消息给调用者处理
} else {
println!("[core配置验证] 验证成功");
println!("[core配置验证] -------- 验证结束 --------\n");
@@ -333,26 +339,33 @@ impl CoreManager {
}
/// 验证指定的配置文件
pub async fn validate_config_file(&self, config_path: &str, is_merge_file: Option<bool>) -> Result<(bool, String)> {
pub async fn validate_config_file(
&self,
config_path: &str,
is_merge_file: Option<bool>,
) -> Result<(bool, String)> {
// 检查程序是否正在退出,如果是则跳过验证
if handle::Handle::global().is_exiting() {
println!("[core配置验证] 应用正在退出,跳过验证");
return Ok((true, String::new()));
}
// 检查文件是否存在
if !std::path::Path::new(config_path).exists() {
let error_msg = format!("File not found: {}", config_path);
//handle::Handle::notice_message("config_validate::file_not_found", &error_msg);
return Ok((false, error_msg));
}
// 如果是合并文件且不是强制验证,执行语法检查但不进行完整验证
if is_merge_file.unwrap_or(false) {
println!("[core配置验证] 检测到Merge文件,仅进行语法检查: {}", config_path);
println!(
"[core配置验证] 检测到Merge文件,仅进行语法检查: {}",
config_path
);
return self.validate_file_syntax(config_path).await;
}
// 检查是否为脚本文件
let is_script = if config_path.ends_with(".js") {
true
@@ -366,12 +379,12 @@ impl CoreManager {
}
}
};
if is_script {
log::info!(target: "app", "检测到脚本文件,使用JavaScript验证: {}", config_path);
return self.validate_script_file(config_path).await;
}
// 对YAML配置文件使用Clash内核验证
log::info!(target: "app", "使用Clash内核验证配置文件: {}", config_path);
self.validate_config_internal(config_path).await
@@ -385,33 +398,36 @@ impl CoreManager {
} else if path.ends_with(".js") {
return Ok(true); // JS文件是脚本文件
}
// 2. 读取文件内容
let content = match std::fs::read_to_string(path) {
Ok(content) => content,
Err(err) => {
log::warn!(target: "app", "无法读取文件以检测类型: {}, 错误: {}", path, err);
return Err(anyhow::anyhow!("Failed to read file to detect type: {}", err));
return Err(anyhow::anyhow!(
"Failed to read file to detect type: {}",
err
));
}
};
// 3. 检查是否存在明显的YAML特征
let has_yaml_features = content.contains(": ") ||
content.contains("#") ||
content.contains("---") ||
content.lines().any(|line| line.trim().starts_with("- "));
let has_yaml_features = content.contains(": ")
|| content.contains("#")
|| content.contains("---")
|| content.lines().any(|line| line.trim().starts_with("- "));
// 4. 检查是否存在明显的JS特征
let has_js_features = content.contains("function ") ||
content.contains("const ") ||
content.contains("let ") ||
content.contains("var ") ||
content.contains("//") ||
content.contains("/*") ||
content.contains("*/") ||
content.contains("export ") ||
content.contains("import ");
let has_js_features = content.contains("function ")
|| content.contains("const ")
|| content.contains("let ")
|| content.contains("var ")
|| content.contains("//")
|| content.contains("/*")
|| content.contains("*/")
|| content.contains("export ")
|| content.contains("import ");
// 5. 决策逻辑
if has_yaml_features && !has_js_features {
// 只有YAML特征,没有JS特征
@@ -422,22 +438,21 @@ impl CoreManager {
} else if has_yaml_features && has_js_features {
// 两种特征都有,需要更精细判断
// 优先检查是否有明确的JS结构特征
if content.contains("function main") ||
content.contains("module.exports") ||
content.contains("export default") {
if content.contains("function main")
|| content.contains("module.exports")
|| content.contains("export default")
{
return Ok(true);
}
// 检查冒号后是否有空格(YAML的典型特征)
let yaml_pattern_count = content.lines()
.filter(|line| line.contains(": "))
.count();
let yaml_pattern_count = content.lines().filter(|line| line.contains(": ")).count();
if yaml_pattern_count > 2 {
return Ok(false); // 多个键值对格式,更可能是YAML
}
}
// 默认情况:无法确定时,假设为非脚本文件(更安全)
log::debug!(target: "app", "无法确定文件类型,默认当作YAML处理: {}", path);
Ok(false)
@@ -455,29 +470,32 @@ impl CoreManager {
return Ok((false, error_msg));
}
};
log::debug!(target: "app", "验证脚本文件: {}", path);
// 使用boa引擎进行基本语法检查
use boa_engine::{Context, Source};
let mut context = Context::default();
let result = context.eval(Source::from_bytes(&content));
match result {
Ok(_) => {
log::debug!(target: "app", "脚本语法验证通过: {}", path);
// 检查脚本是否包含main函数
if !content.contains("function main") && !content.contains("const main") && !content.contains("let main") {
if !content.contains("function main")
&& !content.contains("const main")
&& !content.contains("let main")
{
let error_msg = "Script must contain a main function";
log::warn!(target: "app", "脚本缺少main函数: {}", path);
//handle::Handle::notice_message("config_validate::script_missing_main", error_msg);
return Ok((false, error_msg.to_string()));
}
Ok((true, String::new()))
},
}
Err(err) => {
let error_msg = format!("Script syntax error: {}", err);
log::warn!(target: "app", "脚本语法错误: {}", err);
@@ -494,13 +512,13 @@ impl CoreManager {
println!("[core配置更新] 应用正在退出,跳过验证");
return Ok((true, String::new()));
}
println!("[core配置更新] 开始更新配置");
// 1. 先生成新的配置内容
println!("[core配置更新] 生成新的配置内容");
Config::generate().await?;
// 2. 生成临时文件并进行验证
println!("[core配置更新] 生成临时配置文件用于验证");
let temp_config = Config::generate_file(ConfigType::Check)?;
@@ -519,7 +537,7 @@ impl CoreManager {
// 5. 应用新配置
println!("[core配置更新] 应用新配置");
for i in 0..3 {
match clash_api::put_configs(run_path).await {
match MihomoManager::global().put_configs_force(run_path).await {
Ok(_) => {
println!("[core配置更新] 配置应用成功");
Config::runtime().apply();
@@ -556,7 +574,7 @@ impl CoreManager {
/// 只进行文件语法检查,不进行完整验证
async fn validate_file_syntax(&self, config_path: &str) -> Result<(bool, String)> {
println!("[core配置语法检查] 开始检查文件: {}", config_path);
// 读取文件内容
let content = match std::fs::read_to_string(config_path) {
Ok(content) => content,
@@ -566,14 +584,14 @@ impl CoreManager {
return Ok((false, error_msg));
}
};
// 对YAML文件尝试解析,只检查语法正确性
println!("[core配置语法检查] 进行YAML语法检查");
match serde_yaml::from_str::<serde_yaml::Value>(&content) {
Ok(_) => {
println!("[core配置语法检查] YAML语法检查通过");
Ok((true, String::new()))
},
}
Err(err) => {
// 使用标准化的前缀,以便错误处理函数能正确识别
let error_msg = format!("YAML syntax error: {}", err);
@@ -589,7 +607,7 @@ impl CoreManager {
if !*running {
return RunningMode::NotRunning;
}
// 检查服务状态
match service::check_service().await {
Ok(_) => {
@@ -605,7 +623,7 @@ impl CoreManager {
}
}
}
},
}
Err(_) => {
// 服务不可用,检查是否有sidecar进程
if handle::Handle::global().has_core_process() {
@@ -616,4 +634,4 @@ impl CoreManager {
}
}
}
}
}
@@ -1,4 +1,5 @@
use reqwest::header::HeaderMap;
use serde_json::json;
use std::{
sync::{Arc, Mutex},
time::Duration,
@@ -42,43 +43,92 @@ impl MihomoManager {
data.providers_proxies.clone()
}
pub async fn refresh_proxies(&self) -> Result<&Self, String> {
let url = format!("{}/proxies", self.mihomo_server);
let response = reqwest::ClientBuilder::new()
async fn send_request(
&self,
method: &str,
url: String,
data: Option<serde_json::Value>,
) -> Result<serde_json::Value, String> {
let client_response = reqwest::ClientBuilder::new()
.default_headers(self.headers.clone())
.no_proxy()
.timeout(Duration::from_secs(3))
.timeout(Duration::from_secs(2))
.build()
.map_err(|e| e.to_string())?
.get(url)
.request(
match method {
"GET" => reqwest::Method::GET,
"PUT" => reqwest::Method::PUT,
"POST" => reqwest::Method::POST,
"PATCH" => reqwest::Method::PATCH,
_ => reqwest::Method::GET,
},
&url,
)
.json(&data.unwrap_or(json!({})))
.send()
.await
.map_err(|e| e.to_string())?
.json::<serde_json::Value>()
.await
.map_err(|e| e.to_string())?;
let proxies = response;
let response = if method != "PUT" {
client_response.json::<serde_json::Value>().await
} else {
client_response.text().await.map(|text| json!(text))
}
.map_err(|e| e.to_string())?;
return Ok(response);
}
pub async fn refresh_proxies(&self) -> Result<&Self, String> {
let url = format!("{}/proxies", self.mihomo_server);
let proxies = self.send_request("GET", url, None).await?;
self.update_proxies(proxies);
Ok(self)
}
pub async fn refresh_providers_proxies(&self) -> Result<&Self, String> {
let url = format!("{}/providers/proxies", self.mihomo_server);
let response = reqwest::ClientBuilder::new()
.default_headers(self.headers.clone())
.no_proxy()
.timeout(Duration::from_secs(3))
.build()
.map_err(|e| e.to_string())?
.get(url)
.send()
.await
.map_err(|e| e.to_string())?
.json::<serde_json::Value>()
.await
.map_err(|e| e.to_string())?;
let proxies = response;
self.update_providers_proxies(proxies);
let providers_proxies = self.send_request("GET", url, None).await?;
self.update_providers_proxies(providers_proxies);
Ok(self)
}
}
impl MihomoManager {
pub async fn put_configs_force(&self, clash_config_path: &str) -> Result<(), String> {
let url = format!("{}/configs?force=true", self.mihomo_server);
let payload = serde_json::json!({
"path": clash_config_path,
});
let _response = self.send_request("PUT", url, Some(payload)).await?;
Ok(())
}
pub async fn patch_configs(&self, config: serde_json::Value) -> Result<(), String> {
let url = format!("{}/configs", self.mihomo_server);
let response = self.send_request("PATCH", url, Some(config)).await?;
if response["code"] == 204 {
Ok(())
} else {
Err(response["message"]
.as_str()
.unwrap_or("unknown error")
.to_string())
}
}
pub async fn test_proxy_delay(
&self,
name: &str,
test_url: Option<String>,
timeout: i32,
) -> Result<serde_json::Value, String> {
let test_url = test_url.unwrap_or("http://cp.cloudflare.com/generate_204".to_string());
let url = format!(
"{}/proxies/{}/delay?url={}&timeout={}",
self.mihomo_server, name, test_url, timeout
);
let response = self.send_request("GET", url, None).await?;
return Ok(response);
}
}
+23 -1
View File
@@ -25,7 +25,7 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
// config.yaml 的订阅
let clash_config = { Config::clash().latest().0.clone() };
let (clash_core, enable_tun, enable_builtin, socks_enabled, http_enabled) = {
let (clash_core, enable_tun, enable_builtin, socks_enabled, http_enabled, enable_dns_settings) = {
let verge = Config::verge();
let verge = verge.latest();
(
@@ -34,6 +34,7 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
verge.enable_builtin_enhanced.unwrap_or(true),
verge.verge_socks_enabled.unwrap_or(false),
verge.verge_http_enabled.unwrap_or(false),
verge.enable_dns_settings.unwrap_or(false),
)
};
#[cfg(not(target_os = "windows"))]
@@ -262,6 +263,27 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
config = use_tun(config, enable_tun).await;
config = use_sort(config);
// 应用独立的DNS配置(如果启用)
if enable_dns_settings {
use crate::utils::dirs;
use std::fs;
// 尝试读取dns_config.yaml
if let Ok(app_dir) = dirs::app_home_dir() {
let dns_path = app_dir.join("dns_config.yaml");
if dns_path.exists() {
if let Ok(dns_yaml) = fs::read_to_string(&dns_path) {
if let Ok(dns_config) = serde_yaml::from_str::<serde_yaml::Mapping>(&dns_yaml) {
// 将DNS配置合并到最终配置中
config.insert("dns".into(), dns_config.into());
log::info!(target: "app", "apply dns_config.yaml");
}
}
}
}
}
let mut exists_set = HashSet::new();
exists_set.extend(exists_keys);
exists_keys = exists_set.into_iter().collect();
+19 -41
View File
@@ -24,18 +24,20 @@ pub async fn use_tun(mut config: Mapping, enable: bool) -> Mapping {
let mut tun_val = tun_val.map_or(Mapping::new(), |val| {
val.as_mapping().cloned().unwrap_or(Mapping::new())
});
let dns_key = Value::from("dns");
let dns_val = config.get(&dns_key);
let mut dns_val = dns_val.map_or(Mapping::new(), |val| {
val.as_mapping().cloned().unwrap_or(Mapping::new())
});
let ipv6_key = Value::from("ipv6");
let ipv6_val = config
.get(&ipv6_key)
.and_then(|v| v.as_bool())
.unwrap_or(false);
if enable {
// 读取DNS配置
let dns_key = Value::from("dns");
let dns_val = config.get(&dns_key);
let mut dns_val = dns_val.map_or(Mapping::new(), |val| {
val.as_mapping().cloned().unwrap_or(Mapping::new())
});
let ipv6_key = Value::from("ipv6");
let ipv6_val = config
.get(&ipv6_key)
.and_then(|v| v.as_bool())
.unwrap_or(false);
// 检查现有的 enhanced-mode 设置
let current_mode = dns_val
.get(&Value::from("enhanced-mode"))
@@ -61,42 +63,18 @@ pub async fn use_tun(mut config: Mapping, enable: bool) -> Mapping {
crate::utils::resolve::set_public_dns("223.6.6.6".to_string()).await;
}
}
// 当TUN启用时,将修改后的DNS配置写回
revise!(config, "dns", dns_val);
} else {
revise!(
dns_val,
"enable",
dns_val
.get("enable")
.and_then(|v| v.as_bool())
.unwrap_or(true)
);
revise!(dns_val, "ipv6", ipv6_val);
revise!(
dns_val,
"enhanced-mode",
dns_val
.get("enhanced-mode")
.and_then(|v| v.as_str())
.unwrap_or("redir-host")
);
revise!(
dns_val,
"fake-ip-range",
dns_val
.get("fake-ip-range")
.and_then(|v| v.as_str())
.unwrap_or("198.18.0.1/16")
);
// TUN未启用时,仅恢复系统DNS,不修改配置文件中的DNS设置
#[cfg(target_os = "macos")]
crate::utils::resolve::restore_public_dns().await;
}
// 更新TUN配置
revise!(tun_val, "enable", enable);
revise!(config, "tun", tun_val);
revise!(config, "dns", dns_val);
config
}
+7 -2
View File
@@ -1,6 +1,7 @@
use crate::config::Config;
use crate::core::{clash_api, handle, tray, CoreManager};
use crate::core::{handle, tray, CoreManager};
use crate::log_err;
use crate::module::mihomo::MihomoManager;
use crate::utils::resolve;
use serde_yaml::{Mapping, Value};
use tauri::Manager;
@@ -38,10 +39,14 @@ pub fn restart_app() {
pub fn change_clash_mode(mode: String) {
let mut mapping = Mapping::new();
mapping.insert(Value::from("mode"), mode.clone().into());
// Convert YAML mapping to JSON Value
let json_value = serde_json::json!({
"mode": mode
});
tauri::async_runtime::spawn(async move {
log::debug!(target: "app", "change clash mode to {mode}");
match clash_api::patch_configs(&mapping).await {
match MihomoManager::global().patch_configs(json_value).await {
Ok(_) => {
// 更新订阅
Config::clash().data().patch_config(mapping);
+35 -30
View File
@@ -1,9 +1,10 @@
use crate::utils::resolve;
use crate::core::handle;
use crate::core::{sysopt, CoreManager, clash_api};
use crate::config::Config;
use tauri::Manager;
use crate::core::handle;
use crate::core::{sysopt, CoreManager};
use crate::module::mihomo::MihomoManager;
use crate::utils::resolve;
use futures;
use tauri::Manager;
use tauri_plugin_window_state::{AppHandleExt, StateFlags};
/// Open or close the dashboard window
@@ -52,7 +53,7 @@ pub fn open_or_close_dashboard() {
pub fn setup_window_state_monitor(app_handle: &tauri::AppHandle) {
let window = app_handle.get_webview_window("main").unwrap();
let app_handle_clone = app_handle.clone();
// 监听窗口移动事件
let app_handle_move = app_handle_clone.clone();
window.on_window_event(move |event| {
@@ -60,19 +61,19 @@ pub fn setup_window_state_monitor(app_handle: &tauri::AppHandle) {
// 窗口移动时保存状态
tauri::WindowEvent::Moved(_) => {
let _ = app_handle_move.save_window_state(StateFlags::all());
},
}
// 窗口调整大小时保存状态
tauri::WindowEvent::Resized(_) => {
let _ = app_handle_move.save_window_state(StateFlags::all());
},
}
// 其他可能改变窗口状态的事件
tauri::WindowEvent::ScaleFactorChanged { .. } => {
let _ = app_handle_move.save_window_state(StateFlags::all());
},
}
// 窗口关闭时保存
tauri::WindowEvent::CloseRequested { .. } => {
let _ = app_handle_move.save_window_state(StateFlags::all());
},
}
_ => {}
}
});
@@ -81,16 +82,16 @@ pub fn setup_window_state_monitor(app_handle: &tauri::AppHandle) {
/// 优化的应用退出函数
pub fn quit(code: Option<i32>) {
log::debug!(target: "app", "启动退出流程");
// 获取应用句柄并设置退出标志
let app_handle = handle::Handle::global().app_handle().unwrap();
handle::Handle::global().set_is_exiting();
// 优先关闭窗口,提供立即反馈
if let Some(window) = handle::Handle::global().get_window() {
let _ = window.hide();
}
// 在单独线程中处理资源清理,避免阻塞主线程
std::thread::spawn(move || {
// 使用tokio运行时执行异步清理任务
@@ -100,34 +101,38 @@ pub fn quit(code: Option<i32>) {
// 1. 直接关闭TUN模式 (优先处理,通常最容易卡住)
if Config::verge().data().enable_tun_mode.unwrap_or(false) {
let mut disable = serde_yaml::Mapping::new();
let mut tun = serde_yaml::Mapping::new();
tun.insert("enable".into(), false.into());
disable.insert("tun".into(), tun.into());
let disable = serde_json::json!({
"tun": {
"enable": false
}
});
// 设置1秒超时
let _ = timeout(Duration::from_secs(1),
clash_api::patch_configs(&disable)).await;
let _ = timeout(
Duration::from_secs(1),
MihomoManager::global().patch_configs(disable),
)
.await;
}
// 2. 并行处理系统代理和核心进程清理
let proxy_future = timeout(Duration::from_secs(1),
sysopt::Sysopt::global().reset_sysproxy());
let core_future = timeout(Duration::from_secs(1),
CoreManager::global().stop_core());
let proxy_future = timeout(
Duration::from_secs(1),
sysopt::Sysopt::global().reset_sysproxy(),
);
let core_future = timeout(Duration::from_secs(1), CoreManager::global().stop_core());
// 同时等待两个任务完成
let _ = futures::join!(proxy_future, core_future);
// 3. 处理macOS特定清理
#[cfg(target_os = "macos")]
{
let _ = timeout(Duration::from_millis(500),
resolve::restore_public_dns()).await;
let _ = timeout(Duration::from_millis(500), resolve::restore_public_dns()).await;
}
});
// 无论清理结果如何,确保应用退出
app_handle.exit(code.unwrap_or(0));
});
+4
View File
@@ -163,6 +163,10 @@ pub fn run() {
cmd::copy_clash_env,
cmd::get_proxies,
cmd::get_providers_proxies,
cmd::save_dns_config,
cmd::apply_dns_config,
cmd::check_dns_config_exists,
cmd::get_dns_config_content,
// verge
cmd::get_verge_config,
cmd::patch_verge_config,
+18 -2
View File
@@ -1,7 +1,8 @@
use crate::core::clash_api;
use crate::config::Config;
use mihomo_api;
use once_cell::sync::{Lazy, OnceCell};
use std::sync::Mutex;
use tauri::http::HeaderMap;
pub struct MihomoManager {
mihomo: Mutex<OnceCell<mihomo_api::MihomoManager>>,
@@ -17,7 +18,7 @@ impl MihomoManager {
pub fn global() -> mihomo_api::MihomoManager {
let instance = MihomoManager::__global();
let (current_server, headers) = clash_api::clash_client_info().unwrap();
let (current_server, headers) = MihomoManager::get_clash_client_info().unwrap();
let lock = instance.mihomo.lock().unwrap();
if let Some(mihomo) = lock.get() {
@@ -31,3 +32,18 @@ impl MihomoManager {
lock.get().unwrap().clone()
}
}
impl MihomoManager {
pub fn get_clash_client_info() -> Option<(String, HeaderMap)> {
let client = { Config::clash().data().get_client_info() };
let server = format!("http://{}", client.server);
let mut headers = HeaderMap::new();
headers.insert("Content-Type", "application/json".parse().unwrap());
if let Some(secret) = client.secret {
let secret = format!("Bearer {}", secret).parse().unwrap();
headers.insert("Authorization", secret);
}
Some((server, headers))
}
}
@@ -133,6 +133,81 @@ pub fn delete_log() -> Result<()> {
Ok(())
}
/// 初始化DNS配置文件
fn init_dns_config() -> Result<()> {
use serde_yaml::Value;
// 获取默认DNS配置
let default_dns_config = serde_yaml::Mapping::from_iter([
("enable".into(), Value::Bool(true)),
("listen".into(), Value::String(":53".into())),
("enhanced-mode".into(), Value::String("fake-ip".into())),
("fake-ip-range".into(), Value::String("198.18.0.1/16".into())),
("fake-ip-filter-mode".into(), Value::String("blacklist".into())),
("prefer-h3".into(), Value::Bool(false)),
("respect-rules".into(), Value::Bool(false)),
("use-hosts".into(), Value::Bool(false)),
("use-system-hosts".into(), Value::Bool(false)),
("fake-ip-filter".into(), Value::Sequence(vec![
Value::String("*.lan".into()),
Value::String("*.local".into()),
Value::String("*.arpa".into()),
Value::String("time.*.com".into()),
Value::String("ntp.*.com".into()),
Value::String("time.*.com".into()),
Value::String("+.market.xiaomi.com".into()),
Value::String("localhost.ptlogin2.qq.com".into()),
Value::String("*.msftncsi.com".into()),
Value::String("www.msftconnecttest.com".into()),
])),
("default-nameserver".into(), Value::Sequence(vec![
Value::String("223.6.6.6".into()),
Value::String("8.8.8.8".into()),
])),
("nameserver".into(), Value::Sequence(vec![
Value::String("8.8.8.8".into()),
Value::String("https://doh.pub/dns-query".into()),
Value::String("https://dns.alidns.com/dns-query".into()),
])),
("fallback".into(), Value::Sequence(vec![
Value::String("https://dns.alidns.com/dns-query".into()),
Value::String("https://dns.google/dns-query".into()),
Value::String("https://cloudflare-dns.com/dns-query".into()),
])),
("nameserver-policy".into(), Value::Mapping(serde_yaml::Mapping::new())),
("proxy-server-nameserver".into(), Value::Sequence(vec![
Value::String("https://doh.pub/dns-query".into()),
Value::String("https://dns.alidns.com/dns-query".into()),
])),
("direct-nameserver".into(), Value::Sequence(vec![])),
("direct-nameserver-follow-policy".into(), Value::Bool(false)),
("fallback-filter".into(), Value::Mapping(serde_yaml::Mapping::from_iter([
("geoip".into(), Value::Bool(true)),
("geoip-code".into(), Value::String("CN".into())),
("ipcidr".into(), Value::Sequence(vec![
Value::String("240.0.0.0/4".into()),
Value::String("0.0.0.0/32".into()),
])),
("domain".into(), Value::Sequence(vec![
Value::String("+.google.com".into()),
Value::String("+.facebook.com".into()),
Value::String("+.youtube.com".into()),
])),
]))),
]);
// 检查DNS配置文件是否存在
let app_dir = dirs::app_home_dir()?;
let dns_path = app_dir.join("dns_config.yaml");
if !dns_path.exists() {
log::info!(target: "app", "Creating default DNS config file");
help::save_yaml(&dns_path, &default_dns_config, Some("# Clash Verge DNS Config"))?;
}
Ok(())
}
/// Initialize all the config files
/// before tauri setup
pub fn init_config() -> Result<()> {
@@ -173,6 +248,9 @@ pub fn init_config() -> Result<()> {
<Result<()>>::Ok(())
}));
// 初始化DNS配置文件
let _ = init_dns_config();
Ok(())
}
@@ -22,6 +22,7 @@ import yaml from "js-yaml";
import MonacoEditor from "react-monaco-editor";
import { useThemeMode } from "@/services/states";
import getSystem from "@/utils/get-system";
import { invoke } from "@tauri-apps/api/core";
const Item = styled(ListItem)(({ theme }) => ({
padding: "8px 0",
@@ -145,11 +146,109 @@ export const DnsViewer = forwardRef<DialogRef>((props, ref) => {
useImperativeHandle(ref, () => ({
open: () => {
setOpen(true);
resetToDefaults();
// 获取DNS配置文件并初始化表单
initDnsConfig();
},
close: () => setOpen(false),
}));
// 初始化DNS配置
const initDnsConfig = async () => {
try {
// 尝试从dns_config.yaml文件读取配置
const dnsConfigExists = await invoke<boolean>(
"check_dns_config_exists",
{},
);
if (dnsConfigExists) {
// 如果存在配置文件,加载其内容
const dnsConfig = await invoke<string>("get_dns_config_content", {});
const config = yaml.load(dnsConfig) as any;
// 更新表单数据
updateValuesFromConfig(config);
// 更新YAML编辑器内容
setYamlContent(dnsConfig);
} else {
// 如果不存在配置文件,使用默认值
resetToDefaults();
}
} catch (err) {
console.error("Failed to initialize DNS config", err);
resetToDefaults();
}
};
// 从配置对象更新表单值
const updateValuesFromConfig = (config: any) => {
if (!config) return;
const enhancedMode =
config["enhanced-mode"] || DEFAULT_DNS_CONFIG["enhanced-mode"];
const validEnhancedMode =
enhancedMode === "fake-ip" || enhancedMode === "redir-host"
? enhancedMode
: DEFAULT_DNS_CONFIG["enhanced-mode"];
const fakeIpFilterMode =
config["fake-ip-filter-mode"] ||
DEFAULT_DNS_CONFIG["fake-ip-filter-mode"];
const validFakeIpFilterMode =
fakeIpFilterMode === "blacklist" || fakeIpFilterMode === "whitelist"
? fakeIpFilterMode
: DEFAULT_DNS_CONFIG["fake-ip-filter-mode"];
setValues({
enable: config.enable ?? DEFAULT_DNS_CONFIG.enable,
listen: config.listen ?? DEFAULT_DNS_CONFIG.listen,
enhancedMode: validEnhancedMode,
fakeIpRange:
config["fake-ip-range"] ?? DEFAULT_DNS_CONFIG["fake-ip-range"],
fakeIpFilterMode: validFakeIpFilterMode,
preferH3: config["prefer-h3"] ?? DEFAULT_DNS_CONFIG["prefer-h3"],
respectRules:
config["respect-rules"] ?? DEFAULT_DNS_CONFIG["respect-rules"],
fakeIpFilter:
config["fake-ip-filter"]?.join(", ") ??
DEFAULT_DNS_CONFIG["fake-ip-filter"].join(", "),
nameserver:
config.nameserver?.join(", ") ??
DEFAULT_DNS_CONFIG.nameserver.join(", "),
fallback:
config.fallback?.join(", ") ?? DEFAULT_DNS_CONFIG.fallback.join(", "),
defaultNameserver:
config["default-nameserver"]?.join(", ") ??
DEFAULT_DNS_CONFIG["default-nameserver"].join(", "),
useHosts: config["use-hosts"] ?? DEFAULT_DNS_CONFIG["use-hosts"],
useSystemHosts:
config["use-system-hosts"] ?? DEFAULT_DNS_CONFIG["use-system-hosts"],
proxyServerNameserver:
config["proxy-server-nameserver"]?.join(", ") ??
(DEFAULT_DNS_CONFIG["proxy-server-nameserver"]?.join(", ") || ""),
directNameserver:
config["direct-nameserver"]?.join(", ") ??
(DEFAULT_DNS_CONFIG["direct-nameserver"]?.join(", ") || ""),
directNameserverFollowPolicy:
config["direct-nameserver-follow-policy"] ??
DEFAULT_DNS_CONFIG["direct-nameserver-follow-policy"],
fallbackGeoip:
config["fallback-filter"]?.geoip ??
DEFAULT_DNS_CONFIG["fallback-filter"].geoip,
fallbackGeoipCode:
config["fallback-filter"]?.["geoip-code"] ??
DEFAULT_DNS_CONFIG["fallback-filter"]["geoip-code"],
fallbackIpcidr:
config["fallback-filter"]?.ipcidr?.join(", ") ??
DEFAULT_DNS_CONFIG["fallback-filter"].ipcidr.join(", "),
fallbackDomain:
config["fallback-filter"]?.domain?.join(", ") ??
DEFAULT_DNS_CONFIG["fallback-filter"].domain.join(", "),
nameserverPolicy:
formatNameserverPolicy(config["nameserver-policy"]) || "",
});
};
// 重置为默认值
const resetToDefaults = () => {
setValues({
@@ -396,6 +495,7 @@ export const DnsViewer = forwardRef<DialogRef>((props, ref) => {
return dnsConfig;
};
// 处理保存操作
const onSave = useLockFn(async () => {
try {
let dnsConfig;
@@ -412,8 +512,15 @@ export const DnsViewer = forwardRef<DialogRef>((props, ref) => {
dnsConfig = parsedConfig;
}
await patchClash({ dns: dnsConfig });
mutateClash();
// 不直接应用到clash配置,而是保存到单独文件
await invoke("save_dns_config", { dnsConfig });
// 如果DNS开关当前是打开的,则需要应用新的DNS配置
if (clash?.dns?.enable) {
await invoke("apply_dns_config", { apply: true });
mutateClash(); // 刷新UI
}
setOpen(false);
Notice.success(t("DNS settings saved"));
} catch (err: any) {
@@ -497,7 +604,7 @@ export const DnsViewer = forwardRef<DialogRef>((props, ref) => {
overflow: "auto",
...(visualization
? {}
: { padding: 0, display: "flex", flexDirection: "column" }),
: { padding: "0 24px", display: "flex", flexDirection: "column" }),
}}
okBtn={t("Save")}
cancelBtn={t("Cancel")}
@@ -1,4 +1,4 @@
import { useRef } from "react";
import { useRef, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { TextField, Select, MenuItem, Typography } from "@mui/material";
import {
@@ -22,6 +22,9 @@ import { updateGeoData } from "@/services/api";
import { TooltipIcon } from "@/components/base/base-tooltip-icon";
import { NetworkInterfaceViewer } from "./mods/network-interface-viewer";
import { DnsViewer } from "./mods/dns-viewer";
import { invoke } from "@tauri-apps/api/core";
import { useLockFn } from "ahooks";
import { useListen } from "@/hooks/use-listen";
const isWIN = getSystem() === "windows";
@@ -45,6 +48,10 @@ const SettingClash = ({ onError }: Props) => {
const { enable_random_port = false, verge_mixed_port } = verge ?? {};
// 独立跟踪DNS设置开关状态
const [dnsSettingsEnabled, setDnsSettingsEnabled] = useState(false);
const { addListener } = useListen();
const webRef = useRef<DialogRef>(null);
const portRef = useRef<DialogRef>(null);
const ctrlRef = useRef<DialogRef>(null);
@@ -52,6 +59,12 @@ const SettingClash = ({ onError }: Props) => {
const networkRef = useRef<DialogRef>(null);
const dnsRef = useRef<DialogRef>(null);
// 初始化时从verge配置中加载DNS设置开关状态
useEffect(() => {
const dnsSettingsState = verge?.enable_dns_settings ?? false;
setDnsSettingsEnabled(dnsSettingsState);
}, [verge]);
const onSwitchFormat = (_e: any, value: boolean) => value;
const onChangeData = (patch: Partial<IConfigData>) => {
mutateClash((old) => ({ ...(old! || {}), ...patch }), false);
@@ -68,6 +81,25 @@ const SettingClash = ({ onError }: Props) => {
}
};
// 实现DNS设置开关处理函数
const handleDnsToggle = useLockFn(async (enable: boolean) => {
try {
setDnsSettingsEnabled(enable);
await patchVerge({ enable_dns_settings: enable });
await invoke("apply_dns_config", { apply: enable });
setTimeout(() => {
mutateClash();
}, 500); // 延迟500ms确保后端完成处理
} catch (err: any) {
Notice.error(err.message || err.toString());
setDnsSettingsEnabled(!enable);
await patchVerge({ enable_dns_settings: !enable }).catch(() => {
// 忽略恢复状态时的错误
});
throw err;
}
});
return (
<SettingList title={t("Clash Setting")}>
<WebUIViewer ref={webRef} />
@@ -111,16 +143,12 @@ const SettingClash = ({ onError }: Props) => {
/>
}
>
<GuardState
value={dns?.enable ?? false}
valueProps="checked"
onCatch={onError}
onFormat={onSwitchFormat}
onChange={(e) => onChangeData({ dns: { ...dns, enable: e } })}
onGuard={(e) => patchClash({ dns: { enable: e } })}
>
<Switch edge="end" />
</GuardState>
{/* 使用独立状态,不再依赖dns?.enable */}
<Switch
edge="end"
checked={dnsSettingsEnabled}
onChange={(_, checked) => handleDnsToggle(checked)}
/>
</SettingItem>
<SettingItem label={t("IPv6")}>
+2 -3
View File
@@ -194,7 +194,7 @@
"Test URL": "测试地址",
"Settings": "设置",
"System Setting": "系统设置",
"Tun Mode": "TUN虚拟网卡模式",
"Tun Mode": "TUN(虚拟网卡)模式",
"TUN requires Service Mode": "TUN 模式需要服务",
"Install Service": "安装服务",
"Reset to Default": "重置为默认值",
@@ -502,6 +502,5 @@
"Fallback IP CIDR": "回退 IP CIDR",
"IP CIDRs not using fallback servers": "不使用回退服务器的 IP CIDR,用逗号分隔",
"Fallback Domain": "回退域名",
"Domains using fallback servers": "使用回退服务器的域名,用逗号分隔",
"Fallback Geosite": "回退 Geosite"
"Domains using fallback servers": "使用回退服务器的域名,用逗号分隔"
}
+1
View File
@@ -739,6 +739,7 @@ interface IVergeConfig {
enable_silent_start?: boolean;
enable_system_proxy?: boolean;
enable_global_hotkey?: boolean;
enable_dns_settings?: boolean;
proxy_auto_config?: boolean;
pac_file_content?: string;
enable_random_port?: boolean;
@@ -32,6 +32,8 @@ ubootenv_mtdinfo () {
case "$board" in
alfa-network,ap120c-ac|\
alibaba,ap4220-48m|\
alibaba,ap4220-128m|\
devolo,magic-2-wifi-next|\
edgecore,ecw5211|\
glinet,gl-a1300 |\
@@ -17,7 +17,7 @@
+};
--- /dev/null
+++ b/arch/arm/dts/rk3399-fine-3399.dts
@@ -0,0 +1,789 @@
@@ -0,0 +1,799 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
@@ -120,7 +120,7 @@
+ vin-supply = <&vcc_sys>;
+ };
+
+ leds: gpio-leds {
+ gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&user_led2>;
@@ -149,7 +149,7 @@
+
+ fan0: pwm-fan {
+ compatible = "pwm-fan";
+ cooling-levels = <0 25 50 75 100 150>;
+ cooling-levels = <0 30 60 90 120 160>;
+ #cooling-cells = <2>;
+ fan-supply = <&vcc_sys>;
+ pwms = <&pwm1 0 40000 0>;
@@ -215,18 +215,28 @@
+
+&cpu_thermal {
+ trips {
+ cpu_warm: cpu_warm {
+ temperature = <50000>;
+ hysteresis = <2000>;
+ type = "active";
+ };
+
+ cpu_hot: cpu_hot {
+ hysteresis = <10000>;
+ temperature = <55000>;
+ temperature = <65000>;
+ hysteresis = <2000>;
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map2 {
+ cooling-device =
+ <&fan0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ trip = <&cpu_warm>;
+ cooling-device = <&fan0 THERMAL_NO_LIMIT 1>;
+ };
+
+ map3 {
+ trip = <&cpu_hot>;
+ cooling-device = <&fan0 4 THERMAL_NO_LIMIT>;
+ };
+ };
+};
@@ -675,7 +685,7 @@
+ status = "okay";
+
+ panel@0 {
+ compatible = "sitronix,st7735s", "sitronix,st7735r", "sitronix,st7789v", "jianda,jd-t18003-t01";
+ compatible = "jianda,jd-t18003-t01";
+ reg = <0>;
+ rgb;
+ width = <80>;
+2
View File
@@ -28,6 +28,7 @@ endef
# <https://wireless.wiki.kernel.org/en/users/drivers/ath10k/boardfiles>
ALLWIFIBOARDS:= \
alibaba_ap4220 \
aliyun_ap8220 \
arcadyan_aw1000 \
buffalo_wxr-5950ax12 \
@@ -144,6 +145,7 @@ endef
# Place files in this directory as board-<devicename>.<qca4019|qca9888|qca9889|qca9984|qca99x0|ipq8074>
# Add $(eval $(call generate-ipq-wifi-package,<devicename>,<display name>))
$(eval $(call generate-ipq-wifi-package,alibaba_ap4220,Alibaba AP4220))
$(eval $(call generate-ipq-wifi-package,aliyun_ap8220,Aliyun AP8220))
$(eval $(call generate-ipq-wifi-package,arcadyan_aw1000,Arcadyan AW1000))
$(eval $(call generate-ipq-wifi-package,buffalo_wxr-5950ax12,Buffalo WXR-5950AX12))
Binary file not shown.
@@ -39,11 +39,6 @@ if fs.access(storage_info_file) then
end
end
end
option = s:option(DummyValue, "_"..k,translate(k))
option.value = v
end
end
end
openfog_link=s:option(DummyValue, "openfog_link", translate("<input type=\"button\" class=\"cbi-button cbi-button-apply\" value=\"Openfogos.com\" onclick=\"window.open('https://openfogos.com/')\" />"))
openfog_link.description = translate("OpenFogOS Official Website")
@@ -42,6 +42,8 @@ ipq40xx_setup_interfaces()
ucidef_add_switch "switch0" \
"0u@eth0" "2:lan:1" "3:lan:2" "4:lan:3" "0u@eth1" "5:wan"
;;
alibaba,ap4220-48m|\
alibaba,ap4220-128m|\
asus,map-ac2200|\
cilab,meshpoint-one|\
edgecore,ecw5211|\
@@ -170,6 +172,12 @@ ipq40xx_setup_macs()
local label_mac=""
case "$board" in
alibaba,ap4220-48m|\
alibaba,ap4220-128m)
wan_mac=$(mtd_get_mac_text product_info 0x40)
lan_mac=$(macaddr_add "$wan_mac" 1)
label_mac="$wan_mac"
;;
8dev,habanero-dvk)
label_mac=$(mtd_get_mac_binary "ART" 0x1006)
;;
@@ -58,6 +58,11 @@ case "$FIRMWARE" in
qcom,ap-dk01.1-c1)
caldata_extract "ART" 0x1000 0x2f20
;;
alibaba,ap4220|\
alibaba,ap4220-48m)
caldata_extract "ART" 0x1000 0x2f20
ath10k_patch_mac $(macaddr_add "$(mtd_get_mac_text product_info 0x40)" 2)
;;
asus,map-ac2200|\
asus,rt-ac42u|\
asus,rt-ac58u)
@@ -143,6 +148,11 @@ case "$FIRMWARE" in
qcom,ap-dk01.1-c1)
caldata_extract "ART" 0x5000 0x2f20
;;
alibaba,ap4220|\
alibaba,ap4220-48m)
caldata_extract "ART" 0x5000 0x2f20
ath10k_patch_mac $(macaddr_add "$(mtd_get_mac_text product_info 0x40)" 3)
;;
asus,map-ac2200|\
asus,rt-ac58u)
caldata_extract_ubi "Factory" 0x5000 0x2f20
@@ -215,6 +215,8 @@ platform_do_upgrade_mikrotik_nand() {
platform_do_upgrade() {
case "$(board_name)" in
8dev,jalapeno |\
alibaba,ap4220-48m|\
alibaba,ap4220-128m|\
aruba,ap-303 |\
aruba,ap-303h |\
aruba,ap-365 |\
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
#include "qcom-ipq4018-ap4220.dtsi"
/ {
model = "Alibaba AP4220 128M";
compatible = "alibaba,ap4220-128m";
};
&nand_rootfs {
reg = <0x0 0x08000000>;
};
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
#include "qcom-ipq4018-ap4220.dtsi"
/ {
model = "Alibaba AP4220 48M";
compatible = "alibaba,ap4220-48m";
};
&nand_rootfs {
reg = <0x0 0x03000000>;
};
@@ -0,0 +1,349 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
#include "qcom-ipq4019.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/soc/qcom,tcsr.h>
/ {
aliases {
led-boot = &status;
led-failsafe = &status;
led-running = &status;
led-upgrade = &status;
label-mac-device = &gmac0;
};
chosen {
bootargs-append = " root=/dev/ubiblock0_1";
};
soc {
rng@22000 {
status = "okay";
};
ess-psgmii@98000 {
status = "okay";
};
tcsr@1949000 {
compatible = "qcom,tcsr";
reg = <0x1949000 0x100>;
qcom,wifi_glb_cfg = <TCSR_WIFI_GLB_CFG>;
};
tcsr@194b000 {
compatible = "qcom,tcsr";
reg = <0x194b000 0x100>;
qcom,usb-hsphy-mode-select = <TCSR_USB_HSPHY_HOST_MODE>;
};
ess_tcsr@1953000 {
compatible = "qcom,tcsr";
reg = <0x1953000 0x1000>;
qcom,ess-interface-select = <TCSR_ESS_PSGMII>;
};
tcsr@1957000 {
compatible = "qcom,tcsr";
reg = <0x1957000 0x100>;
qcom,wifi_noc_memtype_m0_m2 = <TCSR_WIFI_NOC_MEMTYPE_M0_M2>;
};
usb2@60f8800 {
status = "okay";
};
usb3@8af8800 {
status = "okay";
};
crypto@8e3a000 {
status = "okay";
};
watchdog@b017000 {
status = "okay";
};
ess-switch@c000000 {
status = "okay";
};
edma@c080000 {
status = "okay";
};
};
leds {
compatible = "gpio-leds";
status: status {
label = "green:status";
gpios = <&tlmm 5 GPIO_ACTIVE_LOW>;
default-state = "keep";
};
wlan2g {
label = "green:wlan2g";
gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "phy0tpt";
};
wlan5g {
label = "green:wlan5g";
gpios = <&tlmm 2 GPIO_ACTIVE_LOW>;
linux,default-trigger = "phy1tpt";
};
};
keys {
compatible = "gpio-keys";
reset {
label = "reset";
gpios = <&tlmm 63 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
};
};
&blsp_dma {
status = "okay";
};
&blsp1_spi1 {
status = "okay";
pinctrl-0 = <&spi0_pins>;
pinctrl-names = "default";
cs-gpios = <&tlmm 54 GPIO_ACTIVE_HIGH>,
<&tlmm 4 GPIO_ACTIVE_HIGH>;
flash@0 {
reg = <0>;
compatible = "jedec,spi-nor";
spi-max-frequency = <24000000>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "SBL1";
reg = <0x0 0x40000>;
read-only;
};
partition@40000 {
label = "MIBIB";
reg = <0x40000 0x20000>;
read-only;
};
partition@60000 {
label = "QSEE";
reg = <0x60000 0x60000>;
read-only;
};
partition@c0000 {
label = "CDT";
reg = <0xc0000 0x10000>;
read-only;
};
partition@d0000 {
label = "DDRPARAMS";
reg = <0xd0000 0x10000>;
read-only;
};
partition@e0000 {
label = "APPSBLENV";
reg = <0xe0000 0x10000>;
read-only;
};
partition@f0000 {
label = "APPSBL";
reg = <0xf0000 0x80000>;
read-only;
};
partition@170000 {
label = "ART";
reg = <0x170000 0x10000>;
read-only;
compatible = "nvmem-cells";
#address-cells = <1>;
#size-cells = <1>;
precal_art_1000: precal@1000 {
reg = <0x1000 0x2f20>;
};
precal_art_5000: precal@5000 {
reg = <0x5000 0x2f20>;
};
};
partition@180000 {
label = "product_info";
reg = <0x00180000 0x00010000>;
read-only;
};
partition@190000 {
label = "mtdoops";
reg = <0x00190000 0x00020000>;
read-only;
};
partition@1b0000 {
label = "priv_data1";
reg = <0x001b0000 0x00010000>;
read-only;
};
partition@1c0000 {
label = "priv_data2";
reg = <0x001c0000 0x00010000>;
read-only;
};
partition@1d0000 {
label = "priv_data3";
reg = <0x001d0000 0x00200000>;
read-only;
};
};
};
nand@1 {
compatible = "spi-nand";
reg = <1>;
spi-max-frequency = <24000000>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
nand_rootfs: partition@0 {
label = "rootfs";
/* reg defined in 48M/128M variant dts. */
};
};
};
};
&blsp1_uart1 {
pinctrl-0 = <&serial0_pins>;
pinctrl-names = "default";
status = "okay";
};
&cryptobam {
status = "okay";
};
&qpic_bam {
status = "okay";
};
&mdio {
status = "okay";
};
&tlmm {
mdio_pins: mdio_pinmux {
mux_mdio {
pins = "gpio53";
function = "mdio";
bias-pull-up;
};
mux_mdc {
pins = "gpio52";
function = "mdc";
bias-pull-up;
};
};
enable-usb-power {
gpio-hog;
gpios = <1 GPIO_ACTIVE_HIGH>;
output-low;
line-name = "enable USB2 power";
};
serial0_pins: serial0_pinmux {
mux_uart {
pins = "gpio60", "gpio61";
function = "blsp_uart0";
bias-disable;
};
};
spi0_pins: spi0_pinmux {
mux_spi {
function = "blsp_spi0";
pins = "gpio55", "gpio56", "gpio57";
drive-strength = <12>;
bias-disable;
};
mux_cs {
function = "gpio";
pins = "gpio54", "gpio4";
drive-strength = <2>;
bias-disable;
output-high;
};
};
};
&ethphy3 {
qcom,single-led-1000;
qcom,single-led-100;
qcom,single-led-10;
};
&ethphy4 {
qcom,single-led-1000;
qcom,single-led-100;
qcom,single-led-10;
};
&usb3_ss_phy {
status = "okay";
};
&usb3_hs_phy {
status = "okay";
};
&usb2_hs_phy {
status = "okay";
};
&vqmmc {
status = "okay";
};
&wifi0 {
status = "okay";
nvmem-cell-names = "pre-calibration";
nvmem-cells = <&precal_art_1000>;
qcom,ath10k-calibration-variant = "Alibaba-AP4220";
};
&wifi1 {
status = "okay";
nvmem-cell-names = "pre-calibration";
nvmem-cells = <&precal_art_5000>;
qcom,ath10k-calibration-variant = "Alibaba-AP4220";
};
@@ -164,6 +164,30 @@ define Device/alfa-network_ap120c-ac
endef
TARGET_DEVICES += alfa-network_ap120c-ac
define Device/alibaba_ap4220
$(call Device/FitImage)
$(call Device/UbiFit)
DEVICE_VENDOR := Alibaba
DEVICE_MODEL := AP4220
SOC := qcom-ipq4018
KERNEL_SIZE := 4096k
BLOCKSIZE := 128k
PAGESIZE := 2048
DEVICE_PACKAGES += ipq-wifi-alibaba_ap4220
endef
define Device/alibaba_ap4220-48m
$(call Device/alibaba_ap4220)
DEVICE_VARIANT := 48M
endef
TARGET_DEVICES += alibaba_ap4220-48m
define Device/alibaba_ap4220-128m
$(call Device/alibaba_ap4220)
DEVICE_VARIANT := 128M
endef
TARGET_DEVICES += alibaba_ap4220-128m
define Device/aruba_glenmorangie
$(call Device/FitImageLzma)
DEVICE_VENDOR := Aruba
@@ -10,12 +10,14 @@ Signed-off-by: John Crispin <john@phrozen.org>
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -904,11 +904,77 @@ dtb-$(CONFIG_ARCH_QCOM) += \
@@ -904,11 +904,79 @@ dtb-$(CONFIG_ARCH_QCOM) += \
qcom-apq8074-dragonboard.dtb \
qcom-apq8084-ifc6540.dtb \
qcom-apq8084-mtp.dtb \
+ qcom-ipq4018-a42.dtb \
+ qcom-ipq4018-ap120c-ac.dtb \
+ qcom-ipq4018-ap4220-48m.dtb \
+ qcom-ipq4018-ap4220-128m.dtb \
+ qcom-ipq4018-dap-2610.dtb \
+ qcom-ipq4018-cs-w3-wd1200g-eup.dtb \
+ qcom-ipq4018-magic-2-wifi-next.dtb \
@@ -9,7 +9,7 @@
/ {
model = "RUMU3F Fine3399";
compatible = "rumu3f,fine-3399","rockchip,rk3399";
compatible = "rumu3f,fine-3399", "rockchip,rk3399";
aliases {
ethernet0 = &gmac;
@@ -100,7 +100,7 @@
vin-supply = <&vcc_sys>;
};
leds: gpio-leds {
gpio-leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&user_led2>;
@@ -127,9 +127,9 @@
};
};
fan0: pwm-fan {
fan: pwm-fan {
compatible = "pwm-fan";
cooling-levels = <0 25 50 75 100 150>;
cooling-levels = <0 30 60 90 120 160>;
#cooling-cells = <2>;
fan-supply = <&vcc_sys>;
pwms = <&pwm1 0 40000 0>;
@@ -195,18 +195,28 @@
&cpu_thermal {
trips {
cpu_warm: cpu_warm {
temperature = <50000>;
hysteresis = <2000>;
type = "active";
};
cpu_hot: cpu_hot {
hysteresis = <10000>;
temperature = <55000>;
temperature = <65000>;
hysteresis = <2000>;
type = "active";
};
};
cooling-maps {
map2 {
cooling-device =
<&fan0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
trip = <&cpu_warm>;
cooling-device = <&fan THERMAL_NO_LIMIT 1>;
};
map3 {
trip = <&cpu_hot>;
cooling-device = <&fan 4 THERMAL_NO_LIMIT>;
};
};
};
@@ -656,7 +666,7 @@
status = "okay";
panel@0 {
compatible = "sitronix,st7735s", "sitronix,st7735r", "sitronix,st7789v", "jianda,jd-t18003-t01";
compatible = "jianda,jd-t18003-t01";
reg = <0>;
rgb;
width = <80>;
+2 -1
View File
@@ -458,7 +458,8 @@ define Device/rumu3f_fine-3399
SOC := rk3399
UBOOT_DEVICE_NAME := fine3399-rk3399
IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-img | gzip | append-metadata
DEVICE_PACKAGES := kmod-gpio-button-hotplug kmod-r8168
DEVICE_PACKAGES := brcmfmac-firmware-43430b0-sdio brcmfmac-nvram-43430b0-sdio \
kmod-brcmfmac kmod-gpio-button-hotplug kmod-usb-net-rtl8152 wpad
endef
TARGET_DEVICES += rumu3f_fine-3399
+8 -2
View File
@@ -6,12 +6,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=25.3.2
PKG_VERSION:=25.3.9
PKG_RELEASE:=1
PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
CONFIG_PACKAGE_$(PKG_NAME)_Nftables_Transparent_Proxy \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Geoview \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \
@@ -35,7 +36,7 @@ LUCI_PKGARCH:=all
LUCI_DEPENDS:=+coreutils +coreutils-base64 +coreutils-nohup +curl \
+chinadns-ng +dns2socks +dnsmasq-full +ip-full \
+libuci-lua +lua +luci-compat +luci-lib-jsonc \
+microsocks +resolveip +tcping +geoview
+microsocks +resolveip +tcping
define Package/$(PKG_NAME)/config
menu "Configuration"
@@ -63,6 +64,11 @@ config PACKAGE_$(PKG_NAME)_Nftables_Transparent_Proxy
select PACKAGE_kmod-nft-nat
default y if PACKAGE_firewall4
config PACKAGE_$(PKG_NAME)_INCLUDE_Geoview
bool "Include Geoview"
select PACKAGE_geoview
default y if aarch64||arm||i386||x86_64
config PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy
bool "Include Haproxy"
select PACKAGE_haproxy
@@ -783,7 +783,7 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
}
opt.set(dom_prefix + 'address', server);
opt.set(dom_prefix + 'port', port);
opt.set(dom_prefix + 'password', decodeURIComponent(password) || "");
opt.set(dom_prefix + 'password', password || "");
opt.set(dom_prefix + 'method', method || "");
opt.set(dom_prefix + 'ss_method', method || "");
opt.set(dom_prefix + 'plugin', plugin || "none");
@@ -918,7 +918,7 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
}
opt.set(dom_prefix + 'address', part2[0]);
opt.set(dom_prefix + 'port', part2[1]);
opt.set(dom_prefix + 'password', decodeURIComponent(part1[1]));
opt.set(dom_prefix + 'password', part1[1]);
opt.set(dom_prefix + 'method', method);
opt.set(dom_prefix + 'ss_method', method);
opt.set(dom_prefix + 'plugin', "none");
@@ -601,7 +601,6 @@ local function processData(szType, content, add_mode, add_from)
--ss://2022-blake3-aes-256-gcm:YctPZ6U7xPPcU%2Bgp3u%2B0tx%2FtRizJN9K8y%2BuKlW2qjlI%3D@192.168.100.1:8888/?plugin=v2ray-plugin%3Bserver#Example3
--ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTp0ZXN0@xxxxxx.com:443?type=ws&path=%2Ftestpath&host=xxxxxx.com&security=tls&fp=&alpn=h3%2Ch2%2Chttp%2F1.1&sni=xxxxxx.com#test-1%40ss
--ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTp4eHh4eHhAeHh4eC54eHh4eC5jb206NTYwMDE#Hong%20Kong-01
--ss://MjAyMi1ibGFrZTMtYWVzLTEyOC1nY206WEdXbmhjUFAxb0Z4SXdxRXpRYXBnUSUzRCUzRCUzQTRuWHRlc0w2QnFOZlEyTVh2dnBqdGclM0QlM0Q@test.com:10333/?group=test#grose7ym
local idx_sp = 0
local alias = ""
@@ -667,7 +666,7 @@ local function processData(szType, content, add_mode, add_from)
local method = userinfo:sub(1, userinfo:find(":") - 1)
local password = userinfo:sub(userinfo:find(":") + 1, #userinfo)
result.method = method
result.password = UrlDecode(password)
result.password = password
if ss_type_default == "shadowsocks-rust" and has_ss_rust then
result.type = 'SS-Rust'
@@ -261,6 +261,102 @@ const vless_flow = [
];
/* Prototype */
const CBIGridSection = form.GridSection.extend({
modaltitle(/* ... */) {
return loadModalTitle.call(this, ...this.hm_modaltitle || [null,null], ...arguments)
},
sectiontitle(/* ... */) {
return loadDefaultLabel.call(this, ...arguments);
},
renderSectionAdd(extra_class) {
const prefmt = this.hm_prefmt;
const LC = this.hm_lowcase_only;
let el = form.GridSection.prototype.renderSectionAdd.call(this, extra_class),
nameEl = el.querySelector('.cbi-section-create-name');
ui.addValidator(nameEl, 'uciname', true, (v) => {
let button = el.querySelector('.cbi-section-create > .cbi-button-add');
const prefix = prefmt?.prefix ? prefmt.prefix : '';
const suffix = prefmt?.suffix ? prefmt.suffix : '';
if (!v) {
button.disabled = true;
return true;
} else if (LC && (v !== v.toLowerCase())) {
button.disabled = true;
return _('Expecting: %s').format(_('Lowercase only'));
} else if (uci.get(this.config, v)) {
button.disabled = true;
return _('Expecting: %s').format(_('unique UCI identifier'));
} else if (uci.get(this.config, prefix + v + suffix)) {
button.disabled = true;
return _('Expecting: %s').format(_('unique identifier'));
} else {
button.disabled = null;
return true;
}
}, 'blur', 'keyup');
return el;
},
handleAdd(ev, name) {
const prefmt = this.hm_prefmt;
const prefix = prefmt?.prefix ? prefmt.prefix : '';
const suffix = prefmt?.suffix ? prefmt.suffix : '';
return form.GridSection.prototype.handleAdd.call(this, ev, prefix + name + suffix);
}
});
const CBIhandleImport = baseclass.extend(/** @lends hm.handleImport.prototype */ {
__init__(map, section, title, description) {
this.map = map;
this.section = section;
this.title = title ?? '';
this.description = description ?? '';
this.placeholder = '';
this.handleFn = this.handleFn.bind(this.section);
},
handleFn(textarea, save) {
if (save) {
return uci.save()
.then(L.bind(this.map.load, this.map))
.then(L.bind(this.map.reset, this.map))
.then(L.ui.hideModal)
.catch(() => {});
} else
return ui.hideModal();
},
render() {
const textarea = new ui.Textarea('', {
placeholder: this.placeholder
});
ui.showModal(this.title, [
E('p', this.description),
textarea.render(),
E('div', { class: 'right' }, [
E('button', {
class: 'btn',
click: ui.hideModal
}, [ _('Cancel') ]),
' ',
E('button', {
class: 'btn cbi-button-action',
click: ui.createHandlerFn(this, 'handleFn', textarea)
}, [ _('Import') ])
])
]);
}
});
const CBIDynamicList = form.DynamicList.extend({
__name__: 'CBI.DynamicList',
@@ -294,9 +390,9 @@ const CBIGenValue = form.Value.extend({
node.classList.add('control-group');
(node.querySelector('.control-group') || node).appendChild(E('button', {
'class': 'cbi-button cbi-button-add',
'title': _('Generate'),
'click': ui.createHandlerFn(this, handleGenKey, this.hm_asymmetric || this.option)
class: 'cbi-button cbi-button-add',
title: _('Generate'),
click: ui.createHandlerFn(this, handleGenKey, this.hm_asymmetric || this.option)
}, [ _('Generate') ]));
return node;
@@ -344,12 +440,12 @@ const CBITextValue = form.TextValue.extend({
const UIDynamicList = ui.DynamicList.extend({
addItem(dl, value, text, flash) {
if (this.options.allowduplicates) {
const new_item = E('div', { 'class': flash ? 'item flash' : 'item', 'tabindex': 0, 'draggable': !less_24_10 }, [
const new_item = E('div', { class: flash ? 'item flash' : 'item', tabindex: 0, draggable: !less_24_10 }, [
E('span', {}, [ text ?? value ]),
E('input', {
'type': 'hidden',
'name': this.options.name,
'value': value })]);
type: 'hidden',
name: this.options.name,
value: value })]);
const ai = dl.querySelector('.add-item');
ai.parentNode.insertBefore(new_item, ai);
@@ -660,15 +756,15 @@ function renderStatus(ElId, isRunning, instance, noGlobal) {
return E([
E('button', {
'class': 'cbi-button cbi-button-apply' + (noGlobal ? ' hidden' : ''),
'click': ui.createHandlerFn(this, handleReload, instance)
class: 'cbi-button cbi-button-apply' + (noGlobal ? ' hidden' : ''),
click: ui.createHandlerFn(this, handleReload, instance)
}, [ _('Reload') ]),
updateStatus(E('span', { id: ElId, style: 'border: unset; font-style: italic; font-weight: bold' }), isRunning ? true : false),
E('a', {
'class': 'cbi-button cbi-button-apply %s'.format(visible ? '' : 'hidden'),
'href': visible ? getDashURL(isRunning) : '',
'target': '_blank',
'rel': 'noreferrer noopener'
class: 'cbi-button cbi-button-apply %s'.format(visible ? '' : 'hidden'),
href: visible ? getDashURL(isRunning) : '',
target: '_blank',
rel: 'noreferrer noopener'
}, [ _('Open Dashboard') ])
]);
}
@@ -728,42 +824,6 @@ function renderResDownload(section_id) {
return El;
}
function renderSectionAdd(prefmt, LC, extra_class) {
let el = form.GridSection.prototype.renderSectionAdd.apply(this, [ extra_class ]),
nameEl = el.querySelector('.cbi-section-create-name');
ui.addValidator(nameEl, 'uciname', true, (v) => {
let button = el.querySelector('.cbi-section-create > .cbi-button-add');
const prefix = prefmt?.prefix ? prefmt.prefix : '';
const suffix = prefmt?.suffix ? prefmt.suffix : '';
if (!v) {
button.disabled = true;
return true;
} else if (LC && (v !== v.toLowerCase())) {
button.disabled = true;
return _('Expecting: %s').format(_('Lowercase only'));
} else if (uci.get(this.config, v)) {
button.disabled = true;
return _('Expecting: %s').format(_('unique UCI identifier'));
} else if (uci.get(this.config, prefix + v + suffix)) {
button.disabled = true;
return _('Expecting: %s').format(_('unique identifier'));
} else {
button.disabled = null;
return true;
}
}, 'blur', 'keyup');
return el;
}
function handleAdd(prefmt, ev, name) {
const prefix = prefmt?.prefix ? prefmt.prefix : '';
const suffix = prefmt?.suffix ? prefmt.suffix : '';
return form.GridSection.prototype.handleAdd.apply(this, [ ev, prefix + name + suffix ]);
}
function handleGenKey(option) {
const section_id = this.section.section;
const type = this.section.getOption('type').formvalue(section_id);
@@ -1195,6 +1255,8 @@ return baseclass.extend({
vless_flow,
/* Prototype */
GridSection: CBIGridSection,
handleImport: CBIhandleImport,
DynamicList: CBIDynamicList,
GenValue: CBIGenValue,
ListValue: CBIListValue,
@@ -1222,8 +1284,6 @@ return baseclass.extend({
updateStatus,
getDashURL,
renderResDownload,
renderSectionAdd,
handleAdd,
handleGenKey,
handleReload,
handleRemoveIdles,
@@ -608,17 +608,15 @@ return view.extend({
o.default = o.disabled;
/* Proxy Group */
o = s.taboption('group', form.SectionValue, '_group', form.GridSection, 'proxy_group', null);
o = s.taboption('group', form.SectionValue, '_group', hm.GridSection, 'proxy_group', null);
ss = o.subsection;
var prefmt = { 'prefix': 'group_', 'suffix': '' };
ss.addremove = true;
ss.rowcolors = true;
ss.sortable = true;
ss.nodescriptions = true;
ss.modaltitle = L.bind(hm.loadModalTitle, ss, _('Proxy Group'), _('Add a proxy group'));
ss.sectiontitle = L.bind(hm.loadDefaultLabel, ss);
ss.renderSectionAdd = L.bind(hm.renderSectionAdd, ss, prefmt, true);
ss.handleAdd = L.bind(hm.handleAdd, ss, prefmt);
ss.hm_modaltitle = [ _('Proxy Group'), _('Add a proxy group') ];
ss.hm_prefmt = { 'prefix': 'group_', 'suffix': '' };
ss.hm_lowcase_only = true;
ss.tab('field_general', _('General fields'));
ss.tab('field_override', _('Override fields'));
@@ -816,17 +814,15 @@ return view.extend({
s.tab('rules', _('Routing rule'));
/* Routing rules */
o = s.taboption('rules', form.SectionValue, '_rules', form.GridSection, 'rules', null);
o = s.taboption('rules', form.SectionValue, '_rules', hm.GridSection, 'rules', null);
ss = o.subsection;
var prefmt = { 'prefix': '', 'suffix': '_host' };
ss.addremove = true;
ss.rowcolors = true;
ss.sortable = true;
ss.nodescriptions = true;
ss.modaltitle = L.bind(hm.loadModalTitle, ss, _('Routing rule'), _('Add a routing rule'));
ss.sectiontitle = L.bind(hm.loadDefaultLabel, ss);
ss.renderSectionAdd = L.bind(hm.renderSectionAdd, ss, prefmt, false);
ss.handleAdd = L.bind(hm.handleAdd, ss, prefmt);
ss.hm_modaltitle = [ _('Routing rule'), _('Add a routing rule') ];
ss.hm_prefmt = { 'prefix': '', 'suffix': '_host' };
ss.hm_lowcase_only = false;
so = ss.option(form.Value, 'label', _('Label'));
so.load = L.bind(hm.loadDefaultLabel, so);
@@ -868,17 +864,15 @@ return view.extend({
s.tab('subrules', _('Sub rule'));
/* Sub rules */
o = s.taboption('subrules', form.SectionValue, '_subrules', form.GridSection, 'subrules', null);
o = s.taboption('subrules', form.SectionValue, '_subrules', hm.GridSection, 'subrules', null);
ss = o.subsection;
var prefmt = { 'prefix': '', 'suffix': '_subhost' };
ss.addremove = true;
ss.rowcolors = true;
ss.sortable = true;
ss.nodescriptions = true;
ss.modaltitle = L.bind(hm.loadModalTitle, ss, _('Sub rule'), _('Add a sub rule'));
ss.sectiontitle = L.bind(hm.loadDefaultLabel, ss);
ss.renderSectionAdd = L.bind(hm.renderSectionAdd, ss, prefmt, false);
ss.handleAdd = L.bind(hm.handleAdd, ss, prefmt);
ss.hm_modaltitle = [ _('Sub rule'), _('Add a sub rule') ];
ss.hm_prefmt = { 'prefix': '', 'suffix': '_subhost' };
ss.hm_lowcase_only = false;
so = ss.option(form.Value, 'label', _('Label'));
so.load = L.bind(hm.loadDefaultLabel, so);
@@ -955,17 +949,15 @@ return view.extend({
s.tab('dns_server', _('DNS server'));
/* DNS server */
o = s.taboption('dns_server', form.SectionValue, '_dns_server', form.GridSection, 'dns_server', null);
o = s.taboption('dns_server', form.SectionValue, '_dns_server', hm.GridSection, 'dns_server', null);
ss = o.subsection;
var prefmt = { 'prefix': 'dns_', 'suffix': '' };
ss.addremove = true;
ss.rowcolors = true;
ss.sortable = true;
ss.nodescriptions = true;
ss.modaltitle = L.bind(hm.loadModalTitle, ss, _('DNS server'), _('Add a DNS server'));
ss.sectiontitle = L.bind(hm.loadDefaultLabel, ss);
ss.renderSectionAdd = L.bind(hm.renderSectionAdd, ss, prefmt, true);
ss.handleAdd = L.bind(hm.handleAdd, ss, prefmt);
ss.hm_modaltitle = [ _('DNS server'), _('Add a DNS server') ];
ss.hm_prefmt = { 'prefix': 'dns_', 'suffix': '' };
ss.hm_lowcase_only = true;
so = ss.option(form.Value, 'label', _('Label'));
so.load = L.bind(hm.loadDefaultLabel, so);
@@ -1096,17 +1088,15 @@ return view.extend({
s.tab('dns_policy', _('DNS policy'));
/* DNS policy */
o = s.taboption('dns_policy', form.SectionValue, '_dns_policy', form.GridSection, 'dns_policy', null);
o = s.taboption('dns_policy', form.SectionValue, '_dns_policy', hm.GridSection, 'dns_policy', null);
ss = o.subsection;
var prefmt = { 'prefix': '', 'suffix': '_domain' };
ss.addremove = true;
ss.rowcolors = true;
ss.sortable = true;
ss.nodescriptions = true;
ss.modaltitle = L.bind(hm.loadModalTitle, ss, _('DNS policy'), _('Add a DNS policy'));
ss.sectiontitle = L.bind(hm.loadDefaultLabel, ss);
ss.renderSectionAdd = L.bind(hm.renderSectionAdd, ss, prefmt, false);
ss.handleAdd = L.bind(hm.handleAdd, ss, prefmt);
ss.hm_modaltitle = [ _('DNS policy'), _('Add a DNS policy') ];
ss.hm_prefmt = { 'prefix': '', 'suffix': '_domain' };
ss.hm_lowcase_only = false;
so = ss.option(form.Value, 'label', _('Label'));
so.load = L.bind(hm.loadDefaultLabel, so);
@@ -25,17 +25,15 @@ return view.extend({
s.tab('node', _('Proxy Node'));
/* Proxy Node */
o = s.taboption('node', form.SectionValue, '_node', form.GridSection, 'node', null);
o = s.taboption('node', form.SectionValue, '_node', hm.GridSection, 'node', null);
ss = o.subsection;
var prefmt = { 'prefix': 'node_', 'suffix': '' };
ss.addremove = true;
ss.rowcolors = true;
ss.sortable = true;
ss.nodescriptions = true;
ss.modaltitle = L.bind(hm.loadModalTitle, ss, _('Node'), _('Add a Node'));
ss.sectiontitle = L.bind(hm.loadDefaultLabel, ss);
ss.renderSectionAdd = L.bind(hm.renderSectionAdd, ss, prefmt, true);
ss.handleAdd = L.bind(hm.handleAdd, ss, prefmt);
ss.hm_modaltitle = [ _('Node'), _('Add a Node') ];
ss.hm_prefmt = { 'prefix': 'node_', 'suffix': '' };
ss.hm_lowcase_only = true;
ss.tab('field_general', _('General fields'));
ss.tab('field_tls', _('TLS fields'));
@@ -807,18 +805,18 @@ return view.extend({
s.tab('provider', _('Provider'));
/* Provider */
o = s.taboption('provider', form.SectionValue, '_provider', form.GridSection, 'provider', null);
o = s.taboption('provider', form.SectionValue, '_provider', hm.GridSection, 'provider', null);
ss = o.subsection;
var prefmt = { 'prefix': 'sub_', 'suffix': '' };
ss.addremove = true;
ss.rowcolors = true;
ss.sortable = true;
ss.nodescriptions = true;
ss.modaltitle = L.bind(hm.loadModalTitle, ss, _('Provider'), _('Add a provider'));
ss.sectiontitle = L.bind(hm.loadDefaultLabel, ss);
ss.hm_modaltitle = [ _('Provider'), _('Add a provider') ];
ss.hm_prefmt = { 'prefix': 'sub_', 'suffix': '' };
ss.hm_lowcase_only = false;
/* Remove idle files start */
ss.renderSectionAdd = function(/* ... */) {
let el = hm.renderSectionAdd.apply(this, [prefmt, false].concat(Array.prototype.slice.call(arguments)));
let el = hm.GridSection.prototype.renderSectionAdd.apply(this, arguments);
el.appendChild(E('button', {
'class': 'cbi-button cbi-button-add',
@@ -828,7 +826,6 @@ return view.extend({
return el;
}
ss.handleAdd = L.bind(hm.handleAdd, ss, prefmt);
/* Remove idle files end */
ss.tab('field_general', _('General fields'));
@@ -1075,17 +1072,15 @@ return view.extend({
s.tab('dialer_proxy', _('Proxy chain'));
/* Proxy chain */
o = s.taboption('dialer_proxy', form.SectionValue, '_dialer_proxy', form.GridSection, 'dialer_proxy', null);
o = s.taboption('dialer_proxy', form.SectionValue, '_dialer_proxy', hm.GridSection, 'dialer_proxy', null);
ss = o.subsection;
var prefmt = { 'prefix': 'chain_', 'suffix': '' };
ss.addremove = true;
ss.rowcolors = true;
ss.sortable = true;
ss.nodescriptions = true;
ss.modaltitle = L.bind(hm.loadModalTitle, ss, _('Proxy chain'), _('Add a proxy chain'));
ss.sectiontitle = L.bind(hm.loadDefaultLabel, ss);
ss.renderSectionAdd = L.bind(hm.renderSectionAdd, ss, prefmt, true);
ss.handleAdd = L.bind(hm.handleAdd, ss, prefmt);
ss.hm_modaltitle = [ _('Proxy chain'), _('Add a proxy chain') ];
ss.hm_prefmt = { 'prefix': 'chain_', 'suffix': '' };
ss.hm_lowcase_only = true;
so = ss.option(form.Value, 'label', _('Label'));
so.load = L.bind(hm.loadDefaultLabel, so);
@@ -103,76 +103,58 @@ return view.extend({
/* Rule set START */
/* Rule set settings */
var prefmt = { 'prefix': 'rule_', 'suffix': '' };
s = m.section(form.GridSection, 'ruleset');
s = m.section(hm.GridSection, 'ruleset');
s.addremove = true;
s.rowcolors = true;
s.sortable = true;
s.nodescriptions = true;
s.modaltitle = L.bind(hm.loadModalTitle, s, _('Rule set'), _('Add a rule set'));
s.sectiontitle = L.bind(hm.loadDefaultLabel, s);
s.hm_modaltitle = [ _('Rule set'), _('Add a rule set') ];
s.hm_prefmt = { 'prefix': 'rule_', 'suffix': '' };
s.hm_lowcase_only = false;
/* Import rule-set links and Remove idle files start */
s.handleLinkImport = function() {
let textarea = new ui.Textarea('', {
'placeholder': 'http(s)://github.com/ACL4SSR/ACL4SSR/raw/refs/heads/master/Clash/Providers/BanAD.yaml?fmt=yaml&behav=classical&rawq=good%3Djob#BanAD\n' +
'file:///example.txt?fmt=text&behav=domain&fill=LmNuCg#CN%20TLD\n' +
'inline://LSAnLmhrJwoK?behav=domain#HK%20TLD\n'
});
ui.showModal(_('Import rule-set links'), [
E('p', _('Supports rule-set links of type: <code>%s</code> and format: <code>%s</code>.</br>')
.format('file, http, inline', 'text, yaml, mrs') +
_('Please refer to <a href="%s" target="_blank">%s</a> for link format standards.')
.format(hm.rulesetdoc, _('Ruleset-URI-Scheme'))),
textarea.render(),
E('div', { class: 'right' }, [
E('button', {
class: 'btn',
click: ui.hideModal
}, [ _('Cancel') ]),
' ',
E('button', {
class: 'btn cbi-button-action',
click: ui.createHandlerFn(this, function() {
let input_links = textarea.getValue().trim().split('\n');
if (input_links && input_links[0]) {
/* Remove duplicate lines */
input_links = input_links.reduce((pre, cur) =>
(!pre.includes(cur) && pre.push(cur), pre), []);
const o = new hm.handleImport(this.map, this, _('Import rule-set links'),
_('Supports rule-set links of type: <code>%s</code> and format: <code>%s</code>.</br>')
.format('file, http, inline', 'text, yaml, mrs') +
_('Please refer to <a href="%s" target="_blank">%s</a> for link format standards.')
.format(hm.rulesetdoc, _('Ruleset-URI-Scheme')));
o.placeholder = 'http(s)://github.com/ACL4SSR/ACL4SSR/raw/refs/heads/master/Clash/Providers/BanAD.yaml?fmt=yaml&behav=classical&rawq=good%3Djob#BanAD\n' +
'file:///example.txt?fmt=text&behav=domain&fill=LmNuCg#CN%20TLD\n' +
'inline://LSAnLmhrJwoK?behav=domain#HK%20TLD\n';
o.handleFn = L.bind(function(textarea, save) {
let input_links = textarea.getValue().trim().split('\n');
let imported_count = 0;
if (input_links && input_links[0]) {
/* Remove duplicate lines */
input_links = input_links.reduce((pre, cur) =>
(!pre.includes(cur) && pre.push(cur), pre), []);
let imported_ruleset = 0;
input_links.forEach((l) => {
let config = parseRulesetLink(l);
if (config) {
let sid = uci.add(data[0], 'ruleset', config.id);
config.id = null;
Object.keys(config).forEach((k) => {
uci.set(data[0], sid, k, config[k] || '');
});
imported_ruleset++;
}
});
input_links.forEach((l) => {
let config = parseRulesetLink(l);
if (config) {
let sid = uci.add(data[0], 'ruleset', config.id);
config.id = null;
Object.keys(config).forEach((k) => {
uci.set(data[0], sid, k, config[k] || '');
});
imported_count++;
}
});
if (imported_ruleset === 0)
ui.addNotification(null, E('p', _('No valid rule-set link found.')));
else
ui.addNotification(null, E('p', _('Successfully imported %s rule-set of total %s.').format(
imported_ruleset, input_links.length)));
if (imported_count === 0)
ui.addNotification(null, E('p', _('No valid rule-set link found.')));
else
ui.addNotification(null, E('p', _('Successfully imported %s rule-set of total %s.').format(
imported_count, input_links.length)));
}
return uci.save()
.then(L.bind(this.map.load, this.map))
.then(L.bind(this.map.reset, this.map))
.then(L.ui.hideModal)
.catch(() => {});
} else {
return ui.hideModal();
}
})
}, [ _('Import') ])
])
])
return hm.handleImport.prototype.handleFn.call(this, textarea, imported_count);
}, this);
return o.render();
}
s.renderSectionAdd = function(/* ... */) {
let el = hm.renderSectionAdd.apply(this, [prefmt, false].concat(Array.prototype.slice.call(arguments)));
let el = hm.GridSection.prototype.renderSectionAdd.apply(this, arguments);
el.appendChild(E('button', {
'class': 'cbi-button cbi-button-add',
@@ -188,7 +170,6 @@ return view.extend({
return el;
}
s.handleAdd = L.bind(hm.handleAdd, s, prefmt);
/* Import rule-set links and Remove idle files end */
o = s.option(form.Value, 'label', _('Label'));
@@ -54,16 +54,14 @@ return view.extend({
o.default = o.disabled;
/* Server settings START */
s = m.section(form.GridSection, 'server', null);
var prefmt = { 'prefix': 'server_', 'suffix': '' };
s = m.section(hm.GridSection, 'server', null);
s.addremove = true;
s.rowcolors = true;
s.sortable = true;
s.nodescriptions = true;
s.modaltitle = L.bind(hm.loadModalTitle, s, _('Server'), _('Add a server'));
s.sectiontitle = L.bind(hm.loadDefaultLabel, s);
s.renderSectionAdd = L.bind(hm.renderSectionAdd, s, prefmt, false);
s.handleAdd = L.bind(hm.handleAdd, s, prefmt);
s.hm_modaltitle = [ _('Server'), _('Add a server') ];
s.hm_prefmt = { 'prefix': 'server_', 'suffix': '' };
s.hm_lowcase_only = false;
s.tab('field_general', _('General fields'));
s.tab('field_tls', _('TLS fields'));
+1 -1
View File
@@ -1,6 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_VERSION:=1.20.1
PKG_VERSION:=1.20.2
LUCI_TITLE:=LuCI Support for nikki
LUCI_DEPENDS:=+luci-base +nikki
@@ -3,6 +3,7 @@
'require view';
'require uci';
'require fs';
'require network';
'require poll';
'require tools.widgets as widgets';
'require tools.nikki as nikki';
@@ -10,10 +11,14 @@
return view.extend({
load: function () {
return Promise.all([
uci.load('nikki')
uci.load('nikki'),
network.getNetworks(),
]);
},
render: function (data) {
const networks = data[1];
let m, s, o, so;
m = new form.Map('nikki');
@@ -24,6 +29,7 @@ return view.extend({
o = s.taboption('general', form.ListValue, 'log_level', _('Log Level'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('silent');
o.value('error');
o.value('warning');
@@ -32,48 +38,66 @@ return view.extend({
o = s.taboption('general', form.ListValue, 'mode', _('Mode'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('global', _('Global Mode'));
o.value('rule', _('Rule Mode'));
o.value('direct', _('Direct Mode'));
o = s.taboption('general', form.ListValue, 'match_process', _('Match Process'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('off');
o.value('strict');
o.value('always');
o = s.taboption('general', widgets.NetworkSelect, 'outbound_interface', _('Outbound Interface'));
o = s.taboption('general', form.ListValue, 'outbound_interface', _('Outbound Interface'));
o.optional = true;
o.placeholder = _('Unmodified');
for (const network of networks) {
if (network.getName() === 'loopback') {
continue;
}
o.value(network.getName());
}
o = s.taboption('general', form.ListValue, 'ipv6', _('IPv6'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('general', form.ListValue, 'unify_delay', _('Unify Delay'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('general', form.ListValue, 'tcp_concurrent', _('TCP Concurrent'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('general', form.Value, 'tcp_keep_alive_idle', _('TCP Keep Alive Idle'));
o.datatype = 'uinteger';
o.placeholder = _('Unmodified');
o = s.taboption('general', form.Value, 'tcp_keep_alive_interval', _('TCP Keep Alive Interval'));
o.datatype = 'uinteger';
o.placeholder = _('Unmodified');
s.tab('external_control', _('External Control Config'));
o = s.taboption('external_control', form.Value, 'ui_path', '*' + ' ' + _('UI Path'));
o.placeholder = _('Unmodified');
o.rmempty = false;
o = s.taboption('external_control', form.Value, 'ui_name', _('UI Name'));
o.placeholder = _('Unmodified');
o = s.taboption('external_control', form.Value, 'ui_url', _('UI Url'));
o.placeholder = _('Unmodified');
o.value('https://github.com/Zephyruso/zashboard/archive/refs/heads/gh-pages.zip', 'Zashboard');
o.value('https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip', 'MetaCubeXD');
o.value('https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip', 'YACD');
@@ -81,13 +105,16 @@ return view.extend({
o = s.taboption('external_control', form.Value, 'api_listen', '*' + ' ' + _('API Listen'));
o.datatype = 'ipaddrport(1)';
o.placeholder = _('Unmodified');
o.rmempty = false;
o = s.taboption('external_control', form.Value, 'api_secret', _('API Secret'));
o.password = true;
o.placeholder = _('Unmodified');
o = s.taboption('external_control', form.ListValue, 'selection_cache', _('Save Proxy Selection'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
@@ -95,24 +122,30 @@ return view.extend({
o = s.taboption('inbound', form.ListValue, 'allow_lan', _('Allow Lan'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('inbound', form.Value, 'http_port', _('HTTP Port'));
o.datatype = 'port';
o.placeholder = _('Unmodified');
o = s.taboption('inbound', form.Value, 'socks_port', _('SOCKS Port'));
o.datatype = 'port';
o.placeholder = _('Unmodified');
o = s.taboption('inbound', form.Value, 'mixed_port', _('Mixed Port'));
o.datatype = 'port';
o.placeholder = _('Unmodified');
o = s.taboption('inbound', form.Value, 'redir_port', '*' + ' ' + _('Redirect Port'));
o.datatype = 'port';
o.placeholder = _('Unmodified');
o.rmempty = false;
o = s.taboption('inbound', form.Value, 'tproxy_port', '*' + ' ' + _('TPROXY Port'));
o.datatype = 'port';
o.placeholder = _('Unmodified');
o.rmempty = false;
o = s.taboption('inbound', form.Flag, 'authentication', _('Overwrite Authentication'));
@@ -139,27 +172,33 @@ return view.extend({
s.tab('tun', _('TUN Config'));
o = s.taboption('tun', form.Value, 'tun_device', '*' + ' ' + _('Device Name'));
o.placeholder = _('Unmodified');
o.rmempty = false;
o = s.taboption('tun', form.ListValue, 'tun_stack', _('Stack'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('system', 'System');
o.value('gvisor', 'gVisor');
o.value('mixed', 'Mixed');
o = s.taboption('tun', form.Value, 'tun_mtu', _('MTU'));
o.datatype = 'uinteger';
o.placeholder = _('Unmodified');
o = s.taboption('tun', form.ListValue, 'tun_gso', _('GSO'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('tun', form.Value, 'tun_gso_max_size', _('GSO Max Size'));
o.datatype = 'uinteger';
o.placeholder = _('Unmodified');
o = s.taboption('tun', form.ListValue, 'tun_endpoint_independent_nat', _('Endpoint Independent NAT'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
@@ -176,19 +215,23 @@ return view.extend({
o = s.taboption('dns', form.Value, 'dns_listen', '*' + ' ' + _('DNS Listen'));
o.datatype = 'ipaddrport(1)';
o.placeholder = _('Unmodified');
o.rmempty = false;
o = s.taboption('dns', form.ListValue, 'dns_ipv6', _('IPv6'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('dns', form.ListValue, 'dns_mode', '*' + ' ' + _('DNS Mode'));
o.placeholder = _('Unmodified');
o.value('redir-host', 'Redir-Host');
o.value('fake-ip', 'Fake-IP');
o = s.taboption('dns', form.Value, 'fake_ip_range', '*' + ' ' + _('Fake-IP Range'));
o.datatype = 'cidr4';
o.placeholder = _('Unmodified');
o.retain = true;
o.rmempty = false;
o.depends('dns_mode', 'fake-ip');
@@ -202,31 +245,37 @@ return view.extend({
o = s.taboption('dns', form.ListValue, 'fake_ip_filter_mode', _('Fake-IP Filter Mode'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('blacklist', _('Block Mode'));
o.value('whitelist', _('Allow Mode'));
o = s.taboption('dns', form.ListValue, 'fake_ip_cache', _('Fake-IP Cache'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('dns', form.ListValue, 'dns_respect_rules', _('Respect Rules'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('dns', form.ListValue, 'dns_doh_prefer_http3', _('DoH Prefer HTTP/3'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('dns', form.ListValue, 'dns_system_hosts', _('Use System Hosts'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('dns', form.ListValue, 'dns_hosts', _('Use Hosts'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
@@ -295,16 +344,19 @@ return view.extend({
o = s.taboption('sniffer', form.ListValue, 'sniffer', _('Enable'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('sniffer', form.ListValue, 'sniffer_sniff_dns_mapping', _('Sniff Redir-Host'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('sniffer', form.ListValue, 'sniffer_sniff_pure_ip', _('Sniff Pure IP'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
@@ -464,29 +516,37 @@ return view.extend({
o = s.taboption('geox', form.ListValue, 'geoip_format', _('GeoIP Format'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('dat', 'DAT');
o.value('mmdb', 'MMDB');
o = s.taboption('geox', form.ListValue, 'geodata_loader', _('GeoData Loader'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('standard', _('Standard Loader'));
o.value('memconservative', _('Memory Conservative Loader'));
o = s.taboption('geox', form.Value, 'geosite_url', _('GeoSite Url'));
o.placeholder = _('Unmodified');
o = s.taboption('geox', form.Value, 'geoip_mmdb_url', _('GeoIP(MMDB) Url'));
o.placeholder = _('Unmodified');
o = s.taboption('geox', form.Value, 'geoip_dat_url', _('GeoIP(DAT) Url'));
o.placeholder = _('Unmodified');
o = s.taboption('geox', form.Value, 'geoip_asn_url', _('GeoIP(ASN) Url'));
o.placeholder = _('Unmodified');
o = s.taboption('geox', form.ListValue, 'geox_auto_update', _('GeoX Auto Update'));
o.optional = true;
o.placeholder = _('Unmodified');
o.value('0', _('Disable'));
o.value('1', _('Enable'));
o = s.taboption('geox', form.Value, 'geox_update_interval', _('GeoX Update Interval'));
o.datatype = 'uinteger';
o.placeholder = _('Unmodified');
s.tab('mixin_file_content', _('Mixin File Content'));
@@ -11,14 +11,16 @@ return view.extend({
return Promise.all([
uci.load('nikki'),
network.getHostHints(),
network.getNetworks(),
nikki.getUsers(),
nikki.getGroups()
]);
},
render: function (data) {
const hosts = data[1].hosts;
const users = data[2];
const groups = data[3];
const networks = data[2];
const users = data[3];
const groups = data[4];
let m, s, o;
@@ -108,13 +110,20 @@ return view.extend({
o.value(mac, hint ? '%s (%s)'.format(mac, hint) : mac);
};
o = s.taboption('access_control', widgets.NetworkSelect, 'acl_interface', _('Interface'));
o = s.taboption('access_control', form.DynamicList, 'acl_interface', _('Interface'));
o.multiple = true;
o.optional = true;
o.retain = true;
o.depends('access_control_mode', 'allow');
o.depends('access_control_mode', 'block');
for (const network of networks) {
if (network.getName() === 'loopback') {
continue;
}
o.value(network.getName());
}
s.tab('bypass', _('Bypass'));
o = s.taboption('bypass', form.MultiValue, 'bypass_user', _('Bypass User'));
+248 -197
View File
@@ -1,33 +1,33 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:82
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:106
msgid "API Listen"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:86
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:111
msgid "API Secret"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:64
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:66
msgid "Access Control"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:67
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:69
msgid "All Mode"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:139
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:144
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:148
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:153
msgid "All Port"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:96
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:123
msgid "Allow Lan"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:206
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:68
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:250
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:70
msgid "Allow Mode"
msgstr ""
@@ -44,40 +44,40 @@ msgstr ""
msgid "App Version"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:419
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:471
msgid "Append Rule"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:350
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:402
msgid "Append Rule Provider"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:406
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:458
msgid "Behavior"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:205
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:69
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:249
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:71
msgid "Block Mode"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:118
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:127
msgid "Bypass"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:134
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:143
msgid "Bypass China Mainland IP"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:147
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:156
msgid "Bypass DSCP"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:127
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:136
msgid "Bypass Group"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:120
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:129
msgid "Bypass User"
msgstr ""
@@ -94,8 +94,8 @@ msgstr ""
msgid "Clear Log"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:140
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:145
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:149
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:154
msgid "Commonly Used Port"
msgstr ""
@@ -119,15 +119,15 @@ msgstr ""
msgid "Cron Expression"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:175
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:214
msgid "DNS Config"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:177
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:216
msgid "DNS Listen"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:186
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:227
msgid "DNS Mode"
msgstr ""
@@ -135,51 +135,51 @@ msgstr ""
msgid "Debug Log"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:441
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:493
msgid "Destination IP"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:445
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:497
msgid "Destination IP Geo"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:442
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:494
msgid "Destination Port"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:137
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:146
msgid "Destination TCP Port to Proxy"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:142
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:151
msgid "Destination UDP Port to Proxy"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:141
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:174
msgid "Device Name"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:37
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:44
msgid "Direct Mode"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:50
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:55
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:60
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:91
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:98
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:155
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:163
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:183
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:210
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:215
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:220
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:225
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:230
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:298
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:303
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:308
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:485
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:67
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:73
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:79
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:118
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:126
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:192
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:202
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:224
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:255
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:261
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:267
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:273
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:279
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:348
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:354
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:360
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:544
msgid "Disable"
msgstr ""
@@ -199,60 +199,60 @@ msgstr ""
msgid "Disable Safe Path Check"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:218
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:264
msgid "DoH Prefer HTTP/3"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:247
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:437
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:296
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:489
msgid "Domain Name"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:444
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:496
msgid "Domain Name Geo"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:439
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:491
msgid "Domain Name Keyword"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:440
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:492
msgid "Domain Name Regex"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:438
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:490
msgid "Domain Name Suffix"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:121
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:154
msgid "Edit Authentications"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:169
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:208
msgid "Edit DNS Hijacks"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:199
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:242
msgid "Edit Fake-IP Filters"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:236
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:285
msgid "Edit Hosts"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:278
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:327
msgid "Edit Nameserver Policies"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:255
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:304
msgid "Edit Nameservers"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:353
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:405
msgid "Edit Rule Providers"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:422
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:474
msgid "Edit Rules"
msgstr ""
@@ -266,37 +266,37 @@ msgid "Editor"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/app.js:95
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:51
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:56
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:61
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:92
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:99
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:129
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:156
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:164
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:184
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:211
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:216
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:221
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:226
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:231
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:244
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:263
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:286
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:296
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:299
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:304
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:309
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:333
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:68
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:74
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:80
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:119
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:127
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:162
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:193
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:203
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:225
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:256
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:262
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:268
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:274
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:280
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:293
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:312
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:335
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:345
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:349
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:355
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:361
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:430
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:486
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:493
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:31
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:385
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:413
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:482
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:545
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:553
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:33
msgid "Enable"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:161
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:199
msgid "Endpoint Independent NAT"
msgstr ""
@@ -304,23 +304,23 @@ msgstr ""
msgid "Expire At"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:69
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:90
msgid "External Control Config"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:208
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:252
msgid "Fake-IP Cache"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:203
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:246
msgid "Fake-IP Filter Mode"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:55
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:57
msgid "Fake-IP Ping Hijack"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:190
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:232
msgid "Fake-IP Range"
msgstr ""
@@ -328,15 +328,15 @@ msgstr ""
msgid "Fast Reload"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:400
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:452
msgid "File Format"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:394
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:446
msgid "File Path"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:388
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:440
msgid "File Size Limit"
msgstr ""
@@ -357,19 +357,19 @@ msgstr ""
msgid "File:"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:314
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:366
msgid "Force Sniff Domain Name"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:153
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:189
msgid "GSO"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:158
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:195
msgid "GSO Max Size"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:23
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:28
msgid "General Config"
msgstr ""
@@ -377,43 +377,43 @@ msgstr ""
msgid "Generate & Download"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:470
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:523
msgid "GeoData Loader"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:465
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:517
msgid "GeoIP Format"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:481
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:538
msgid "GeoIP(ASN) Url"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:479
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:535
msgid "GeoIP(DAT) Url"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:477
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:532
msgid "GeoIP(MMDB) Url"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:475
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:529
msgid "GeoSite Url"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:483
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:541
msgid "GeoX Auto Update"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:463
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:515
msgid "GeoX Config"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:488
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:547
msgid "GeoX Update Interval"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:35
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:42
msgid "Global Mode"
msgstr ""
@@ -421,7 +421,7 @@ msgstr ""
msgid "Grant access to nikki procedures"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:101
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:129
msgid "HTTP Port"
msgstr ""
@@ -429,44 +429,44 @@ msgstr ""
msgid "How To Use"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:250
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:299
msgid "IP"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:43
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:45
msgid "IPv4 DNS Hijack"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:49
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:51
msgid "IPv4 Proxy"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:48
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:181
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:64
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:221
msgid "IPv6"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:46
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:48
msgid "IPv6 DNS Hijack"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:52
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:54
msgid "IPv6 Proxy"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:320
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:372
msgid "Ignore Sniff Domain Name"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:94
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:121
msgid "Inbound Config"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:111
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:113
msgid "Interface"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:61
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:63
msgid "Lan Proxy"
msgstr ""
@@ -479,28 +479,28 @@ msgstr ""
msgid "Log"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:25
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:30
msgid "Log Level"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:150
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:185
msgid "MTU"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:39
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:46
msgid "Match Process"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:289
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:447
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:338
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:499
msgid "Matcher"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:473
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:527
msgid "Memory Conservative Loader"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:107
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:137
msgid "Mixed Port"
msgstr ""
@@ -508,25 +508,25 @@ msgstr ""
msgid "Mixin Config"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:491
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:551
msgid "Mixin File Content"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:21
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:26
msgid "Mixin Option"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:33
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:66
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:39
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:68
msgid "Mode"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:367
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:419
msgid "Name"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:273
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:292
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:322
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:341
msgid "Nameserver"
msgstr ""
@@ -535,12 +535,12 @@ msgstr ""
msgid "Nikki"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:457
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:509
msgid "No Resolve"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:381
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:450
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:433
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:502
msgid "Node"
msgstr ""
@@ -552,59 +552,59 @@ msgstr ""
msgid "Open Dashboard"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:45
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:53
msgid "Outbound Interface"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:118
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:151
msgid "Overwrite Authentication"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:166
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:205
msgid "Overwrite DNS Hijack"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:345
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:397
msgid "Overwrite Destination"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:196
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:239
msgid "Overwrite Fake-IP Filter"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:311
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:363
msgid "Overwrite Force Sniff Domain Name"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:233
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:282
msgid "Overwrite Hosts"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:317
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:369
msgid "Overwrite Ignore Sniff Domain Name"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:252
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:301
msgid "Overwrite Nameserver"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:275
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:324
msgid "Overwrite Nameserver Policy"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:323
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:375
msgid "Overwrite Sniff By Protocol"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:135
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:168
msgid "Password"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:493
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:553
msgid "Please go to the editor tab to edit the file for mixin"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:342
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:394
msgid "Port"
msgstr ""
@@ -612,7 +612,7 @@ msgstr ""
msgid "Prefer"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:443
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:495
msgid "Process Name"
msgstr ""
@@ -625,11 +625,11 @@ msgstr ""
msgid "Profile for Startup"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:336
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:388
msgid "Protocol"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:27
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:29
#: applications/luci-app-nikki/root/usr/share/luci/menu.d/luci-app-nikki.json:37
msgid "Proxy Config"
msgstr ""
@@ -638,11 +638,11 @@ msgstr ""
msgid "Proxy Provider:"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:35
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:37
msgid "Redirect Mode"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:110
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:141
msgid "Redirect Port"
msgstr ""
@@ -654,7 +654,7 @@ msgstr ""
msgid "Remote"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:213
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:258
msgid "Respect Rules"
msgstr ""
@@ -662,15 +662,15 @@ msgstr ""
msgid "Restart Service"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:58
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:60
msgid "Router Proxy"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:348
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:400
msgid "Rule Config"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:36
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:43
msgid "Rule Mode"
msgstr ""
@@ -678,7 +678,7 @@ msgstr ""
msgid "Rule Provider:"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:436
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:488
msgid "Rule Set"
msgstr ""
@@ -686,11 +686,11 @@ msgstr ""
msgid "Running"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:104
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:133
msgid "SOCKS Port"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:89
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:115
msgid "Save Proxy Selection"
msgstr ""
@@ -703,27 +703,27 @@ msgstr ""
msgid "Scroll To Bottom"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:326
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:378
msgid "Sniff By Protocol"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:306
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:357
msgid "Sniff Pure IP"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:301
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:351
msgid "Sniff Redir-Host"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:294
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:343
msgid "Sniffer Config"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:144
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:178
msgid "Stack"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:472
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:526
msgid "Standard Loader"
msgstr ""
@@ -752,37 +752,37 @@ msgstr ""
msgid "Subscription:"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:58
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:76
msgid "TCP Concurrent"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:63
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:82
msgid "TCP Keep Alive Idle"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:66
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:86
msgid "TCP Keep Alive Interval"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:34
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:36
msgid "TCP Proxy Mode"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:36
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:40
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:38
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:42
msgid "TPROXY Mode"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:114
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:146
msgid "TPROXY Port"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:139
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:172
msgid "TUN Config"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:37
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:41
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:39
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:43
msgid "TUN Mode"
msgstr ""
@@ -794,7 +794,7 @@ msgstr ""
msgid "Total"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:29
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:31
msgid "Transparent Proxy"
msgstr ""
@@ -802,32 +802,83 @@ msgstr ""
msgid "Transparent Proxy with Mihomo on OpenWrt."
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:266
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:370
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:434
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:315
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:422
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:486
msgid "Type"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:39
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:41
msgid "UDP Proxy Mode"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:74
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:96
msgid "UI Name"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:71
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:92
msgid "UI Path"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:76
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:99
msgid "UI Url"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:53
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:70
msgid "Unify Delay"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:32
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:41
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:48
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:55
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:66
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:72
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:78
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:84
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:88
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:93
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:97
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:100
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:108
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:113
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:117
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:125
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:131
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:135
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:139
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:143
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:148
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:175
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:180
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:187
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:191
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:197
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:201
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:218
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:223
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:228
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:234
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:248
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:254
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:260
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:266
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:272
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:278
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:347
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:353
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:359
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:519
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:525
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:530
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:533
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:536
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:539
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:543
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:549
msgid "Unmodified"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/profile.js:60
msgid "Update"
msgstr ""
@@ -840,7 +891,7 @@ msgstr ""
msgid "Update Dashboard"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:413
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:465
msgid "Update Interval"
msgstr ""
@@ -848,15 +899,15 @@ msgstr ""
msgid "Upload Profile"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:376
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:428
msgid "Url"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:228
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:276
msgid "Use Hosts"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:223
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:270
msgid "Use System Hosts"
msgstr ""
@@ -868,6 +919,6 @@ msgstr ""
msgid "User Agent"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:132
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:165
msgid "Username"
msgstr ""
+248 -197
View File
@@ -8,33 +8,33 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:82
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:106
msgid "API Listen"
msgstr "API 监听"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:86
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:111
msgid "API Secret"
msgstr "API 密钥"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:64
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:66
msgid "Access Control"
msgstr "访问控制"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:67
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:69
msgid "All Mode"
msgstr "全部模式"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:139
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:144
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:148
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:153
msgid "All Port"
msgstr "全部端口"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:96
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:123
msgid "Allow Lan"
msgstr "允许局域网访问"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:206
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:68
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:250
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:70
msgid "Allow Mode"
msgstr "白名单模式"
@@ -51,40 +51,40 @@ msgstr "插件日志"
msgid "App Version"
msgstr "插件版本"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:419
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:471
msgid "Append Rule"
msgstr "追加规则"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:350
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:402
msgid "Append Rule Provider"
msgstr "追加规则提供者"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:406
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:458
msgid "Behavior"
msgstr "行为"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:205
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:69
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:249
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:71
msgid "Block Mode"
msgstr "黑名单模式"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:118
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:127
msgid "Bypass"
msgstr "绕过"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:134
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:143
msgid "Bypass China Mainland IP"
msgstr "绕过中国大陆 IP"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:147
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:156
msgid "Bypass DSCP"
msgstr "绕过 DSCP"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:127
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:136
msgid "Bypass Group"
msgstr "绕过用户组"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:120
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:129
msgid "Bypass User"
msgstr "绕过用户"
@@ -101,8 +101,8 @@ msgstr "选择配置文件"
msgid "Clear Log"
msgstr "清空日志"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:140
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:145
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:149
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:154
msgid "Commonly Used Port"
msgstr "常用端口"
@@ -126,15 +126,15 @@ msgstr "核心版本"
msgid "Cron Expression"
msgstr "Cron 表达式"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:175
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:214
msgid "DNS Config"
msgstr "DNS 配置"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:177
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:216
msgid "DNS Listen"
msgstr "DNS 监听"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:186
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:227
msgid "DNS Mode"
msgstr "DNS 模式"
@@ -142,51 +142,51 @@ msgstr "DNS 模式"
msgid "Debug Log"
msgstr "调试日志"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:441
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:493
msgid "Destination IP"
msgstr "目标 IP"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:445
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:497
msgid "Destination IP Geo"
msgstr "目标 IPGeo"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:442
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:494
msgid "Destination Port"
msgstr "目标端口"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:137
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:146
msgid "Destination TCP Port to Proxy"
msgstr "要代理的 TCP 目标端口"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:142
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:151
msgid "Destination UDP Port to Proxy"
msgstr "要代理的 UDP 目标端口"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:141
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:174
msgid "Device Name"
msgstr "设备名称"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:37
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:44
msgid "Direct Mode"
msgstr "直连模式"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:50
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:55
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:60
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:91
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:98
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:155
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:163
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:183
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:210
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:215
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:220
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:225
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:230
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:298
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:303
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:308
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:485
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:67
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:73
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:79
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:118
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:126
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:192
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:202
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:224
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:255
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:261
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:267
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:273
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:279
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:348
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:354
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:360
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:544
msgid "Disable"
msgstr "禁用"
@@ -206,60 +206,60 @@ msgstr "禁用回环检测"
msgid "Disable Safe Path Check"
msgstr "禁用安全路径检查"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:218
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:264
msgid "DoH Prefer HTTP/3"
msgstr "DoH 优先 HTTP/3"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:247
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:437
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:296
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:489
msgid "Domain Name"
msgstr "域名"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:444
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:496
msgid "Domain Name Geo"
msgstr "域名(Geo"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:439
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:491
msgid "Domain Name Keyword"
msgstr "域名(关键字)"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:440
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:492
msgid "Domain Name Regex"
msgstr "域名(正则表达式)"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:438
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:490
msgid "Domain Name Suffix"
msgstr "域名(后缀)"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:121
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:154
msgid "Edit Authentications"
msgstr "编辑身份验证"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:169
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:208
msgid "Edit DNS Hijacks"
msgstr "编辑 DNS 劫持"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:199
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:242
msgid "Edit Fake-IP Filters"
msgstr "编辑 Fake-IP 过滤列表"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:236
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:285
msgid "Edit Hosts"
msgstr "编辑 Hosts"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:278
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:327
msgid "Edit Nameserver Policies"
msgstr "编辑 DNS 服务器查询策略"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:255
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:304
msgid "Edit Nameservers"
msgstr "编辑 DNS 服务器"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:353
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:405
msgid "Edit Rule Providers"
msgstr "编辑规则提供者"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:422
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:474
msgid "Edit Rules"
msgstr "编辑规则"
@@ -273,37 +273,37 @@ msgid "Editor"
msgstr "编辑器"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/app.js:95
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:51
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:56
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:61
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:92
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:99
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:129
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:156
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:164
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:184
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:211
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:216
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:221
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:226
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:231
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:244
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:263
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:286
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:296
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:299
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:304
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:309
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:333
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:68
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:74
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:80
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:119
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:127
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:162
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:193
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:203
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:225
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:256
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:262
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:268
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:274
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:280
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:293
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:312
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:335
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:345
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:349
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:355
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:361
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:430
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:486
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:493
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:31
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:385
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:413
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:482
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:545
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:553
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:33
msgid "Enable"
msgstr "启用"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:161
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:199
msgid "Endpoint Independent NAT"
msgstr "独立于端点的 NAT"
@@ -311,23 +311,23 @@ msgstr "独立于端点的 NAT"
msgid "Expire At"
msgstr "到期时间"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:69
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:90
msgid "External Control Config"
msgstr "外部控制配置"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:208
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:252
msgid "Fake-IP Cache"
msgstr "Fake-IP 缓存"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:203
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:246
msgid "Fake-IP Filter Mode"
msgstr "Fake-IP 过滤模式"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:55
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:57
msgid "Fake-IP Ping Hijack"
msgstr "Fake-IP Ping 劫持"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:190
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:232
msgid "Fake-IP Range"
msgstr "Fake-IP 范围"
@@ -335,15 +335,15 @@ msgstr "Fake-IP 范围"
msgid "Fast Reload"
msgstr "快速重载"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:400
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:452
msgid "File Format"
msgstr "文件格式"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:394
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:446
msgid "File Path"
msgstr "文件路径"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:388
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:440
msgid "File Size Limit"
msgstr "文件大小限制"
@@ -364,19 +364,19 @@ msgstr "IPv6 保留地址"
msgid "File:"
msgstr "文件:"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:314
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:366
msgid "Force Sniff Domain Name"
msgstr "强制嗅探的域名"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:153
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:189
msgid "GSO"
msgstr "通用分段卸载"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:158
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:195
msgid "GSO Max Size"
msgstr "分段最大长度"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:23
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:28
msgid "General Config"
msgstr "全局配置"
@@ -384,43 +384,43 @@ msgstr "全局配置"
msgid "Generate & Download"
msgstr "生成并下载"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:470
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:523
msgid "GeoData Loader"
msgstr "GeoData 加载器"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:465
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:517
msgid "GeoIP Format"
msgstr "GeoIP 格式"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:481
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:538
msgid "GeoIP(ASN) Url"
msgstr "GeoIP(ASN) 下载地址"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:479
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:535
msgid "GeoIP(DAT) Url"
msgstr "GeoIP(DAT) 下载地址"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:477
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:532
msgid "GeoIP(MMDB) Url"
msgstr "GeoIP(MMDB) 下载地址"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:475
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:529
msgid "GeoSite Url"
msgstr "GeoSite 下载地址"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:483
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:541
msgid "GeoX Auto Update"
msgstr "定时更新GeoX文件"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:463
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:515
msgid "GeoX Config"
msgstr "GeoX 配置"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:488
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:547
msgid "GeoX Update Interval"
msgstr "GeoX 文件更新间隔"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:35
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:42
msgid "Global Mode"
msgstr "全局模式"
@@ -428,7 +428,7 @@ msgstr "全局模式"
msgid "Grant access to nikki procedures"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:101
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:129
msgid "HTTP Port"
msgstr "HTTP 端口"
@@ -436,44 +436,44 @@ msgstr "HTTP 端口"
msgid "How To Use"
msgstr "使用说明"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:250
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:299
msgid "IP"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:43
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:45
msgid "IPv4 DNS Hijack"
msgstr "IPv4 DNS 劫持"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:49
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:51
msgid "IPv4 Proxy"
msgstr "IPv4 代理"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:48
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:181
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:64
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:221
msgid "IPv6"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:46
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:48
msgid "IPv6 DNS Hijack"
msgstr "IPv6 DNS 劫持"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:52
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:54
msgid "IPv6 Proxy"
msgstr "IPv6 代理"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:320
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:372
msgid "Ignore Sniff Domain Name"
msgstr "忽略嗅探的域名"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:94
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:121
msgid "Inbound Config"
msgstr "入站配置"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:111
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:113
msgid "Interface"
msgstr "接口"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:61
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:63
msgid "Lan Proxy"
msgstr "局域网代理"
@@ -486,28 +486,28 @@ msgstr "本地"
msgid "Log"
msgstr "日志"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:25
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:30
msgid "Log Level"
msgstr "日志级别"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:150
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:185
msgid "MTU"
msgstr "最大传输单元"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:39
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:46
msgid "Match Process"
msgstr "匹配进程"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:289
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:447
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:338
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:499
msgid "Matcher"
msgstr "匹配"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:473
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:527
msgid "Memory Conservative Loader"
msgstr "为内存受限设备优化的加载器"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:107
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:137
msgid "Mixed Port"
msgstr "混合端口"
@@ -515,25 +515,25 @@ msgstr "混合端口"
msgid "Mixin Config"
msgstr "混入配置"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:491
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:551
msgid "Mixin File Content"
msgstr "混入文件内容"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:21
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:26
msgid "Mixin Option"
msgstr "混入选项"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:33
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:66
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:39
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:68
msgid "Mode"
msgstr "模式"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:367
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:419
msgid "Name"
msgstr "名称"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:273
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:292
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:322
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:341
msgid "Nameserver"
msgstr "DNS 服务器"
@@ -542,12 +542,12 @@ msgstr "DNS 服务器"
msgid "Nikki"
msgstr ""
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:457
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:509
msgid "No Resolve"
msgstr "不解析"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:381
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:450
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:433
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:502
msgid "Node"
msgstr "节点"
@@ -559,59 +559,59 @@ msgstr "未在运行"
msgid "Open Dashboard"
msgstr "打开面板"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:45
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:53
msgid "Outbound Interface"
msgstr "出站接口"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:118
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:151
msgid "Overwrite Authentication"
msgstr "覆盖身份验证"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:166
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:205
msgid "Overwrite DNS Hijack"
msgstr "覆盖 DNS 劫持"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:345
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:397
msgid "Overwrite Destination"
msgstr "将嗅探结果作为连接目标"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:196
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:239
msgid "Overwrite Fake-IP Filter"
msgstr "覆盖 Fake-IP 过滤列表"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:311
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:363
msgid "Overwrite Force Sniff Domain Name"
msgstr "覆盖强制嗅探的域名"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:233
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:282
msgid "Overwrite Hosts"
msgstr "覆盖 Hosts"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:317
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:369
msgid "Overwrite Ignore Sniff Domain Name"
msgstr "覆盖忽略嗅探的域名"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:252
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:301
msgid "Overwrite Nameserver"
msgstr "覆盖 DNS 服务器"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:275
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:324
msgid "Overwrite Nameserver Policy"
msgstr "覆盖 DNS 服务器查询策略"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:323
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:375
msgid "Overwrite Sniff By Protocol"
msgstr "覆盖按协议嗅探"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:135
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:168
msgid "Password"
msgstr "密码"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:493
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:553
msgid "Please go to the editor tab to edit the file for mixin"
msgstr "请前往编辑器标签编辑用于混入的文件"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:342
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:394
msgid "Port"
msgstr "端口"
@@ -619,7 +619,7 @@ msgstr "端口"
msgid "Prefer"
msgstr "优先"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:443
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:495
msgid "Process Name"
msgstr "进程名"
@@ -632,11 +632,11 @@ msgstr "配置文件"
msgid "Profile for Startup"
msgstr "用于启动的配置文件"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:336
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:388
msgid "Protocol"
msgstr "协议"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:27
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:29
#: applications/luci-app-nikki/root/usr/share/luci/menu.d/luci-app-nikki.json:37
msgid "Proxy Config"
msgstr "代理配置"
@@ -645,11 +645,11 @@ msgstr "代理配置"
msgid "Proxy Provider:"
msgstr "代理提供者:"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:35
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:37
msgid "Redirect Mode"
msgstr "Redirect 模式"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:110
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:141
msgid "Redirect Port"
msgstr "Redirect 端口"
@@ -661,7 +661,7 @@ msgstr "重载服务"
msgid "Remote"
msgstr "远程"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:213
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:258
msgid "Respect Rules"
msgstr "遵循分流规则"
@@ -669,15 +669,15 @@ msgstr "遵循分流规则"
msgid "Restart Service"
msgstr "重启服务"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:58
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:60
msgid "Router Proxy"
msgstr "路由器代理"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:348
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:400
msgid "Rule Config"
msgstr "规则配置"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:36
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:43
msgid "Rule Mode"
msgstr "规则模式"
@@ -685,7 +685,7 @@ msgstr "规则模式"
msgid "Rule Provider:"
msgstr "规则提供者:"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:436
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:488
msgid "Rule Set"
msgstr "规则集"
@@ -693,11 +693,11 @@ msgstr "规则集"
msgid "Running"
msgstr "运行中"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:104
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:133
msgid "SOCKS Port"
msgstr "SOCKS 端口"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:89
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:115
msgid "Save Proxy Selection"
msgstr "保存节点/策略组选择"
@@ -710,27 +710,27 @@ msgstr "定时重启"
msgid "Scroll To Bottom"
msgstr "滚动到底部"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:326
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:378
msgid "Sniff By Protocol"
msgstr "按协议嗅探"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:306
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:357
msgid "Sniff Pure IP"
msgstr "嗅探纯 IP 连接"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:301
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:351
msgid "Sniff Redir-Host"
msgstr "嗅探 Redir-Host 流量"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:294
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:343
msgid "Sniffer Config"
msgstr "嗅探器配置"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:144
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:178
msgid "Stack"
msgstr "栈"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:472
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:526
msgid "Standard Loader"
msgstr "标准加载器"
@@ -759,37 +759,37 @@ msgstr "订阅链接"
msgid "Subscription:"
msgstr "订阅:"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:58
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:76
msgid "TCP Concurrent"
msgstr "TCP 并发"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:63
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:82
msgid "TCP Keep Alive Idle"
msgstr "TCP Keep Alive 空闲"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:66
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:86
msgid "TCP Keep Alive Interval"
msgstr "TCP Keep Alive 间隔"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:34
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:36
msgid "TCP Proxy Mode"
msgstr "TCP 代理模式"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:36
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:40
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:38
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:42
msgid "TPROXY Mode"
msgstr "TPROXY 模式"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:114
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:146
msgid "TPROXY Port"
msgstr "TPROXY 端口"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:139
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:172
msgid "TUN Config"
msgstr "TUN 配置"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:37
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:41
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:39
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:43
msgid "TUN Mode"
msgstr "TUN 模式"
@@ -801,7 +801,7 @@ msgstr "检查配置文件"
msgid "Total"
msgstr "总量"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:29
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:31
msgid "Transparent Proxy"
msgstr "透明代理"
@@ -809,32 +809,83 @@ msgstr "透明代理"
msgid "Transparent Proxy with Mihomo on OpenWrt."
msgstr "在 OpenWrt 上使用 Mihomo 进行透明代理。"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:266
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:370
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:434
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:315
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:422
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:486
msgid "Type"
msgstr "类型"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:39
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/proxy.js:41
msgid "UDP Proxy Mode"
msgstr "UDP 代理模式"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:74
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:96
msgid "UI Name"
msgstr "UI 名称"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:71
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:92
msgid "UI Path"
msgstr "UI 路径"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:76
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:99
msgid "UI Url"
msgstr "UI 下载地址"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:53
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:70
msgid "Unify Delay"
msgstr "统一延迟"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:32
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:41
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:48
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:55
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:66
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:72
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:78
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:84
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:88
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:93
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:97
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:100
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:108
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:113
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:117
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:125
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:131
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:135
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:139
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:143
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:148
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:175
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:180
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:187
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:191
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:197
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:201
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:218
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:223
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:228
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:234
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:248
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:254
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:260
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:266
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:272
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:278
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:347
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:353
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:359
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:519
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:525
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:530
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:533
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:536
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:539
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:543
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:549
msgid "Unmodified"
msgstr "不修改"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/profile.js:60
msgid "Update"
msgstr "更新"
@@ -847,7 +898,7 @@ msgstr "更新时间"
msgid "Update Dashboard"
msgstr "更新面板"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:413
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:465
msgid "Update Interval"
msgstr "更新间隔"
@@ -855,15 +906,15 @@ msgstr "更新间隔"
msgid "Upload Profile"
msgstr "上传配置文件"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:376
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:428
msgid "Url"
msgstr "下载地址"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:228
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:276
msgid "Use Hosts"
msgstr "使用 Hosts"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:223
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:270
msgid "Use System Hosts"
msgstr "使用系统的 Hosts"
@@ -875,6 +926,6 @@ msgstr "已使用"
msgid "User Agent"
msgstr "用户代理(UA"
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:132
#: applications/luci-app-nikki/htdocs/luci-static/resources/view/nikki/mixin.js:165
msgid "Username"
msgstr "用户名"
+8 -2
View File
@@ -6,12 +6,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=25.3.2
PKG_VERSION:=25.3.9
PKG_RELEASE:=1
PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
CONFIG_PACKAGE_$(PKG_NAME)_Nftables_Transparent_Proxy \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Geoview \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \
@@ -35,7 +36,7 @@ LUCI_PKGARCH:=all
LUCI_DEPENDS:=+coreutils +coreutils-base64 +coreutils-nohup +curl \
+chinadns-ng +dns2socks +dnsmasq-full +ip-full \
+libuci-lua +lua +luci-compat +luci-lib-jsonc \
+microsocks +resolveip +tcping +geoview
+microsocks +resolveip +tcping
define Package/$(PKG_NAME)/config
menu "Configuration"
@@ -63,6 +64,11 @@ config PACKAGE_$(PKG_NAME)_Nftables_Transparent_Proxy
select PACKAGE_kmod-nft-nat
default y if PACKAGE_firewall4
config PACKAGE_$(PKG_NAME)_INCLUDE_Geoview
bool "Include Geoview"
select PACKAGE_geoview
default y if aarch64||arm||i386||x86_64
config PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy
bool "Include Haproxy"
select PACKAGE_haproxy
@@ -783,7 +783,7 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
}
opt.set(dom_prefix + 'address', server);
opt.set(dom_prefix + 'port', port);
opt.set(dom_prefix + 'password', decodeURIComponent(password) || "");
opt.set(dom_prefix + 'password', password || "");
opt.set(dom_prefix + 'method', method || "");
opt.set(dom_prefix + 'ss_method', method || "");
opt.set(dom_prefix + 'plugin', plugin || "none");
@@ -918,7 +918,7 @@ local hysteria2_type = map:get("@global_subscribe[0]", "hysteria2_type") or "sin
}
opt.set(dom_prefix + 'address', part2[0]);
opt.set(dom_prefix + 'port', part2[1]);
opt.set(dom_prefix + 'password', decodeURIComponent(part1[1]));
opt.set(dom_prefix + 'password', part1[1]);
opt.set(dom_prefix + 'method', method);
opt.set(dom_prefix + 'ss_method', method);
opt.set(dom_prefix + 'plugin', "none");
@@ -601,7 +601,6 @@ local function processData(szType, content, add_mode, add_from)
--ss://2022-blake3-aes-256-gcm:YctPZ6U7xPPcU%2Bgp3u%2B0tx%2FtRizJN9K8y%2BuKlW2qjlI%3D@192.168.100.1:8888/?plugin=v2ray-plugin%3Bserver#Example3
--ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTp0ZXN0@xxxxxx.com:443?type=ws&path=%2Ftestpath&host=xxxxxx.com&security=tls&fp=&alpn=h3%2Ch2%2Chttp%2F1.1&sni=xxxxxx.com#test-1%40ss
--ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTp4eHh4eHhAeHh4eC54eHh4eC5jb206NTYwMDE#Hong%20Kong-01
--ss://MjAyMi1ibGFrZTMtYWVzLTEyOC1nY206WEdXbmhjUFAxb0Z4SXdxRXpRYXBnUSUzRCUzRCUzQTRuWHRlc0w2QnFOZlEyTVh2dnBqdGclM0QlM0Q@test.com:10333/?group=test#grose7ym
local idx_sp = 0
local alias = ""
@@ -667,7 +666,7 @@ local function processData(szType, content, add_mode, add_from)
local method = userinfo:sub(1, userinfo:find(":") - 1)
local password = userinfo:sub(userinfo:find(":") + 1, #userinfo)
result.method = method
result.password = UrlDecode(password)
result.password = password
if ss_type_default == "shadowsocks-rust" and has_ss_rust then
result.type = 'SS-Rust'
+1 -1
View File
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=mosdns
PKG_VERSION:=5.3.3
PKG_RELEASE:=3
PKG_RELEASE:=4
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/IrineSistiana/mosdns/tar.gz/v$(PKG_VERSION)?
@@ -0,0 +1,341 @@
From 771f9a0ecca80a12f167e56e68d2afd354857e64 Mon Sep 17 00:00:00 2001
From: sbwml <admin@cooluc.com>
Date: Sat, 8 Mar 2025 21:01:39 +0800
Subject: [PATCH] mosdns: update dependencies
Signed-off-by: sbwml <admin@cooluc.com>
---
go.mod | 69 +++++++++++++------------
go.sum | 158 ++++++++++++++++++++++++++-------------------------------
2 files changed, 107 insertions(+), 120 deletions(-)
--- a/go.mod
+++ b/go.mod
@@ -1,30 +1,30 @@
module github.com/IrineSistiana/mosdns/v5
-go 1.22
+go 1.23.0
require (
github.com/IrineSistiana/go-bytes-pool v0.0.0-20230918115058-c72bd9761c57
- github.com/go-chi/chi/v5 v5.1.0
- github.com/google/nftables v0.2.0
+ github.com/go-chi/chi/v5 v5.2.1
+ github.com/google/nftables v0.3.0
github.com/kardianos/service v1.2.2
- github.com/klauspost/compress v1.17.9
- github.com/miekg/dns v1.1.62
+ github.com/klauspost/compress v1.18.0
+ github.com/miekg/dns v1.1.63
github.com/mitchellh/mapstructure v1.5.0
github.com/nadoo/ipset v0.5.0
- github.com/prometheus/client_golang v1.19.1
- github.com/quic-go/quic-go v0.46.0
- github.com/spf13/cobra v1.8.1
+ github.com/prometheus/client_golang v1.21.1
+ github.com/quic-go/quic-go v0.50.0
+ github.com/spf13/cobra v1.9.1
github.com/spf13/viper v1.19.0
- github.com/stretchr/testify v1.9.0
- github.com/vishvananda/netlink v1.2.1-beta.2.0.20221107222636-d3c0a2caa559
+ github.com/stretchr/testify v1.10.0
+ github.com/vishvananda/netlink v1.3.0
go.uber.org/zap v1.27.0
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
- golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa
- golang.org/x/net v0.28.0
- golang.org/x/sync v0.8.0
- golang.org/x/sys v0.24.0
- golang.org/x/time v0.6.0
- google.golang.org/protobuf v1.34.2
+ golang.org/x/exp v0.0.0-20250305212735-054e65f0b394
+ golang.org/x/net v0.37.0
+ golang.org/x/sync v0.12.0
+ golang.org/x/sys v0.31.0
+ golang.org/x/time v0.11.0
+ google.golang.org/protobuf v1.36.5
)
replace github.com/nadoo/ipset v0.5.0 => github.com/IrineSistiana/ipset v0.5.1-0.20220703061533-6e0fc3b04c0a
@@ -33,38 +33,37 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
- github.com/fsnotify/fsnotify v1.7.0 // indirect
+ github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
- github.com/google/go-cmp v0.6.0 // indirect
- github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
+ github.com/google/go-cmp v0.7.0 // indirect
+ github.com/google/pprof v0.0.0-20250302191652-9094ed2288e7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
- github.com/josharian/native v1.1.0 // indirect
- github.com/magiconair/properties v1.8.7 // indirect
- github.com/mdlayher/netlink v1.7.2 // indirect
+ github.com/magiconair/properties v1.8.9 // indirect
+ github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 // indirect
github.com/mdlayher/socket v0.5.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
- github.com/onsi/ginkgo/v2 v2.20.0 // indirect
- github.com/pelletier/go-toml/v2 v2.2.2 // indirect
+ github.com/onsi/ginkgo/v2 v2.23.0 // indirect
+ github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
- github.com/prometheus/common v0.55.0 // indirect
+ github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
- github.com/quic-go/qpack v0.4.0 // indirect
- github.com/sagikazarmark/locafero v0.6.0 // indirect
+ github.com/quic-go/qpack v0.5.1 // indirect
+ github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
- github.com/spf13/afero v1.11.0 // indirect
- github.com/spf13/cast v1.7.0 // indirect
- github.com/spf13/pflag v1.0.5 // indirect
+ github.com/spf13/afero v1.12.0 // indirect
+ github.com/spf13/cast v1.7.1 // indirect
+ github.com/spf13/pflag v1.0.6 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
- go.uber.org/mock v0.4.0 // indirect
+ go.uber.org/mock v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- golang.org/x/crypto v0.26.0 // indirect
- golang.org/x/mod v0.20.0 // indirect
- golang.org/x/text v0.17.0 // indirect
- golang.org/x/tools v0.24.0 // indirect
+ golang.org/x/crypto v0.36.0 // indirect
+ golang.org/x/mod v0.24.0 // indirect
+ golang.org/x/text v0.23.0 // indirect
+ golang.org/x/tools v0.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
--- a/go.sum
+++ b/go.sum
@@ -6,148 +6,136 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKn
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
-github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
-github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
-github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
-github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
+github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
+github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
+github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
+github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
-github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/nftables v0.2.0 h1:PbJwaBmbVLzpeldoeUKGkE2RjstrjPKMl6oLrfEJ6/8=
-github.com/google/nftables v0.2.0/go.mod h1:Beg6V6zZ3oEn0JuiUQ4wqwuyqqzasOltcoXPtgLbFp4=
-github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
-github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/nftables v0.3.0 h1:bkyZ0cbpVeMHXOrtlFc8ISmfVqq5gPJukoYieyVmITg=
+github.com/google/nftables v0.3.0/go.mod h1:BCp9FsrbF1Fn/Yu6CLUc9GGZFw/+hsxfluNXXmxBfRM=
+github.com/google/pprof v0.0.0-20250302191652-9094ed2288e7 h1:+J3r2e8+RsmN3vKfo75g0YSY61ms37qzPglu4p0sGro=
+github.com/google/pprof v0.0.0-20250302191652-9094ed2288e7/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
-github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
-github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/kardianos/service v1.2.2 h1:ZvePhAHfvo0A7Mftk/tEzqEZ7Q4lgnR8sGz4xu1YX60=
github.com/kardianos/service v1.2.2/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
-github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
-github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
+github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
+github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
-github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
-github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
-github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
+github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
+github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
+github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 h1:A1Cq6Ysb0GM0tpKMbdCXCIfBclan4oHk1Jb+Hrejirg=
+github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42/go.mod h1:BB4YCPDOzfy7FniQ/lxuYQ3dgmM2cZumHbK8RpTjN2o=
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
-github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
-github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
+github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
+github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
-github.com/onsi/ginkgo/v2 v2.20.0 h1:PE84V2mHqoT1sglvHc8ZdQtPcwmvvt29WLEEO3xmdZw=
-github.com/onsi/ginkgo/v2 v2.20.0/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI=
-github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
-github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
-github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
-github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/onsi/ginkgo/v2 v2.23.0 h1:FA1xjp8ieYDzlgS5ABTpdUDB7wtngggONc8a7ku2NqQ=
+github.com/onsi/ginkgo/v2 v2.23.0/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM=
+github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
+github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
+github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
+github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
-github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
+github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
+github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
-github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
-github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
+github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
+github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
-github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
-github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
-github.com/quic-go/quic-go v0.46.0 h1:uuwLClEEyk1DNvchH8uCByQVjo3yKL9opKulExNDs7Y=
-github.com/quic-go/quic-go v0.46.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
+github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
+github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
+github.com/quic-go/quic-go v0.50.0 h1:3H/ld1pa3CYhkcc20TPIyG1bNsdhn9qZBGN3b9/UyUo=
+github.com/quic-go/quic-go v0.50.0/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
-github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
+github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
+github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
-github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
-github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
-github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
-github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
-github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
-github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
+github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
+github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
+github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
+github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
+github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
+github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
+github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
-github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
-github.com/vishvananda/netlink v1.2.1-beta.2.0.20221107222636-d3c0a2caa559 h1:NwQroOyW+fpfiUroBzAMqFc6NRwBmvJevoVtEK6gsFE=
-github.com/vishvananda/netlink v1.2.1-beta.2.0.20221107222636-d3c0a2caa559/go.mod h1:cAAsePK2e15YDAMJNyOpGYEWNe4sIghTY7gpz4cX/Ik=
-github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
+github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
+github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
-go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
-go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
+go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
+go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
-golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
-golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
-golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
-golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
-golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
-golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
-golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
-golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
-golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
+golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
+golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
+golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
+golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
+golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
+golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
+golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
+golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
+golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
-golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
-golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
-golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
-golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
-golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
-golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
-google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
-google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
+golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
+golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
+golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
+golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
+golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
+golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
+golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
+google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
+google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+22 -22
View File
@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=naiveproxy
PKG_VERSION:=133.0.6943.49-1
PKG_VERSION:=134.0.6998.39-1
PKG_RELEASE:=1
# intel 80386 & riscv64 & cortex-a76
@@ -20,47 +20,47 @@ else ifeq ($(ARCH_PREBUILT),riscv64_riscv64)
endif
ifeq ($(ARCH_PACKAGES),aarch64_cortex-a53)
PKG_HASH:=070ea4fec533a8ce32f55b6daf8c0431a9b532aba0a0a065583005c6baea77bc
PKG_HASH:=0e616a8dade5207435e0f7a2d5c39e86850079d2c992a3877d1483b1367db97e
else ifeq ($(ARCH_PACKAGES),aarch64_cortex-a72)
PKG_HASH:=b442d4cd10612de60e88b29ed2f7662149570f0da093305511538194ed99f9cb
PKG_HASH:=c98c1867f58d24757d2fab09ee28bf921d9805f0d836bb11d25c4acf8306abec
else ifeq ($(ARCH_PACKAGES),aarch64_generic)
PKG_HASH:=110c0174bc9aeca41c03d207b1aa714c71528c03a8e148699b094473f8ef53f4
PKG_HASH:=9c9d62f1a66b7616e42833ef79ad64aa38c1ac036710ea8bc2a7a133784b7be4
else ifeq ($(ARCH_PACKAGES),arm_arm1176jzf-s_vfp)
PKG_HASH:=dac5719da72e253e02533ba1902367289b5f8fc97e2f1b2e3787e3e702922f2d
PKG_HASH:=2442a34a532e7bfbc0926fd1fbabc94a19779a4ea6edcc50bfe8c2281d524b8d
else ifeq ($(ARCH_PACKAGES),arm_arm926ej-s)
PKG_HASH:=04f237181162ff3e8d83f9f864efead8dcec60a5d75c69b7b112aa0d3107c7a7
PKG_HASH:=4efd0b2bdff46657436dda8016f65a06feb1db1275b3b9023e1b5d4bcd95f776
else ifeq ($(ARCH_PACKAGES),arm_cortex-a15_neon-vfpv4)
PKG_HASH:=ec5bd89729eef1995b58f11f9e52f6495144001fdd3990116da598a9102d5454
PKG_HASH:=7b423e5def6b067bcf72c987714a34ed0eaf785cb5dd6d372a9a15e573ac3074
else ifeq ($(ARCH_PACKAGES),arm_cortex-a5_vfpv4)
PKG_HASH:=bb06489f76b3c8e6420aa6119afa16fe4398f8a3a29478f3939838f60126e3cd
PKG_HASH:=30d429df58bd50d6a527500e1e279e5ae31440383afec5756b0373c68b971dcb
else ifeq ($(ARCH_PACKAGES),arm_cortex-a7)
PKG_HASH:=2a5456cc82a92a69407ddc61b1cfc7d44290e6167d96d4c4fd2dfae53df7f4c5
PKG_HASH:=7b4f3b658058569f7cbfb18a6179c317c6bad9947885d46212a32ba526bb519a
else ifeq ($(ARCH_PACKAGES),arm_cortex-a7_neon-vfpv4)
PKG_HASH:=474af81306bbb4278b70d5803cd8b810b0bffa422027b09e0e4e8a6303a6441f
PKG_HASH:=bf85b73a85a198f73b5d0bd5f538a04be9d126d54b35d56ef1fbf366a758b168
else ifeq ($(ARCH_PACKAGES),arm_cortex-a7_vfpv4)
PKG_HASH:=7f69c052fc6fb35ad3f2f90142c5f03a1ca2d1aa3c5de42ed9c6c5e46db3bff5
PKG_HASH:=26481b7801cf55b46b0e0363de4f4520bf4e839586652ed820a3a21413cc3351
else ifeq ($(ARCH_PACKAGES),arm_cortex-a8_vfpv3)
PKG_HASH:=005df4da3739d42852da7931d15846f22442f0e7ef67716b33dbbfc04f6073e5
PKG_HASH:=535c30dedf4a95b9d3e79e4b6c36e8ee256c6f439ebbdaa673163b32eef63f0e
else ifeq ($(ARCH_PACKAGES),arm_cortex-a9)
PKG_HASH:=a961140b121be616da691aa97a54e01ccf83d925b06d46f0a2e7f70ce93a337d
PKG_HASH:=afa8050347a759b1030939339a7e3e46bab4a8ba42d00b5db3dc7d9bddf5b996
else ifeq ($(ARCH_PACKAGES),arm_cortex-a9_neon)
PKG_HASH:=ecd4f18604ee118be763b710a6a183bf4043387950304f0b2fcefb87beec2eeb
PKG_HASH:=52bd52c123e3b0c23eda946056bcdca805977ac81d97dba3bd8f07ecb04e2add
else ifeq ($(ARCH_PACKAGES),arm_cortex-a9_vfpv3-d16)
PKG_HASH:=707ff36bf95a4e71ff98dcc43182890cc1ac15b6d427c28e443134ca00295374
PKG_HASH:=d04f22d4c2d33982d638d0a0ec0db07a1fec021ce3100e820c862f7f9788d74b
else ifeq ($(ARCH_PACKAGES),arm_mpcore)
PKG_HASH:=135796bf6de20e1ddfb80f8aeb7c57098c1dcaeac2a566633255bb59eaf138a4
PKG_HASH:=a3cb60d42ae13253983728767cd41b7ded11bb699ea4239fafeb03e93477c0fc
else ifeq ($(ARCH_PACKAGES),arm_xscale)
PKG_HASH:=4f7f88885c4318259cfba73ff846eea1c5a94632f5c9d969d664eb1d7795380a
PKG_HASH:=6a9e7a2679812af394cbfc41b5403b5025c8acc15a56c46dc288becd0f940222
else ifeq ($(ARCH_PACKAGES),mipsel_24kc)
PKG_HASH:=6759691bfbd271ac310be605a95d73755c34cc9dbac02d506fb272203733a937
PKG_HASH:=64f6f77e87cb8c06d880b3d4ecafc9baab117452e70dddcdb8c69aae41b6a6ca
else ifeq ($(ARCH_PACKAGES),mipsel_mips32)
PKG_HASH:=543f521ac576667ffeeb3c2a1605cd427badb1dee863e78a562a055e25b6c540
PKG_HASH:=9be977a06b701dfadae4f6c5e56fde7adbda0f7cc8b11921fae01b5ef2315cc7
else ifeq ($(ARCH_PACKAGES),riscv64)
PKG_HASH:=8723cdb1e77c59bf90888c6f4ae1dac8ffb0de369b5de69249a62c5eefae2507
PKG_HASH:=91969c969010f7bb1bde3871b7004a37257a8bc7dcf1d3d2a393b38213e236ff
else ifeq ($(ARCH_PACKAGES),x86)
PKG_HASH:=50729ddb13d31caacc1cd2f6e96d7813478c7e693ae006e3a78e71fea82a2f23
PKG_HASH:=b07fc6775a51b6ff66763210c3c08a60a3e17faa9ed92f5bc0fef8e93266c876
else ifeq ($(ARCH_PACKAGES),x86_64)
PKG_HASH:=eb8fd19699363122f2dbaba8e8dce681e32415b8c485cbb5525ea26c107f1a0f
PKG_HASH:=49e051113d6bf1a9376f26e40ade0672e38b75bc978cabc7622e3a2d0c424d3a
else
PKG_HASH:=dummy
endif
+1 -1
View File
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=v2dat
PKG_SOURCE_DATE:=2022-12-15
PKG_SOURCE_VERSION:=47b8ee51fb528e11e1a83453b7e767a18d20d1f7
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_DATE).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/urlesistiana/v2dat/tar.gz/$(PKG_SOURCE_VERSION)?
@@ -7,8 +7,6 @@ Subject: [PATCH] format logtime
mlog/logger.go | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/mlog/logger.go b/mlog/logger.go
index c8b08a9..b44c88d 100644
--- a/mlog/logger.go
+++ b/mlog/logger.go
@@ -1,17 +1,28 @@
@@ -42,6 +40,3 @@ index c8b08a9..b44c88d 100644
func L() *zap.Logger {
return logger
}
--
2.34.8
@@ -0,0 +1,96 @@
From d5d61b6027b2fe4c75887d33d8a5f98a3ec0795f Mon Sep 17 00:00:00 2001
From: sbwml <admin@cooluc.com>
Date: Sat, 8 Mar 2025 20:26:40 +0800
Subject: [PATCH] v2dat: update dependencies
Signed-off-by: sbwml <admin@cooluc.com>
---
go.mod | 14 ++++++--------
go.sum | 41 +++++++++++++----------------------------
2 files changed, 19 insertions(+), 36 deletions(-)
--- a/go.mod
+++ b/go.mod
@@ -1,18 +1,16 @@
module github.com/urlesistiana/v2dat
-go 1.19
+go 1.21
require (
- github.com/spf13/cobra v1.6.1
- go.uber.org/zap v1.24.0
- google.golang.org/protobuf v1.28.1
+ github.com/spf13/cobra v1.9.1
+ go.uber.org/zap v1.27.0
+ google.golang.org/protobuf v1.36.5
)
require (
github.com/google/go-cmp v0.5.9 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
- github.com/spf13/pflag v1.0.5 // indirect
- github.com/stretchr/testify v1.8.1 // indirect
- go.uber.org/atomic v1.10.0 // indirect
- go.uber.org/multierr v1.9.0 // indirect
+ github.com/spf13/pflag v1.0.6 // indirect
+ go.uber.org/multierr v1.11.0 // indirect
)
--- a/go.sum
+++ b/go.sum
@@ -1,42 +1,27 @@
-github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
-github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
-github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
+github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
+github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
+github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
-go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
-go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
-go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
-go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
-go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
-go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
-google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
+go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
+google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+42 -9
View File
@@ -116,6 +116,7 @@ class VKIE(VKBaseIE):
'id': '-77521_162222515',
'ext': 'mp4',
'title': 'ProtivoGunz - Хуёвая песня',
'description': 'Видео из официальной группы Noize MC\nhttp://vk.com/noizemc',
'uploader': 're:(?:Noize MC|Alexander Ilyashenko).*',
'uploader_id': '39545378',
'duration': 195,
@@ -165,6 +166,7 @@ class VKIE(VKBaseIE):
'id': '-93049196_456239755',
'ext': 'mp4',
'title': '8 серия (озвучка)',
'description': 'Видео из официальной группы Noize MC\nhttp://vk.com/noizemc',
'duration': 8383,
'comment_count': int,
'uploader': 'Dizi2021',
@@ -240,6 +242,7 @@ class VKIE(VKBaseIE):
'upload_date': '20221005',
'uploader': 'Шальная Императрица',
'uploader_id': '-74006511',
'description': 'md5:f9315f7786fa0e84e75e4f824a48b056',
},
},
{
@@ -278,6 +281,25 @@ class VKIE(VKBaseIE):
},
'skip': 'No formats found',
},
{
'note': 'video has chapters',
'url': 'https://vkvideo.ru/video-18403220_456239696',
'info_dict': {
'id': '-18403220_456239696',
'ext': 'mp4',
'title': 'Трамп отменяет гранты // DeepSeek - Революция в ИИ // Илон Маск читер',
'description': 'md5:b112ea9de53683b6d03d29076f62eec2',
'uploader': 'Руслан Усачев',
'uploader_id': '-18403220',
'comment_count': int,
'like_count': int,
'duration': 1983,
'thumbnail': r're:https?://.+\.jpg',
'chapters': 'count:21',
'timestamp': 1738252883,
'upload_date': '20250130',
},
},
{
# live stream, hls and rtmp links, most likely already finished live
# stream by the time you are reading this comment
@@ -449,7 +471,6 @@ class VKIE(VKBaseIE):
return self.url_result(opts_url)
data = player['params'][0]
title = unescapeHTML(data['md_title'])
# 2 = live
# 3 = post live (finished live)
@@ -507,17 +528,29 @@ class VKIE(VKBaseIE):
return {
'id': video_id,
'formats': formats,
'title': title,
'thumbnail': data.get('jpg'),
'uploader': data.get('md_author'),
'uploader_id': str_or_none(data.get('author_id') or mv_data.get('authorId')),
'duration': int_or_none(data.get('duration') or mv_data.get('duration')),
'subtitles': subtitles,
**traverse_obj(mv_data, {
'title': ('title', {unescapeHTML}),
'description': ('desc', {clean_html}, filter),
'duration': ('duration', {int_or_none}),
'like_count': ('likes', {int_or_none}),
'comment_count': ('commcount', {int_or_none}),
}),
**traverse_obj(data, {
'title': ('md_title', {unescapeHTML}),
'description': ('description', {clean_html}, filter),
'thumbnail': ('jpg', {url_or_none}),
'uploader': ('md_author', {str}),
'uploader_id': (('author_id', 'authorId'), {str_or_none}, any),
'duration': ('duration', {int_or_none}),
'chapters': ('time_codes', lambda _, v: isinstance(v['time'], int), {
'title': ('text', {str}),
'start_time': 'time',
}),
}),
'timestamp': timestamp,
'view_count': view_count,
'like_count': int_or_none(mv_data.get('likes')),
'comment_count': int_or_none(mv_data.get('commcount')),
'is_live': is_live,
'subtitles': subtitles,
'_format_sort_fields': ('res', 'source'),
}