配置文件预处理
版本要求
0.10.1 版本更新后,支持使用 JavaScript 对下载后的配置文件进行预处理
0.11.10 版本更新后,支持使用 YAML 对下载后配置文件进行简单预处理
简便方法(YAML)
如果需要对下载地址为https://example.com/profile.yaml
的配置文件进行预处理,操作如下:
-
进入 Settings 界面
-
滚动至 Profiles 栏
-
点击 Parsers 右边 Edit 打开编辑器,填入:
parsers: - url: https://example.com/profile.yaml yaml: prepend-rules: - DOMAIN,test.com,DIRECT # rules最前面增加一个规则 append-proxies: - name: test # proxies最后面增加一个服务 type: http server: 123.123.123.123 port: 456
-
点击编辑器右下角保存按钮
当配置文件触发刷新(包括自动更新)时,CFW 会读取yaml
字段定义的值,将对应值插入/合并到原配置文件中
参数说明
键 | 值类型 | 操作 |
---|---|---|
append-rules | 数组 | 数组合并至原配置rules 数组后 |
prepend-rules | 数组 | 数组合并至原配置rules 数组前 |
append-proxies | 数组 | 数组合并至原配置proxies 数组后 |
prepend-proxies | 数组 | 数组合并至原配置proxies 数组前 |
append-proxy-groups | 数组 | 数组合并至原配置proxy-groups 数组后 |
prepend-proxy-groups | 数组 | 数组合并至原配置proxy-groups 数组前 |
mix-proxy-providers | 对象 | 对象合并至原配置proxy-providers 中 |
mix-rule-providers | 对象 | 对象合并至原配置rule-providers 中 |
mix-object | 对象 | 对象合并至原配置最外层中 |
commands | 数组 | 在上面操作完成后执行简单命令操作配置文件 |
Commands 使用方法(beta)
commands 是一组简单的命令,作为上面操作的补充
例子:
commands:
- dns.enable=false # 命令1
- proxy-groups.0.proxies.2+DIRECT # 命令2
每个命令可以被分为三个部分,分别是:定位+操作+设定值
命令 1 中,定位是dns.enable
,操作是=
,设定值是false
命令 2 中,定位是proxy-groups.0.proxies.2
,操作是+
,设定值是DIRECT
定位
定位中每个层级以.
分割,数组类型的定位下标由 0 开始计算,命令 2 中proxy-groups.0
即表示定位至第 1 个策略组,.proxies
表示访问第一个策略组的 proxies 属性,.proxies.2
表示 proxies 属性的第 3 个位置
如果不想用序号定位,也可以使用name
值定位,proxies
以及proxy-groups
中的每个项目都会有name
属性。例如在proxies
中已经定义了名为debug
的节点,那么修改其udp
参数的定位即为proxies.(debug).udp
,名称两边的()
是保证识别,如果节点名不包括+
、.
或=
这几个符号,也可以省略不写
操作
目前支持三种操作:
=
:覆盖+
:插入-
:删除
命令 1 中,=
表示将dns
下enable
的值覆盖为false
命令 2 中,+
表示在定位的策略组中的proxies
数组中添加一个名为DIRECT
的值,原本其他值被向后移动 1 位。如果此处改成=
,则会覆盖原来第一个值
设定值
设定值是用于插入或覆盖的值,如果操作是-
,则此值可有可无,例如:
commands:
- proxies.0- # 命令3
此处可以将配置文件proxies
的第 1 个节点删除
如果设定值为纯数字,则会被识别为整数,为true|false
则识别为布尔类型,如果 JSON 编码通过则识别为对象
v0.13.7 版本更新后,支持 3 个内置值用于设置策略组节点,分别是[]proxyNames
,[]groupNames
和[]shuffledProxyNames
,并支持使用正则过滤其中节点,例子如下:
yaml:
prepend-proxy-groups:
- name: myGroup # 建立新策略组
type: fallback
url: "http://www.gstatic.com/generate_204"
interval: 300
proxies:
- DIRECT
commands:
- proxy-groups.myGroup.proxies=[]proxyNames|HK # 向策略组添加所有定义的节点名,并按“HK”正则表达式过滤
进阶方法(JavaScript)
如果需要对下载地址为https://example.com/profile.yaml
的配置文件进行预处理,操作如下:
-
进入 Settings 界面
-
滚动至 Profiles 栏
-
点击 Parsers 右边 Edit 打开编辑器,填入:
parsers: - url: https://example.com/profile.yaml code: | module.exports.parse = async (raw, { axios, yaml, notify, console }, { name, url, interval, selected }) => { const obj = yaml.parse(raw) return yaml.stringify(obj) }
-
点击编辑器右下角保存按钮
当配置文件触发刷新(包括自动更新)时,CFW 会调用此方法对下载的配置文件内容进行处理,再写入本地文件中
当然,parsers 也支持使用路径引入代码:
parsers:
- url: https://example.com/profile.yaml
file: "C:/Users/cfw/parser.js"
::: tip 使用文件时,允许调用该文件目录下的 node_modules 模块 :::
版本 0.20.10 开始支持从远端获取
parsers:
- url: https://example.com/profile.yaml
remote:
url: https://gist.githubusercontent.com/Fndroid/40e6117252f794aa629b875aa1ecadea/raw/d1ba6d230746c9d2ecfbef211c52fd9a567a781e/parser.js
cache: true # 默认为false,指示是否对重复下载此预处理代码使用缓存
::: danger 注意
使用远端配置请选择可信的代码提供者,如不能信任代码提供者,可以从远端拷贝代码然后使用code
填入而非使用remote
方式引入!
:::
参数说明
CFW 调用用户定义的parse
方法时,会传入 3 个参数,分别是配置文件文本内容,工具类对象/方法以及配置文件元数据
配置文件文本内容
raw 是一个字符串,一般需要用 yaml 库解析成 JavaScript 对象
工具类对象/方法
包括:
- axios:网络请求框架,GitHub
- yaml:yaml 框架,GitHub
- notify:发出系统通知方法,签名为
function notify(title:string, message:string, silent:bool)
- console:日志输出至文件,方便调试,在 Settings 界面中 Parser 设置下方打开
- homeDir:Home Directory 目录
:::tip
除了以上工具类,在使用.js
文件时,也可以通过npm
引入第三方模块
:::
配置文件元数据
元数据为 JavaScript 对象,包括:
- name:名称
- url:下载地址
- interval:更新周期
- selected:策略组选择缓存,数组
- mode:模式缓存
:::tip 元数据在配置文件首次下载时只有 url 参数 :::
返回说明
parse
方法需要返回一个字符串,CFW 会将返回的字符串存入对应的配置文件中
多处理器及正则匹配
正则匹配
上面例子中,使用url
匹配配置文件地址,如果一个处理器需要处理多个配置文件,也可以使用正则表达式进行匹配,使用关键字reg
设置
parsers:
- reg: ^https://test\.com/.+$ # 正则匹配域名
yaml:
prepend-rules:
- DOMAIN,test.com,DIRECT
多处理器
parser 定义的数组支持多个处理器从上至下按顺序执行,例如:
parsers:
- reg: https://test.com.+$ # 第一个执行的parser
file: "C:/Users/cfw/parser.yaml"
- url: https://example.com/profile.yaml # 对上一个parser执行的结果进行处理
file: "C:/Users/cfw/parser.js"
::: tip file 同时支持 yaml 及 js 格式的文件 :::
使用案例
向本地配置文件添加订阅信息
- 准备一个本地配置文件的副本,记下文件名和路径。为方便后续说明,以下用
myprofile.yml
指代此文件名,用C:\...\myprofile.yml
指代此文件路径。
::: tip NOTICE 配置完成后,此副本文件将作为 CFW 配置文件的订阅源使用,对配置文件的非临时性修改需要在此副本文件中进行编辑,并在修改后执行订阅更新。移动、重命名此文件后需要修改 CFW 中相应的配置选项。 :::
::: tip 此处使用 CFW 创建的配置文件本身而非副本作为订阅源虽然可以实现相同的功能,但无法保证运行时的可靠性,如果没有特殊情况不建议这样使用。 :::
- 准备一个包含订阅信息
subscription-userinfo
的订阅链接。为方便后续说明,以下用https://example.com/subscription_url
指代此订阅链接。
::: tip
可使用curl -I 'https://example.com/subscription_url'
检查订阅链接是否包含订阅信息。
:::
-
修改 CFW 中的配置文件选项,在
URL
中填写副本文件的本地映射地址file:///C:\...\myprofile.yml
。保存后执行订阅更新并确保没有报错。 -
添加对应的预处理脚本,并确保正常匹配到配置文件。
parsers: # array
- reg: "myprofile.yml"
code: |
module.exports.parse = async (raw, { axios, yaml, notify, console }) => {
raw = raw.replace(/# upload=\d*; download=\d*; total=\d*; expire=\d*;*\n/gm,'')
const url = 'https://example.com/subscription_url'
let { headers:{"subscription-userinfo": si = ""}={}, status } = await axios.head(url)
si = si.replace(/;*$/g,'')
if (status === 200 && si) {
return `# ${si};\n${raw}`
}
return raw
}
- 执行订阅更新,配置文件模块中出现订阅信息即说明配置成功。
::: tip 配置完成后可自行设置自动更新选项。 :::