Files
sub-provider/docs/ini改造方案.md
riglen 05e0355e14 step1
2026-04-21 15:47:09 +08:00

810 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
可以。下面这份就是一版 **“类 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"