fix: keep OneDrive on direct routing #7
@@ -27,15 +27,17 @@ vpn-rules/
|
||||
|
||||
## 消费端接入
|
||||
|
||||
### Clash Verge(macOS)
|
||||
### Clash Verge(Windows / macOS)
|
||||
|
||||
```bash
|
||||
# 生成并写入 Clash Verge 数据目录的 Script.js
|
||||
# 按当前平台生成并写入 Clash Verge 数据目录的全局 Script.js
|
||||
python3 scripts/gen_clash_verge_script.py
|
||||
# 然后在 Clash Verge 界面点「重启内核」生效
|
||||
```
|
||||
|
||||
对当前及以后新增/切换的所有订阅生效;订阅更新不会覆盖它。
|
||||
Windows 默认写入 `%APPDATA%\io.github.clash-verge-rev.clash-verge-rev\profiles\Script.js`;
|
||||
macOS 默认写入 `~/Library/Application Support/io.github.clash-verge-rev.clash-verge-rev/profiles/Script.js`。
|
||||
|
||||
### 路由器 mihomo(Magic Catling2 / OpenWrt)
|
||||
|
||||
|
||||
@@ -4,14 +4,39 @@
|
||||
用法:
|
||||
python3 scripts/gen_clash_verge_script.py [--out 目标路径]
|
||||
|
||||
默认输出到 Clash Verge 数据目录 profiles/Script.js(全局直连规则的唯一正确机制,
|
||||
见 clash-verge-config 记忆)。生成后需在 Clash Verge 界面点「重启内核」生效。
|
||||
默认按 Windows/macOS 平台输出到 Clash Verge 数据目录 profiles/Script.js(全局直连
|
||||
规则的唯一正确机制)。生成后需在 Clash Verge 界面点「重启内核」生效。
|
||||
"""
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
DEFAULT_OUT = Path.home() / "Library/Application Support/io.github.clash-verge-rev.clash-verge-rev/profiles/Script.js"
|
||||
APP_ID = "io.github.clash-verge-rev.clash-verge-rev"
|
||||
|
||||
|
||||
def default_output_path(
|
||||
platform_name: str = sys.platform,
|
||||
*,
|
||||
home: Path | None = None,
|
||||
appdata: Path | None = None,
|
||||
) -> Path:
|
||||
"""返回当前平台的 Clash Verge 全局 Script.js 路径。"""
|
||||
home = home or Path.home()
|
||||
if platform_name == "win32":
|
||||
if appdata is None:
|
||||
roaming = os.environ.get("APPDATA")
|
||||
if not roaming:
|
||||
raise SystemExit("[error] Windows 环境缺少 APPDATA,无法定位 Clash Verge 数据目录")
|
||||
appdata = Path(roaming)
|
||||
return appdata / APP_ID / "profiles" / "Script.js"
|
||||
if platform_name == "darwin":
|
||||
return home / "Library/Application Support" / APP_ID / "profiles" / "Script.js"
|
||||
return home / ".local/share" / APP_ID / "profiles" / "Script.js"
|
||||
|
||||
|
||||
DEFAULT_OUT = default_output_path()
|
||||
|
||||
|
||||
def load_payload(path: Path) -> list[str]:
|
||||
@@ -22,7 +47,7 @@ def load_payload(path: Path) -> list[str]:
|
||||
if line.startswith("- "):
|
||||
payload.append(line[2:].strip())
|
||||
if not payload:
|
||||
raise SystemExit(f"❌ direct.yaml 里没有 payload 条目: {path}")
|
||||
raise SystemExit(f"[error] direct.yaml 里没有 payload 条目: {path}")
|
||||
return payload
|
||||
|
||||
|
||||
@@ -66,7 +91,7 @@ def main() -> None:
|
||||
out = Path(args.out)
|
||||
out.parent.mkdir(parents=True, exist_ok=True)
|
||||
out.write_text(script, encoding="utf-8")
|
||||
print(f"✅ 已生成 {out}({len(payload)} 条规则)")
|
||||
print(f"[ok] 已生成 {out}({len(payload)} 条规则)")
|
||||
print(" 请在 Clash Verge 界面点「重启内核」生效。")
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path, PurePosixPath
|
||||
|
||||
@@ -10,10 +13,59 @@ ROOT = Path(__file__).resolve().parents[1]
|
||||
SPEC_PATH = ROOT / "MODULE_SPEC.yaml"
|
||||
sys.path.insert(0, str(ROOT / "scripts"))
|
||||
|
||||
from gen_clash_verge_script import load_payload, to_rule # noqa: E402
|
||||
from gen_clash_verge_script import ( # noqa: E402
|
||||
default_output_path,
|
||||
load_payload,
|
||||
to_rule,
|
||||
)
|
||||
|
||||
|
||||
class ModuleSpecTests(unittest.TestCase):
|
||||
def test_clash_verge_default_output_path_is_platform_aware(self) -> None:
|
||||
home = Path("C:/Users/example")
|
||||
appdata = Path("C:/Users/example/AppData/Roaming")
|
||||
|
||||
self.assertEqual(
|
||||
default_output_path("win32", home=home, appdata=appdata),
|
||||
appdata
|
||||
/ "io.github.clash-verge-rev.clash-verge-rev"
|
||||
/ "profiles"
|
||||
/ "Script.js",
|
||||
)
|
||||
self.assertEqual(
|
||||
default_output_path("darwin", home=home),
|
||||
home
|
||||
/ "Library/Application Support"
|
||||
/ "io.github.clash-verge-rev.clash-verge-rev"
|
||||
/ "profiles"
|
||||
/ "Script.js",
|
||||
)
|
||||
|
||||
def test_clash_verge_generator_supports_windows_gbk_console(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
output = Path(temp_dir) / "Script.js"
|
||||
env = os.environ.copy()
|
||||
env["PYTHONIOENCODING"] = "gbk"
|
||||
result = subprocess.run(
|
||||
[
|
||||
sys.executable,
|
||||
str(ROOT / "scripts/gen_clash_verge_script.py"),
|
||||
"--out",
|
||||
str(output),
|
||||
],
|
||||
cwd=ROOT,
|
||||
env=env,
|
||||
capture_output=True,
|
||||
check=False,
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
result.returncode,
|
||||
0,
|
||||
result.stderr.decode("gbk", errors="replace"),
|
||||
)
|
||||
self.assertTrue(output.is_file())
|
||||
|
||||
def test_module_spec_declares_rule_authority_and_safe_context(self) -> None:
|
||||
spec = json.loads(SPEC_PATH.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user