This commit is contained in:
riglen
2026-04-21 15:47:09 +08:00
parent 333b66c6bd
commit 05e0355e14
5 changed files with 1130 additions and 0 deletions

809
docs/ini改造方案.md Normal file
View File

@@ -0,0 +1,809 @@
可以。下面这份就是一版 **“类 ACL4SSR 风格 INI/CONF 配置整体说明”**,你可以直接丢给 Codex。
它刻意 **不引入 YAML**,只保留高密度、行导向、声明式的写法。你现在贴的配置本身已经在用 `[custom]``ruleset=``custom_proxy_group=``enable_rule_generator=true``overwrite_original_rules=true` 这套思路subconverter 现有 ACL4SSR 相关配置和外部配置 gist 里也能看到同类结构,甚至有把公共规则和公共分组拆出去再导入的写法。 ([GitHub][1])
---
# sub-provider 类 ACL4SSR 风格 INI 配置说明(草案)
## 1. 目标
将 sub-provider 的配置设计为一种 **ACL4SSR-like 的高密度 INI/CONF DSL**,用于:
* 管理订阅源
* 定义节点选择器
* 定义代理组
* 注册规则模块
* 选择输出 profile
* 生成完整 Clash/Mihomo YAML
这里的重点不是兼容标准 INI 解析器,而是:
> **保留 INI 的可读感 + ACL4SSR 的高密度声明风格 + 方便 Python 自定义解析**
---
## 2. 设计原则
### 2.1 保留 ACL4SSR 的使用习惯
沿用这些核心心智模型:
* `ruleset = 规则模块 -> 目标策略组`
* `group = 策略组定义`
* `selector = 节点筛选器`
* `source = 订阅源`
* `profile = 输出方案`
### 2.2 高密度、行导向
每一条配置尽量一行表达一个对象,方便:
* 快速编辑
* 批量复制
* diff
* 注释开关
* 手工维护
### 2.3 规则正文与配置分离
* `*.list` 文件只保存规则主体
* 目标策略组由配置指定
* 生成器负责最终拼接
### 2.4 不追求严格标准 INI
原因:
* 标准 INI 不擅长重复 key
* 不擅长表达列表对象
* 不擅长表达高密度分组语法
因此这里定义的是:
> **INI-like / CONF-like 自定义配置格式**
---
## 3. 文件组织
推荐结构:
```text
config/
base.conf
profiles/
default.conf
lite.conf
media.conf
rules/
modules/
Riglen.list
LocalAreaNetwork.list
UnBan.list
BanAD.list
BanProgramAD.list
Google.list
GoogleCN.list
SteamCN.list
Bing.list
OneDrive.list
Microsoft.list
Apple.list
Telegram.list
AI.list
OpenAi.list
YouTube.list
Netflix.list
ProxyMedia.list
ProxyGFWlist.list
Pt.list
ChinaDomain.list
ChinaCompanyIp.list
Download.list
```
### 说明
* `base.conf`:全局配置、源、选择器、组定义、模块注册、内置规则
* `profiles/*.conf`:不同输出方案
* `rules/modules/*.list`:规则正文
---
## 4. 基础语法
## 4.1 注释
支持两种注释:
```ini
; 这是注释
# 这也是注释
```
## 4.2 空行
空行忽略。
## 4.3 键值形式
基本格式:
```ini
key = value
```
左右空格允许存在,解析时应 trim。
## 4.4 重复 key
允许重复 key。
例如:
```ini
source = ...
source = ...
selector = ...
selector = ...
group = ...
group = ...
module = ...
module = ...
```
解析器应将这类 key 视为“多条记录”,而不是覆盖。
## 4.5 大小写
建议:
* 指令名小写
* 值区分大小写
* 策略组名、规则内容、正则表达式保持原样
---
## 5. 支持的指令
本方案定义以下核心指令:
* `listen`
* `output_dir`
* `cache_dir`
* `mode`
* `allow_lan`
* `log_level`
* `ipv6`
* `append_userinfo_header`
* `userinfo_source_policy`
以及对象型指令:
* `source =`
* `selector =`
* `group =`
* `module =`
* `builtin =`
profile 内支持:
* `name =`
* `enabled =`
* `sources =`
* `include_modules =`
* `exclude_modules =`
* `include_builtins =`
* `override_policy =`
* `prepend_rule =`
* `append_rule =`
---
## 6. base.conf 说明
## 6.1 全局标量配置
### 示例
```ini
listen = 0.0.0.0:3000
output_dir = ./output
cache_dir = ./data/cache
mode = rule
allow_lan = true
log_level = info
ipv6 = false
append_userinfo_header = true
userinfo_source_policy = first_enabled_source
```
### 含义
* `listen`:监听地址
* `output_dir`:生成结果输出目录
* `cache_dir`:缓存目录
* `mode`Clash 模式,通常为 `rule`
* `allow_lan`:是否允许局域网访问
* `log_level`:日志级别
* `ipv6`:是否开启 IPv6
* `append_userinfo_header`:是否透传订阅流量头
* `userinfo_source_policy`:多源时如何选取订阅信息头
---
## 6.2 source 指令
### 目标
定义订阅输入源。
### 格式
```ini
source = key,type,value,enabled=true,cache_ttl=1800
```
### 示例
```ini
source = airport_main,url,https://example.com/sub?token=xxxx,enabled=true,cache_ttl=1800
source = local_links,file,./data/local_links.txt,enabled=false
```
### 字段说明
* 第 1 列:`key`
* 第 2 列:`type`
* 第 3 列:`value`
* 后续:可选命名参数
### 支持类型
* `url`:远程订阅链接
* `file`:本地文件
* `inline`:内联文本
* `base64`base64 内容
### 建议解析规则
前三列固定,后续按 `k=v` 解析。
---
## 6.3 selector 指令
### 目标
定义节点筛选器,供代理组复用。
### 格式
```ini
selector = key,regex
```
### 示例
```ini
selector = all,.*
selector = hk,(港|HK|hk|Hong Kong|HongKong|hongkong)
selector = jp,(日本|东京|大阪|JP|Japan)
selector = us,(美|洛杉矶|西雅图|US|United States)
selector = netflix,(NF|奈飞|解锁|Netflix|NETFLIX|Media)
```
### 含义
* `key`:选择器名
* `regex`:匹配节点名的正则表达式
### 约定
后续在 `group` 指令中通过 `@selector_key` 引用。
---
## 6.4 group 指令
这是整个 DSL 的核心。
它保留 ACL4SSR 风格的高密度分组写法。你的示例里已经大量使用 `custom_proxy_group=` 这种反引号分隔格式。 现有 subconverter 相关 ACL4SSR 配置里也是同类写法。([GitHub][1])
### 格式
```ini
group = 组名`类型`参数1`参数2`参数3...
```
### 成员约定
* `[]组名`:引用已有组
* `[]DIRECT`:内置 DIRECT
* `[]REJECT`:内置 REJECT
* `@selector_key`:引用 selector 动态筛节点
* `.*`:兼容保留写法,可映射为全部节点
### 示例
```ini
group = 🚀 节点选择`select`[]♻️ 自动选择`[]🇭🇰 香港节点`[]🇯🇵 日本节点`[]🚀 手动切换`[]DIRECT
group = 🚀 手动切换`select`@all
group = ♻️ 自动选择`url-test`@all`http://www.gstatic.com/generate_204`300,,50
group = 🇭🇰 香港节点`url-test`@hk`http://www.gstatic.com/generate_204`300,,50
group = 🇯🇵 日本节点`url-test`@jp`http://www.gstatic.com/generate_204`300,,50
group = 🎥 奈飞节点`select`@netflix
group = 🐟 漏网之鱼`select`[]DIRECT`[]🚀 节点选择`[]♻️ 自动选择
```
### 解析规则建议
#### `select`
```ini
group = 组名`select`成员1`成员2`成员3...
```
#### `url-test`
```ini
group = 组名`url-test`@selector`测试URL`间隔,,容差
```
#### `fallback`
```ini
group = 组名`fallback`@selector`测试URL`间隔,,容差
```
#### `load-balance`
```ini
group = 组名`load-balance`@selector`测试URL`间隔,,容差
```
### 设计建议
不要再继续沿用 `custom_proxy_group=` 这个旧名字。
内部 DSL 里直接统一为:
```ini
group = ...
```
这样更短,也更像你自己的项目语法。
---
## 6.5 module 指令
### 目标
注册规则模块。
### 格式
```ini
module = key,path,policy,order,enabled
```
### 示例
```ini
module = riglen,./rules/modules/Riglen.list,🚀 节点选择,10,true
module = lan,./rules/modules/LocalAreaNetwork.list,🎯 全球直连,20,true
module = banad,./rules/modules/BanAD.list,🛑 广告拦截,40,true
module = apple,./rules/modules/Apple.list,🍎 苹果服务,80,true
module = ai,./rules/modules/AI.list,💬 Ai平台,100,true
module = openai,./rules/modules/OpenAi.list,💬 Ai平台,101,true
```
### 字段说明
* `key`:模块唯一标识
* `path`:规则文件路径
* `policy`:默认策略组
* `order`:排序
* `enabled`:默认是否启用
### 规则文件约定
规则文件只保存规则主体,不含目标策略组。
例如 `OpenAi.list`
```ini
DOMAIN-SUFFIX,openai.com
DOMAIN-SUFFIX,chatgpt.com
DOMAIN-SUFFIX,oaistatic.com
```
生成时补成:
```ini
DOMAIN-SUFFIX,openai.com,💬 Ai平台
```
---
## 6.6 builtin 指令
### 目标
定义不来自 `.list` 文件的内置规则。
### 格式
```ini
builtin = key,type,value,policy,order,enabled
```
### 示例
```ini
builtin = geoip_cn,GEOIP,CN,🎯 全球直连,9000,true
builtin = final,FINAL,,🐟 漏网之鱼,9999,true
```
### 映射规则
* `GEOIP + CN + 🎯 全球直连`
-> `GEOIP,CN,🎯 全球直连`
* `FINAL + 🐟 漏网之鱼`
-> `MATCH,🐟 漏网之鱼`
### 说明
这里保留了 ACL4SSR 配置里 `[]GEOIP,CN``[]FINAL` 这种内置规则思想,只是换成更适合你项目的数据化声明。你的现有配置里已经有这两类用法。 ([GitHub][1])
---
## 7. profile 配置说明
每个 profile 一个文件,放在 `config/profiles/` 下。
---
## 7.1 基本字段
### 示例
```ini
name = 默认完整配置
enabled = true
sources = airport_main
include_modules = riglen,lan,unban,banad,apple,telegram,ai,openai
exclude_modules =
include_builtins = geoip_cn,final
```
### 含义
* `name`profile 名称
* `enabled`:是否启用
* `sources`:本 profile 使用哪些订阅源
* `include_modules`:启用哪些模块
* `exclude_modules`:从启用列表中排除哪些模块
* `include_builtins`:启用哪些内置规则
---
## 7.2 override_policy 指令
### 目标
覆盖模块默认策略组。
### 格式
```ini
override_policy = module_key,new_policy
```
### 示例
```ini
override_policy = apple,🚀 节点选择
override_policy = ai,💬 Ai平台
```
### 含义
例如某模块默认是 `🍎 苹果服务`,某 profile 想改成 `🚀 节点选择`,就在 profile 里覆盖。
---
## 7.3 prepend_rule / append_rule 指令
### 目标
给特定 profile 注入自定义规则。
### 示例
```ini
prepend_rule = DOMAIN-SUFFIX,internal.example.com,DIRECT
append_rule = DOMAIN-SUFFIX,test.example.com,🚀 节点选择
```
### 含义
* `prepend_rule`:插在 rules 最前
* `append_rule`:插在 builtin 之前或之后,由实现约定
### 建议
`MATCH` / `FINAL` 仍应最后输出。
---
## 8. 解析器行为规范
## 8.1 base.conf
解析器应支持:
* 普通标量键值
* 多条 `source`
* 多条 `selector`
* 多条 `group`
* 多条 `module`
* 多条 `builtin`
## 8.2 profile.conf
解析器应支持:
* 普通标量键值
* 多条 `override_policy`
* 多条 `prepend_rule`
* 多条 `append_rule`
## 8.3 字段 trim
建议默认:
* 去掉左右空白
* 不改动组名内部空格
* 不改动正则原文
## 8.4 布尔值
支持:
* `true/false`
* `yes/no`
* `1/0`
内部统一成布尔值。
## 8.5 列表字段
例如:
```ini
sources = airport_main,local_links
include_modules = apple,ai,openai
```
按逗号切分trim 后转数组。
## 8.6 module/source 的 CSV 解析
建议用 Python `csv` 模块解析逗号分隔,而不是简单 `split(",")`,避免后续扩展时出问题。
## 8.7 group 的反引号解析
建议:
1. 去掉前缀 `group =`
2. 按反引号 `` ` `` 分段
3. 第一段为组名
4. 第二段为类型
5. 后续段按组类型解释
---
## 9. 生成流程规范
生成器处理顺序建议如下:
### 第 1 步:加载 base.conf
构建:
* 源表
* selector 表
* group 定义表
* module 注册表
* builtin 注册表
### 第 2 步:加载指定 profile.conf
得到:
* 使用哪些源
* 启用哪些模块
* 启用哪些 builtin
* policy override
* prepend/append 规则
### 第 3 步:拉取并解析节点
* 拉 URL 订阅
* 读本地文件
* 统一解析为节点对象
* 去重 / 重命名 / 过滤
### 第 4 步:按 selector 构建节点集合
例如:
* `hk` -> 匹配香港节点
* `us` -> 匹配美国节点
* `all` -> 全部节点
### 第 5 步:构建 proxy-groups
解析 `group = ...` 指令,生成最终组定义。
### 第 6 步:构建 rules
1. 按模块顺序加载 `.list`
2. 对每行规则补上目标 policy
3. 应用 `override_policy`
4. 加入 `prepend_rule`
5. 加入 builtin
6. 加入 `append_rule`
7. 确保 `FINAL/MATCH` 最后
### 第 7 步:渲染完整 YAML
这里是生成器内部输出,不需要在配置层暴露 YAML 结构给用户。
---
## 10. 错误处理建议
以下情况应报错并指出行号:
* 未知指令
* `group` 语法不合法
* `module` 路径不存在
* profile 引用了不存在的 `source`
* profile 引用了不存在的 `module`
* `override_policy` 指向未知模块
* `@selector_key` 未定义
* builtin 类型不支持
以下情况可仅 warning
* selector 匹配不到节点
* group 最终成员为空
* 模块文件为空
* 规则重复
---
## 11. 兼容性策略建议
## 11.1 兼容旧 ACL4SSR 心智模型
虽然这是你自己的 DSL但建议
* 注释继续支持 `;`
* 保留 `ruleset -> policy` 的思想
* 保留高密度 `group` 行语法
* 保留 `GEOIP` / `FINAL` 的 builtin 概念
## 11.2 不必兼容旧关键字原样
内部不建议继续沿用:
* `ruleset=`
* `custom_proxy_group=`
建议统一改成更短的:
* `module =`
* `group =`
这样语义更清晰:
* `module` 是规则模块注册
* `group` 是代理组定义
---
## 12. 最小示例
## 12.1 base.conf
```ini
listen = 0.0.0.0:3000
mode = rule
allow_lan = true
log_level = info
source = airport_main,url,https://example.com/sub?token=xxxx,enabled=true,cache_ttl=1800
selector = all,.*
selector = hk,(港|HK|hk|Hong Kong|HongKong|hongkong)
selector = us,(美|US|United States)
group = 🚀 节点选择`select`[]♻️ 自动选择`[]🇭🇰 香港节点`[]🇺🇲 美国节点`[]DIRECT
group = ♻️ 自动选择`url-test`@all`http://www.gstatic.com/generate_204`300,,50
group = 🇭🇰 香港节点`url-test`@hk`http://www.gstatic.com/generate_204`300,,50
group = 🇺🇲 美国节点`url-test`@us`http://www.gstatic.com/generate_204`300,,150
group = 🐟 漏网之鱼`select`[]DIRECT`[]🚀 节点选择
module = apple,./rules/modules/Apple.list,🍎 苹果服务,80,true
module = openai,./rules/modules/OpenAi.list,💬 Ai平台,100,true
builtin = geoip_cn,GEOIP,CN,🎯 全球直连,9000,true
builtin = final,FINAL,,🐟 漏网之鱼,9999,true
```
## 12.2 profiles/default.conf
```ini
name = 默认完整配置
enabled = true
sources = airport_main
include_modules = apple,openai
exclude_modules =
include_builtins = geoip_cn,final
override_policy = apple,🚀 节点选择
prepend_rule = DOMAIN-SUFFIX,internal.example.com,DIRECT
```
---
## 13. 给 Codex 的实现要求
你可以直接把下面这段交给 Codex
```md
请为 sub-provider 设计并实现一套类 ACL4SSR 风格的 INI/CONF 配置系统,不要引入 YAML 配置层。
目标:
- 使用高密度、行导向、声明式配置
- 保留 ACL4SSR 的使用习惯,但不要求 100% 兼容其原始关键字
- 规则正文继续使用 rules/modules/*.list
- 配置文件负责声明:
- source
- selector
- group
- module
- builtin
- profile
要求:
1. base.conf 负责全局配置、source、selector、group、module、builtin。
2. profiles/*.conf 负责具体输出 profile。
3. group 使用反引号分隔的 ACL4SSR-like 语法。
4. module 指向规则文件路径和默认策略组。
5. builtin 用于表达 GEOIP、FINAL 这类内置规则。
6. 生成器读取这些 conf 文件后,生成完整 Clash/Mihomo YAML。
7. 不要接数据库,不要做面板。
8. 解析器要能给出清晰的行号错误提示。
9. profile 支持 override_policy、prepend_rule、append_rule。
10. 先实现最小可用版本,再逐步扩展。
```
---
## 14. 最终结论
你现在最适合的路线,就是:
> **规则正文继续放 `.list`**
> **配置层改成类 ACL4SSR 风格的 `.conf`**
> **Python 写一个轻量 parser + generator**
> **最终输出完整 YAML**
这条路最顺,也最符合你现在的使用习惯。
[1]: https://github.com/tindy2013/subconverter/blob/master/base/config/ACL4SSR_NoMicrosoft.ini "subconverter/base/config/ACL4SSR_NoMicrosoft.ini at master · tindy2013/subconverter · GitHub"