Author SHA1 Message Date
ao gong 112374e2a1 test(gen-script): lock in to_rule() inline-# handling with regression tests
CI / lite (push) Successful in 3s
新增 2 个 test method 覆盖 b4a4769 修复的边界 case:
- test_to_rule_strips_inline_hash_comment_before_classifying_no_resolve
  锁定带 inline # 注释的条目(本次修复的真实场景)
  + 验证注释里出现 'no-resolve' / ',DIRECT' 字符串不被误处理
- test_to_rule_preserves_canonical_forms
  锁定 happy path(纯规则、带 no-resolve、带行尾空白)

为让 test_checked_in_router_projections_match_the_rule_source 通过,
同步重生成 router/direct-plain.txt 和 router/direct-rules.yaml。
这俩投影文件自 907fe9d 起就 stale 14+ 条规则(国内 LLM、UGREEN、
Steam 段全没同步),本次连同 b4a4769 的修复一起补齐。

测试结果:python3 -m unittest discover -s tests
  Ran 9 tests in 0.028s — OK
2026-09-05 13:40:50 +08:00
ao gong b4a4769dcf fix(gen-script): strip inline '#' comment before classifying no-resolve suffix
CI / lite (push) Failing after 4s
to_rule() 在判断 entry.endswith(',no-resolve') 之前没有剥掉行尾 # 注释,
导致带 inline 注释的条目走 else 分支,把注释当成 entry 一部分拼进去,
最终生成出 mihomo 解析失败的规则:

  'IP-CIDR,162.254.192.0/18,no-resolve   # Akamai Steam CDN 主段,DIRECT'

修法:
- to_rule() 先 split('#', 1)[0].rstrip() 剥注释再判断
- direct.yaml 第 91 行 inline 注释挪到独立行(避免再次踩坑)

验证:gen_clash_verge_script.py 重跑后 Script.js 第 49 行已变成
  'IP-CIDR,162.254.192.0/18,DIRECT,no-resolve',
Clash Verge 重启内核后订阅配置校验失败消失。
2026-09-05 13:32:48 +08:00
ao gong 907fe9d46a direct: add Steam global pass (community/store/CDN/Valve nets)
CI / lite (push) Failing after 4s
2026-09-05 11:56:06 +08:00
ageorge156 854b8e1cdd fix: keep OneDrive on direct routing (#7)
CI / lite (push) Successful in 9s
## 变更

- 将 `OneDrive.exe` 设为全局 `DIRECT`,优先于供应商 Microsoft 规则
- 为 Clash Verge 全局脚本补充国内可达的阿里 DNS / 腾讯 DNS DoH fallback
- 同步更新路由器规则投影与跨平台生成说明

## 验证

- `python -m unittest discover -s tests -v`:7 项通过
- mihomo DNS API 成功解析 OneDrive 目标
- 实际日志确认 `OneDrive.exe -> skydrive.wns.windows.com:443` 命中 `ProcessName(OneDrive.exe)` 并使用 `DIRECT`

Reviewed-on: http://192.168.50.2:3000/ageorge156/vpn-rules/pulls/7
2026-08-30 16:55:17 +08:00
5 changed files with 90 additions and 1 deletions
+18
View File
@@ -76,3 +76,21 @@ payload:
- IP-CIDR,110.42.0.0/16,no-resolve
- IP-CIDR,43.248.128.0/17,no-resolve
- IP-CIDR,111.170.0.0/16,no-resolve
# Steam 全局直连(社区/商店/CDN/Valve 官方网段;避免下载/联机绕美节点)
- DOMAIN-SUFFIX,steampowered.com
- DOMAIN-SUFFIX,steamcommunity.com
- DOMAIN-SUFFIX,steamgames.com
- DOMAIN-SUFFIX,steamusercontent.com
- DOMAIN-SUFFIX,steam-chat.com
- DOMAIN-SUFFIX,steamstatic.com
- DOMAIN-SUFFIX,steamcontent.com
- DOMAIN-KEYWORD,csgo.
- PROCESS-NAME,steam
- PROCESS-NAME,steamwebhelper
- IP-CIDR,162.254.192.0/18,no-resolve
# Akamai Steam CDN 主段
- IP-CIDR,103.10.124.0/23,no-resolve
- IP-CIDR,103.28.54.0/23,no-resolve
- IP-CIDR,146.66.152.0/21,no-resolve
- IP-CIDR,155.133.224.0/19,no-resolve
+15
View File
@@ -33,3 +33,18 @@ DOMAIN-SUFFIX,syncthing.net
IP-CIDR,110.42.0.0/16,no-resolve
IP-CIDR,43.248.128.0/17,no-resolve
IP-CIDR,111.170.0.0/16,no-resolve
DOMAIN-SUFFIX,steampowered.com
DOMAIN-SUFFIX,steamcommunity.com
DOMAIN-SUFFIX,steamgames.com
DOMAIN-SUFFIX,steamusercontent.com
DOMAIN-SUFFIX,steam-chat.com
DOMAIN-SUFFIX,steamstatic.com
DOMAIN-SUFFIX,steamcontent.com
DOMAIN-KEYWORD,csgo.
PROCESS-NAME,steam
PROCESS-NAME,steamwebhelper
IP-CIDR,162.254.192.0/18,no-resolve
IP-CIDR,103.10.124.0/23,no-resolve
IP-CIDR,103.28.54.0/23,no-resolve
IP-CIDR,146.66.152.0/21,no-resolve
IP-CIDR,155.133.224.0/19,no-resolve
+15
View File
@@ -46,3 +46,18 @@ rules:
- IP-CIDR,110.42.0.0/16,DIRECT,no-resolve
- IP-CIDR,43.248.128.0/17,DIRECT,no-resolve
- IP-CIDR,111.170.0.0/16,DIRECT,no-resolve
- DOMAIN-SUFFIX,steampowered.com,DIRECT
- DOMAIN-SUFFIX,steamcommunity.com,DIRECT
- DOMAIN-SUFFIX,steamgames.com,DIRECT
- DOMAIN-SUFFIX,steamusercontent.com,DIRECT
- DOMAIN-SUFFIX,steam-chat.com,DIRECT
- DOMAIN-SUFFIX,steamstatic.com,DIRECT
- DOMAIN-SUFFIX,steamcontent.com,DIRECT
- DOMAIN-KEYWORD,csgo.,DIRECT
- PROCESS-NAME,steam,DIRECT
- PROCESS-NAME,steamwebhelper,DIRECT
- IP-CIDR,162.254.192.0/18,DIRECT,no-resolve
- IP-CIDR,103.10.124.0/23,DIRECT,no-resolve
- IP-CIDR,103.28.54.0/23,DIRECT,no-resolve
- IP-CIDR,146.66.152.0/21,DIRECT,no-resolve
- IP-CIDR,155.133.224.0/19,DIRECT,no-resolve
+6 -1
View File
@@ -52,7 +52,12 @@ def load_payload(path: Path) -> list[str]:
def to_rule(entry: str) -> str:
"""rule-provider 条目(无策略)→ 完整规则(补 DIRECT)。"""
"""rule-provider 条目(无策略)→ 完整规则(补 DIRECT)。
处理:先剥掉行尾 `#` 注释,再补 DIRECT 策略,避免带注释的条目被错误拼接。
"""
# 剥掉 `#` 之后的行尾注释
entry = entry.split("#", 1)[0].rstrip()
if entry.endswith(",no-resolve"):
return f"{entry[:-len(',no-resolve')]},DIRECT,no-resolve"
return f"{entry},DIRECT"
+36
View File
@@ -203,6 +203,42 @@ class ModuleSpecTests(unittest.TestCase):
"PROCESS-NAME,OneDrive.exe,DIRECT",
)
def test_to_rule_strips_inline_hash_comment_before_classifying_no_resolve(self) -> None:
# 回归测试 (b4a4769):to_rule() 在判断 entry.endswith(',no-resolve') 之前
# 没有剥掉行尾 # 注释,导致带 inline 注释的 Akamai Steam CDN 规则
# 走错分支,把注释当成 entry 的一部分拼进去,生成 mihomo 解析失败的规则。
self.assertEqual(
to_rule("IP-CIDR,162.254.192.0/18,no-resolve # Akamai Steam CDN 主段"),
"IP-CIDR,162.254.192.0/18,DIRECT,no-resolve",
)
# 注释里出现 "no-resolve" 不能误判为 suffix
self.assertEqual(
to_rule("DOMAIN-SUFFIX,example.com # 走 no-resolve 路径"),
"DOMAIN-SUFFIX,example.com,DIRECT",
)
# 注释里出现 ",DIRECT" 不能误拼到 proxy 字段
self.assertEqual(
to_rule("IP-CIDR,10.0.0.0/8 # 不是 DIRECT, 是 REJECT"),
"IP-CIDR,10.0.0.0/8,DIRECT",
)
def test_to_rule_preserves_canonical_forms(self) -> None:
# 不带注释、不带 no-resolve
self.assertEqual(
to_rule("DOMAIN-SUFFIX,bilibili.com"),
"DOMAIN-SUFFIX,bilibili.com,DIRECT",
)
# 带 no-resolve、无注释
self.assertEqual(
to_rule("IP-CIDR,127.0.0.0/8,no-resolve"),
"IP-CIDR,127.0.0.0/8,DIRECT,no-resolve",
)
# 带 no-resolve + 行尾空白
self.assertEqual(
to_rule("IP-CIDR,127.0.0.0/8,no-resolve "),
"IP-CIDR,127.0.0.0/8,DIRECT,no-resolve",
)
def test_clash_verge_script_adds_reachable_direct_dns_fallbacks(self) -> None:
script = render_script(["PROCESS-NAME,OneDrive.exe"])