From 429788a19f957ee5e3c52ce94ae6bb1b5226d48f Mon Sep 17 00:00:00 2001 From: nitezs Date: Sat, 23 Sep 2023 00:58:57 +0800 Subject: [PATCH] fix --- API_README.md | 4 +-- README.md | 2 +- api/controller/default.go | 61 +++++++++++++++++++++++++------------ api/templates/index.html | 64 +++++++++++++++++++++++---------------- validator/sub.go | 18 ++++++----- 5 files changed, 94 insertions(+), 55 deletions(-) diff --git a/API_README.md b/API_README.md index 17e3599..0462aa8 100644 --- a/API_README.md +++ b/API_README.md @@ -8,12 +8,12 @@ | proxy | string | sub/proxy 至少有一项存在 | - | 节点分享链接(可以输入多个,用 `,` 分隔) | | refresh | bool | 否 | `false` | 强制刷新配置(默认缓存 5 分钟) | | template | string | 否 | - | 外部模板链接或内部模板名称 | -| ruleProvider | string | 否 | - | 格式 `[Behavior,Url,Group,Prepend,Name],[Behavior,Url,Group,Prepend,Name]...`,其中 `Group` 是该规则集所走的策略组名,`Prepend` 为 bool 类型,如果为 `true` 规则将被添加到规则列表顶部,否则添加到规则列表底部(会调整到MATCH规则之前) | +| ruleProvider | string | 否 | - | 格式 `[Behavior,Url,Group,Prepend,Name],[Behavior,Url,Group,Prepend,Name]...`,其中 `Group` 是该规则集使用的策略组名,`Prepend` 为 bool 类型,如果为 `true` 规则将被添加到规则列表顶部,否则添加到规则列表底部(会调整到MATCH规则之前) | | rule | string | 否 | - | 格式 `[Rule,Prepend],[Rule,Prepend]...`,其中 `Prepend` 为 bool 类型,如果为 `true` 规则将被添加到规则列表顶部,否则添加到规则列表底部(会调整到MATCH规则之前) | | autoTest | bool | 否 | `false` | 国家策略组是否自动测速 | | lazy | bool | 否 | `false` | 自动测速是否启用 lazy | | sort | string | 否 | `nameasc` | 国家策略组排序策略,可选值 `nameasc`、`namedesc`、`sizeasc`、`sizedesc` | -| replace | string | 否 | - | 通过正则表达式重命名节点,格式 `[ReplaceKey,ReplaceTo]` | +| replace | string | 否 | - | 通过正则表达式重命名节点,格式 `[,],[,]...` | | remove | string | 否 | - | 通过正则表达式删除节点 | # `/short` diff --git a/README.md b/README.md index 0550fed..e178a88 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ ### 模板 -可以通过变脸自定义模板中的策略组代理节点 +可以通过变量自定义模板中的策略组代理节点 解释的不太清楚,可以参考下方默认模板 - `` 为添加所有节点 diff --git a/api/controller/default.go b/api/controller/default.go index ae4b885..275bfcc 100644 --- a/api/controller/default.go +++ b/api/controller/default.go @@ -89,6 +89,10 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template proxyList = append(proxyList, sub.Proxies...) } } + // 添加自定义节点 + if len(query.Proxies) != 0 { + proxyList = append(proxyList, utils.ParseProxy(query.Proxies...)...) + } // 去重 proxies := make(map[string]*model.Proxy) for i := range proxyList { @@ -105,38 +109,57 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template } names[proxyList[i].Name] = true } - // 删除节点、改名 + // 删除节点 if strings.TrimSpace(query.Remove) != "" { - removeReg, err := regexp.Compile(query.Remove) - if err != nil { - logger.Logger.Debug("remove regexp compile failed", zap.Error(err)) - return nil, errors.New("remove 参数非法: " + err.Error()) - } - replaceReg, err := regexp.Compile(query.ReplaceKey) - if err != nil { - logger.Logger.Debug("replace regexp compile failed", zap.Error(err)) - return nil, errors.New("replaceName 参数非法: " + err.Error()) - } newProxyList := make([]model.Proxy, 0, len(proxyList)) for i := range proxyList { + removeReg, err := regexp.Compile(query.Remove) + if err != nil { + logger.Logger.Debug("remove regexp compile failed", zap.Error(err)) + return nil, errors.New("remove 参数非法: " + err.Error()) + } + // 删除匹配到的节点 if removeReg.MatchString(proxyList[i].Name) { continue // 如果匹配到要删除的元素,跳过该元素,不添加到新切片中 } - if replaceReg.MatchString(proxyList[i].Name) { - proxyList[i].Name = replaceReg.ReplaceAllString(proxyList[i].Name, query.ReplaceTo) - } newProxyList = append(newProxyList, proxyList[i]) // 将要保留的元素添加到新切片中 } proxyList = newProxyList } + // 重命名 + if len(query.ReplaceKeys) != 0 { + // 创建重命名正则表达式 + replaceRegs := make([]*regexp.Regexp, 0, len(query.ReplaceKeys)) + for _, v := range query.ReplaceKeys { + replaceReg, err := regexp.Compile(v) + if err != nil { + logger.Logger.Debug("replace regexp compile failed", zap.Error(err)) + return nil, errors.New("replace 参数非法: " + err.Error()) + } + replaceRegs = append(replaceRegs, replaceReg) + } + for i := range proxyList { + // 重命名匹配到的节点 + for j, v := range replaceRegs { + if err != nil { + logger.Logger.Debug("replace regexp compile failed", zap.Error(err)) + return nil, errors.New("replaceName 参数非法: " + err.Error()) + } + if v.MatchString(proxyList[i].Name) { + proxyList[i].Name = v.ReplaceAllString( + proxyList[i].Name, query.ReplaceTo[j], + ) + } + } + } + } + // trim + for i := range proxyList { + proxyList[i].Name = strings.TrimSpace(proxyList[i].Name) + } // 将新增节点都添加到临时变量 t 中,防止策略组排序错乱 var t = &model.Subscription{} utils.AddProxy(t, query.AutoTest, query.Lazy, clashType, proxyList...) - // 处理自定义代理 - utils.AddProxy( - t, query.AutoTest, query.Lazy, clashType, - utils.ParseProxy(query.Proxies...)..., - ) // 排序策略组 switch query.Sort { case "sizeasc": diff --git a/api/templates/index.html b/api/templates/index.html index d3354d3..3c6d4e7 100644 --- a/api/templates/index.html +++ b/api/templates/index.html @@ -182,24 +182,15 @@ -
- -
- - -
+
+ +
@@ -285,6 +276,17 @@ return div; } + function createReplace() { + const div = document.createElement("div"); + div.classList.add("input-group", "mb-2"); + div.innerHTML = ` + + + + `; + return div; + } + function createRule() { const div = document.createElement("div"); div.classList.add("input-group", "mb-2"); @@ -307,6 +309,11 @@ document.getElementById("ruleGroup").appendChild(div); } + function addReplace() { + const div = createReplace(); + document.getElementById("replaceGroup").appendChild(div); + } + function removeElement(button) { button.parentElement.remove(); } @@ -429,15 +436,20 @@ } // 获取替换节点名称的正则表达式 - const replaceKey = document.getElementById("replaceKey").value; - const replaceTo = document.getElementById("replaceTo").value; - if (replaceKey.trim() !== "" && replaceTo.trim() !== "") { - queryParams.push( - `replace=[${encodeURIComponent(replaceKey)},${encodeURIComponent( - replaceTo, - )}]`, - ); + let replaceList = []; + const replaces = document.getElementsByName("replace"); + for (let i = 0; i < replaces.length / 2; i++) { + let replaceStr = `<${replaces[i * 2].value}>`; + let replaceTo = `<${replaces[i * 2 + 1].value}>`; + if (replaceStr.trim() === "") { + alert("重命名设置中存在空值,请检查后重试!"); + return ""; + } + replaceList.push(`[${replaceStr},${replaceTo}]`); } + queryParams.push( + `replace=${encodeURIComponent(replaceList.join(","))}`, + ); return `${endpoint}?${queryParams.join("&")}`; } diff --git a/validator/sub.go b/validator/sub.go index 66e1b70..aca9116 100644 --- a/validator/sub.go +++ b/validator/sub.go @@ -27,8 +27,8 @@ type SubValidator struct { Sort string `form:"sort" binding:""` Remove string `form:"remove" binding:""` Replace string `form:"replace" binding:""` - ReplaceKey string `form:"replaceKey" binding:""` - ReplaceTo string `form:"replaceString" binding:""` + ReplaceKeys []string `form:"-" binding:""` + ReplaceTo []string `form:"-" binding:""` } type RuleProviderStruct struct { @@ -140,12 +140,16 @@ func ParseQuery(c *gin.Context) (SubValidator, error) { query.Rules = nil } if strings.TrimSpace(query.Replace) != "" { - replace := strings.Split(strings.Trim(query.Replace, "[]"), ",") - if len(replace) != 2 { - return SubValidator{}, errors.New("参数错误: replace 格式错误") + reg := regexp.MustCompile(`\[<(.*?)>,<(.*?)>\]`) + replaces := reg.FindAllStringSubmatch(query.Replace, -1) + for i := range replaces { + length := len(replaces[i]) + if length != 3 { + return SubValidator{}, errors.New("参数错误: replace 格式错误") + } + query.ReplaceKeys = append(query.ReplaceKeys, replaces[i][1]) + query.ReplaceTo = append(query.ReplaceTo, replaces[i][2]) } - query.ReplaceKey = replace[0] - query.ReplaceTo = replace[1] } return query, nil }