feat: vpn 全局直连规则真源(rule-provider)+ Clash Verge 脚本生成器
CI / check (push) Successful in 3s

This commit is contained in:
George Berkshire
2026-08-19 16:46:26 +08:00
commit 25fcdf0701
5 changed files with 239 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env python3
"""把 direct.yaml(真源)生成为 Clash Verge 的全局增强脚本 Script.js。
用法:
python3 scripts/gen_clash_verge_script.py [--out 目标路径]
默认输出到 Clash Verge 数据目录 profiles/Script.js(全局直连规则的唯一正确机制,
见 clash-verge-config 记忆)。生成后需在 Clash Verge 界面点「重启内核」生效。
"""
import argparse
from pathlib import Path
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"
def load_payload(path: Path) -> list[str]:
payload: list[str] = []
with path.open(encoding="utf-8") as f:
for line in f:
line = line.strip()
if line.startswith("- "):
payload.append(line[2:].strip())
if not payload:
raise SystemExit(f"❌ direct.yaml 里没有 payload 条目: {path}")
return payload
def to_rule(entry: str) -> str:
"""rule-provider 条目(无策略)→ 完整规则(补 DIRECT)。"""
if entry.endswith(",no-resolve"):
return f"{entry[:-len(',no-resolve')]},DIRECT,no-resolve"
return f"{entry},DIRECT"
def render_script(payload: list[str]) -> str:
rules = [f" {to_rule(e)!r}," for e in payload]
lines = "\n".join(rules)
return f"""// 由 vpn-rules/direct.yaml 生成 — 勿手改,改真源后重跑 gen_clash_verge_script.py。
// 全局直连规则:FRP 控制面、B站、国内 LLM、内网段、国区 iCloud、UGREEN 一律 DIRECT。
const prependRules = [
{lines}
];
function main(config, profileName) {{
const existingRules = Array.isArray(config.rules) ? config.rules : [];
const existingRuleSet = new Set(existingRules);
config.rules = [
...prependRules.filter((rule) => !existingRuleSet.has(rule)),
...existingRules,
];
return config;
}}
"""
def main() -> None:
ap = argparse.ArgumentParser(description="direct.yaml → Clash Verge Script.js")
ap.add_argument("--out", default=str(DEFAULT_OUT), help="输出路径")
args = ap.parse_args()
payload = load_payload(REPO_ROOT / "direct.yaml")
script = render_script(payload)
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(" 请在 Clash Verge 界面点「重启内核」生效。")
if __name__ == "__main__":
main()