From 06c9858866a8866987be18d95c28e585c8c80229 Mon Sep 17 00:00:00 2001 From: nitezs Date: Thu, 21 Sep 2023 17:37:37 +0800 Subject: [PATCH 1/7] =?UTF-8?q?modify:=20=E5=A2=9E=E5=8A=A0debug=E8=BE=93?= =?UTF-8?q?=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/controller/default.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/api/controller/default.go b/api/controller/default.go index 0b58d97..2c561aa 100644 --- a/api/controller/default.go +++ b/api/controller/default.go @@ -4,11 +4,13 @@ import ( "crypto/sha256" "encoding/hex" "errors" + "go.uber.org/zap" "gopkg.in/yaml.v3" "net/url" "regexp" "sort" "strings" + "sub2clash/logger" "sub2clash/model" "sub2clash/parser" "sub2clash/utils" @@ -31,17 +33,24 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template if err != nil { templateBytes, err = utils.LoadTemplate(template) if err != nil { + logger.Logger.Debug( + "load template failed", zap.String("template", template), zap.Error(err), + ) return nil, errors.New("加载模板失败: " + err.Error()) } } else { templateBytes, err = utils.LoadSubscription(template, query.Refresh) if err != nil { + logger.Logger.Debug( + "load template failed", zap.String("template", template), zap.Error(err), + ) return nil, errors.New("加载模板失败: " + err.Error()) } } // 解析模板 err = yaml.Unmarshal(templateBytes, &temp) if err != nil { + logger.Logger.Debug("parse template failed", zap.Error(err)) return nil, errors.New("解析模板失败: " + err.Error()) } var proxyList []model.Proxy @@ -49,10 +58,12 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template for i := range query.Subs { data, err := utils.LoadSubscription(query.Subs[i], query.Refresh) if err != nil { + logger.Logger.Debug( + "load subscription failed", zap.String("url", query.Subs[i]), zap.Error(err), + ) return nil, errors.New("加载订阅失败: " + err.Error()) } // 解析订阅 - err = yaml.Unmarshal(data, &sub) if err != nil { reg, _ := regexp.Compile("(ssr|ss|vmess|trojan|http|https)://") @@ -63,6 +74,11 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template // 如果无法直接解析,尝试Base64解码 base64, err := parser.DecodeBase64(string(data)) if err != nil { + logger.Logger.Debug( + "parse subscription failed", zap.String("url", query.Subs[i]), + zap.String("data", string(data)), + zap.Error(err), + ) return nil, errors.New("加载订阅失败: " + err.Error()) } p := utils.ParseProxy(strings.Split(base64, "\n")...) From 2339b7d256abcade3de9d2b5542cf88796168505 Mon Sep 17 00:00:00 2001 From: nitezs Date: Fri, 22 Sep 2023 23:43:26 +0800 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E8=8A=82=E7=82=B9=E6=A3=80=E6=B5=8B=20feat:=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8A=82=E7=82=B9=E5=90=8D=E7=A7=B0=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E4=B8=B2=E6=9B=BF=E6=8D=A2=20feat:=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=8A=82=E7=82=B9=E5=88=A0=E9=99=A4=20feat:=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=9F=AD=E9=93=BE=E5=AF=86=E7=A0=81=E8=AE=BE?= =?UTF-8?q?=E5=AE=9A=20modify:=20=E4=BF=AE=E6=94=B9=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- API_README.md | 36 +++++++++++++++++ README.md | 24 ++++-------- api/controller/default.go | 73 +++++++++++++++++++++++++++-------- api/controller/short_link.go | 9 +++++ api/templates/index.html | 59 ++++++++++++++++++++++++++++ model/short_link.go | 1 + templates/template_clash.yaml | 19 ++++++++- templates/template_meta.yaml | 9 ++++- utils/get.go | 14 ++++++- utils/proxy.go | 2 - validator/short_link.go | 6 ++- validator/sub.go | 12 ++++++ 12 files changed, 225 insertions(+), 39 deletions(-) create mode 100644 API_README.md diff --git a/API_README.md b/API_README.md new file mode 100644 index 0000000..17e3599 --- /dev/null +++ b/API_README.md @@ -0,0 +1,36 @@ +# `/clash`, `/meta` + +获取 Clash/Clash.Meta 配置链接 + +| Query 参数 | 类型 | 是否必须 | 默认值 | 说明 | +|--------------|--------|-------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| sub | string | sub/proxy 至少有一项存在 | - | 订阅链接(可以输入多个,用 `,` 分隔) | +| 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规则之前) | +| 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]` | +| remove | string | 否 | - | 通过正则表达式删除节点 | + +# `/short` + +获取短链,Content-Type 为 `application/json` +具体参考使用可以参考 [api\templates\index.html](./api/templates/index.html) + +| Body 参数 | 类型 | 是否必须 | 默认值 | 说明 | +|----------|--------|------|-----|------------------| +| url | string | 是 | - | 需要转换的 Query 参数部分 | +| password | string | 否 | - | 短链密码 | + +# `/s/:hash` + +短链跳转 +`hash` 为动态路由参数,可以通过 `/short` 接口获取 + +| Query 参数 | 类型 | 是否必须 | 默认值 | 说明 | +|----------|--------|------|-----|------| +| password | string | 否 | - | 短链密码 | diff --git a/README.md b/README.md index ba8b5d5..0550fed 100644 --- a/README.md +++ b/README.md @@ -39,23 +39,17 @@ ### API -#### `/clash`, `/meta` +[API文档](./API_README.md) -获取 Clash/Clash.Meta 配置链接 +### 模板 -| Query 参数 | 类型 | 是否必须 | 默认值 | 说明 | -|--------------|--------|-------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| sub | string | sub/proxy 至少有一项存在 | - | 订阅链接(可以输入多个,用 `,` 分隔) | -| 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规则之前) | -| rule | string | 否 | - | 格式 `[Rule,Prepend],[Rule,Prepend]...`,其中 `Prepend` 为 bool 类型,如果为 `true` 规则将被添加到规则列表顶部,否则添加到规则列表底部(会调整到MATCH规则之前) | -| autoTest | bool | 否 | `false` | 国家策略组是否自动测速 | -| lazy | bool | 否 | `false` | 自动测速是否启用 lazy | -| sort | string | 否 | `nameasc` | 国家策略组排序策略,可选值 `nameasc`、`namedesc`、`sizeasc`、`sizedesc` | +可以通过变脸自定义模板中的策略组代理节点 +解释的不太清楚,可以参考下方默认模板 -## 默认模板 +- `` 为添加所有节点 +- `` 为添加所有国家策略组 + +#### 默认模板 - [Clash](./templates/template_clash.yaml) - [Clash.Meta](./templates/template_meta.yaml) @@ -63,5 +57,3 @@ ## 已知问题 [代理链接解析](./parser)还没有经过严格测试,可能会出现解析错误的情况,如果出现问题请提交 issue - -## TODO diff --git a/api/controller/default.go b/api/controller/default.go index 2c561aa..ae4b885 100644 --- a/api/controller/default.go +++ b/api/controller/default.go @@ -9,6 +9,7 @@ import ( "net/url" "regexp" "sort" + "strconv" "strings" "sub2clash/logger" "sub2clash/model" @@ -88,6 +89,46 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template proxyList = append(proxyList, sub.Proxies...) } } + // 去重 + proxies := make(map[string]*model.Proxy) + for i := range proxyList { + key := proxyList[i].Server + ":" + strconv.Itoa(proxyList[i].Port) + ":" + proxyList[i].Type + if _, exist := proxies[key]; exist { + proxyList = append(proxyList[:i], proxyList[i+1:]...) + } + } + // 重名检测 + names := make(map[string]bool) + for i := range proxyList { + if _, exist := names[proxyList[i].Name]; exist { + proxyList[i].Name = proxyList[i].Name + "@" + proxyList[i].Server + ":" + strconv.Itoa(proxyList[i].Port) + } + 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 { + 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 + } // 将新增节点都添加到临时变量 t 中,防止策略组排序错乱 var t = &model.Subscription{} utils.AddProxy(t, query.AutoTest, query.Lazy, clashType, proxyList...) @@ -154,28 +195,28 @@ func MergeSubAndTemplate(temp *model.Subscription, sub *model.Subscription) { ) } } + var proxyNames []string + for _, proxy := range sub.Proxies { + proxyNames = append(proxyNames, proxy.Name) + } // 将订阅中的节点添加到模板中 temp.Proxies = append(temp.Proxies, sub.Proxies...) // 将订阅中的策略组添加到模板中 - skipGroups := []string{"全球直连", "广告拦截", "手动切换"} for i := range temp.ProxyGroups { - skip := false - for _, v := range skipGroups { - if strings.Contains(temp.ProxyGroups[i].Name, v) { - if v == "手动切换" { - proxies := make([]string, 0, len(sub.Proxies)) - for _, p := range sub.Proxies { - proxies = append(proxies, p.Name) - } - temp.ProxyGroups[i].Proxies = proxies - } - skip = true - continue + if temp.ProxyGroups[i].IsCountryGrop { + continue + } + newProxies := make([]string, 0, len(temp.ProxyGroups[i].Proxies)) + for j := range temp.ProxyGroups[i].Proxies { + if temp.ProxyGroups[i].Proxies[j] == "" { + newProxies = append(newProxies, proxyNames...) + } else if temp.ProxyGroups[i].Proxies[j] == "" { + newProxies = append(newProxies, countryGroupNames...) + } else { + newProxies = append(newProxies, temp.ProxyGroups[i].Proxies[j]) } } - if !skip { - temp.ProxyGroups[i].Proxies = append(temp.ProxyGroups[i].Proxies, countryGroupNames...) - } + temp.ProxyGroups[i].Proxies = newProxies } temp.ProxyGroups = append(temp.ProxyGroups, sub.ProxyGroups...) } diff --git a/api/controller/short_link.go b/api/controller/short_link.go index 1eea508..de5fad7 100644 --- a/api/controller/short_link.go +++ b/api/controller/short_link.go @@ -50,15 +50,20 @@ func ShortLinkGenHandler(c *gin.Context) { Hash: hash, Url: params.Url, LastRequestTime: -1, + Password: params.Password, }, ) // 返回短链接 + if params.Password != "" { + hash += "/?password=" + params.Password + } c.String(200, hash) } func ShortLinkGetHandler(c *gin.Context) { // 获取动态路由 hash := c.Param("hash") + password := c.Query("password") if strings.TrimSpace(hash) == "" { c.String(400, "参数错误") return @@ -71,6 +76,10 @@ func ShortLinkGetHandler(c *gin.Context) { c.String(404, "未找到短链接") return } + if shortLink.Password != "" && shortLink.Password != password { + c.String(403, "密码错误") + return + } // 更新最后访问时间 shortLink.LastRequestTime = time.Now().Unix() database.SaveShortLink(&shortLink) diff --git a/api/templates/index.html b/api/templates/index.html index 4b3bf5e..d3354d3 100644 --- a/api/templates/index.html +++ b/api/templates/index.html @@ -168,6 +168,39 @@ + + +
+ + +
+ + +
+ +
+ + +
+
@@ -188,6 +221,12 @@
+
-
- -
- - -
+
+ +
@@ -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 } From c1e909915620af7cc39c0b3d59e61367b9f984d2 Mon Sep 17 00:00:00 2001 From: nitezs Date: Sat, 23 Sep 2023 01:11:58 +0800 Subject: [PATCH 4/7] fix --- api/controller/default.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/api/controller/default.go b/api/controller/default.go index 275bfcc..8631326 100644 --- a/api/controller/default.go +++ b/api/controller/default.go @@ -95,12 +95,15 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template } // 去重 proxies := make(map[string]*model.Proxy) + newProxies := make([]model.Proxy, 0, len(proxyList)) for i := range proxyList { key := proxyList[i].Server + ":" + strconv.Itoa(proxyList[i].Port) + ":" + proxyList[i].Type - if _, exist := proxies[key]; exist { - proxyList = append(proxyList[:i], proxyList[i+1:]...) + if _, exist := proxies[key]; !exist { + proxies[key] = &proxyList[i] + newProxies = append(newProxies, proxyList[i]) } } + proxyList = newProxies // 重名检测 names := make(map[string]bool) for i := range proxyList { From 67e4121fa6ffe9e442f4fdc9969f7250c6e75abb Mon Sep 17 00:00:00 2001 From: nitezs Date: Sat, 23 Sep 2023 01:31:04 +0800 Subject: [PATCH 5/7] fix --- api/controller/default.go | 18 +++++++++--------- utils/sub.go | 12 +++++++++--- utils/template.go | 4 +++- utils/write_default_template.go | 4 +++- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/api/controller/default.go b/api/controller/default.go index 8631326..174dccf 100644 --- a/api/controller/default.go +++ b/api/controller/default.go @@ -93,7 +93,7 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template if len(query.Proxies) != 0 { proxyList = append(proxyList, utils.ParseProxy(query.Proxies...)...) } - // 去重 + // 去掉配置相同的节点 proxies := make(map[string]*model.Proxy) newProxies := make([]model.Proxy, 0, len(proxyList)) for i := range proxyList { @@ -104,14 +104,6 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template } } proxyList = newProxies - // 重名检测 - names := make(map[string]bool) - for i := range proxyList { - if _, exist := names[proxyList[i].Name]; exist { - proxyList[i].Name = proxyList[i].Name + "@" + proxyList[i].Server + ":" + strconv.Itoa(proxyList[i].Port) - } - names[proxyList[i].Name] = true - } // 删除节点 if strings.TrimSpace(query.Remove) != "" { newProxyList := make([]model.Proxy, 0, len(proxyList)) @@ -156,6 +148,14 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template } } } + // 重名检测 + names := make(map[string]int) + for i := range proxyList { + if _, exist := names[proxyList[i].Name]; exist { + proxyList[i].Name = proxyList[i].Name + " " + strconv.Itoa(names[proxyList[i].Name]) + } + names[proxyList[i].Name] = names[proxyList[i].Name] + 1 + } // trim for i := range proxyList { proxyList[i].Name = strings.TrimSpace(proxyList[i].Name) diff --git a/utils/sub.go b/utils/sub.go index 00bf437..d7442b1 100644 --- a/utils/sub.go +++ b/utils/sub.go @@ -35,7 +35,9 @@ func LoadSubscription(url string, refresh bool) ([]byte, error) { return nil, err } defer func(file *os.File) { - _ = file.Close() + if file != nil { + _ = file.Close() + } }(file) fileLock.RLock() defer fileLock.RUnlock() @@ -56,7 +58,9 @@ func FetchSubscriptionFromAPI(url string) ([]byte, error) { return nil, err } defer func(Body io.ReadCloser) { - _ = Body.Close() + if Body != nil { + _ = Body.Close() + } }(resp.Body) data, err := io.ReadAll(resp.Body) if err != nil { @@ -67,7 +71,9 @@ func FetchSubscriptionFromAPI(url string) ([]byte, error) { return nil, err } defer func(file *os.File) { - _ = file.Close() + if file != nil { + _ = file.Close() + } }(file) fileLock.Lock() defer fileLock.Unlock() diff --git a/utils/template.go b/utils/template.go index 781a099..45bf68a 100644 --- a/utils/template.go +++ b/utils/template.go @@ -17,7 +17,9 @@ func LoadTemplate(template string) ([]byte, error) { return nil, err } defer func(file *os.File) { - _ = file.Close() + if file != nil { + _ = file.Close() + } }(file) result, err := io.ReadAll(file) if err != nil { diff --git a/utils/write_default_template.go b/utils/write_default_template.go index 07a60ae..9fbb192 100644 --- a/utils/write_default_template.go +++ b/utils/write_default_template.go @@ -16,7 +16,9 @@ func writeTemplate(path string, template string) error { return err } defer func(file *os.File) { - _ = file.Close() + if file != nil { + _ = file.Close() + } }(file) _, err = file.WriteString(template) if err != nil { From be9df16b61616ec6b127dacb709e4b1cd5a168e1 Mon Sep 17 00:00:00 2001 From: nitezs Date: Sat, 23 Sep 2023 01:55:43 +0800 Subject: [PATCH 6/7] fix --- api/controller/short_link.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/api/controller/short_link.go b/api/controller/short_link.go index de5fad7..4e9101e 100644 --- a/api/controller/short_link.go +++ b/api/controller/short_link.go @@ -26,11 +26,16 @@ func ShortLinkGenHandler(c *gin.Context) { } // 生成hash hash := utils.RandomString(config.Default.ShortLinkLength) - // 存入数据库 var item model.ShortLink result := database.FindShortLinkByUrl(params.Url, &item) if result.Error == nil { - c.String(200, item.Hash) + if params.Password != "" && item.Password != params.Password { + item.Password = params.Password + database.SaveShortLink(&item) + c.String(200, item.Hash+"?password="+params.Password) + } else { + c.String(200, item.Hash) + } return } else { if !errors.Is(result.Error, gorm.ErrRecordNotFound) { @@ -55,7 +60,7 @@ func ShortLinkGenHandler(c *gin.Context) { ) // 返回短链接 if params.Password != "" { - hash += "/?password=" + params.Password + hash += "?password=" + params.Password } c.String(200, hash) } @@ -73,11 +78,11 @@ func ShortLinkGetHandler(c *gin.Context) { result := database.FindShortLinkByHash(hash, &shortLink) // 重定向 if result.Error != nil { - c.String(404, "未找到短链接") + c.String(404, "未找到短链接或密码错误") return } if shortLink.Password != "" && shortLink.Password != password { - c.String(403, "密码错误") + c.String(404, "未找到短链接或密码错误") return } // 更新最后访问时间 From 3546396e3d60f2c7c3755b8c9626d4fc9b0ea01b Mon Sep 17 00:00:00 2001 From: nitezs Date: Sat, 23 Sep 2023 08:48:45 +0800 Subject: [PATCH 7/7] fix --- api/controller/default.go | 2 +- api/controller/short_link.go | 21 ++++++++-- templates/template_meta.yaml | 81 +++++++++++++++++++++++++++++------- utils/get.go | 6 +-- 4 files changed, 86 insertions(+), 24 deletions(-) diff --git a/api/controller/default.go b/api/controller/default.go index 174dccf..e0eed50 100644 --- a/api/controller/default.go +++ b/api/controller/default.go @@ -67,7 +67,7 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template // 解析订阅 err = yaml.Unmarshal(data, &sub) if err != nil { - reg, _ := regexp.Compile("(ssr|ss|vmess|trojan|http|https)://") + reg, _ := regexp.Compile("(ssr|ss|vmess|trojan|vless)://") if reg.Match(data) { p := utils.ParseProxy(strings.Split(string(data), "\n")...) proxyList = append(proxyList, p...) diff --git a/api/controller/short_link.go b/api/controller/short_link.go index 4e9101e..9c39619 100644 --- a/api/controller/short_link.go +++ b/api/controller/short_link.go @@ -3,10 +3,14 @@ package controller import ( "errors" "github.com/gin-gonic/gin" + "go.uber.org/zap" "gorm.io/gorm" + "io" "net/http" + "strconv" "strings" "sub2clash/config" + "sub2clash/logger" "sub2clash/model" "sub2clash/utils" "sub2clash/utils/database" @@ -29,7 +33,7 @@ func ShortLinkGenHandler(c *gin.Context) { var item model.ShortLink result := database.FindShortLinkByUrl(params.Url, &item) if result.Error == nil { - if params.Password != "" && item.Password != params.Password { + if item.Password != params.Password { item.Password = params.Password database.SaveShortLink(&item) c.String(200, item.Hash+"?password="+params.Password) @@ -88,6 +92,17 @@ func ShortLinkGetHandler(c *gin.Context) { // 更新最后访问时间 shortLink.LastRequestTime = time.Now().Unix() database.SaveShortLink(&shortLink) - uri := config.Default.BasePath + shortLink.Url - c.Redirect(http.StatusTemporaryRedirect, uri) + get, err := utils.Get("http://localhost:" + strconv.Itoa(config.Default.Port) + "/" + shortLink.Url) + if err != nil { + logger.Logger.Debug("get short link data failed", zap.Error(err)) + c.String(500, "请求错误: "+err.Error()) + return + } + all, err := io.ReadAll(get.Body) + if err != nil { + logger.Logger.Debug("read short link data failed", zap.Error(err)) + c.String(500, "读取错误: "+err.Error()) + return + } + c.String(http.StatusOK, string(all)) } diff --git a/templates/template_meta.yaml b/templates/template_meta.yaml index 0711087..8885bf4 100644 --- a/templates/template_meta.yaml +++ b/templates/template_meta.yaml @@ -15,39 +15,83 @@ proxy-groups: type: select proxies: - - - name: 微软服务 + - name: 游戏平台(中国) type: select proxies: - - - 节点选择 + - - 手动切换 - DIRECT - - name: 游戏平台 + - name: 游戏平台(全球) type: select proxies: - - - 节点选择 + - - 手动切换 - DIRECT - name: 巴哈姆特 type: select proxies: - - - 节点选择 + - - 手动切换 - DIRECT - name: 哔哩哔哩 type: select proxies: - - - 节点选择 + - - 手动切换 - DIRECT - - name: 全球直连 + - name: Telegram type: select proxies: - - DIRECT - 节点选择 + - + - 手动切换 + - DIRECT + - name: OpenAI + type: select + proxies: + - 节点选择 + - + - 手动切换 + - DIRECT + - name: Youtube + type: select + proxies: + - 节点选择 + - + - 手动切换 + - DIRECT + - name: Microsoft + type: select + proxies: + - 节点选择 + - + - 手动切换 + - DIRECT + - name: Onedrive + type: select + proxies: + - 节点选择 + - + - 手动切换 + - DIRECT + - name: Apple + type: select + proxies: + - 节点选择 + - + - 手动切换 + - DIRECT + - name: Netflix + type: select + proxies: + - 节点选择 + - + - 手动切换 + - DIRECT - name: 广告拦截 type: select proxies: @@ -56,19 +100,26 @@ proxy-groups: - name: 漏网之鱼 type: select proxies: - - - 节点选择 + - - 手动切换 - DIRECT rules: - - GEOSITE,private,全球直连,no-resolve - - GEOIP,private,全球直连 + - GEOSITE,private,DIRECT,no-resolve + - GEOIP,private,DIRECT - GEOSITE,category-ads-all,广告拦截 - - GEOSITE,microsoft,微软服务 + - GEOSITE,microsoft,Microsoft + - GEOSITE,apple,Apple + - GEOSITE,netflix,Netflix + - GEOSITE,onedrive,Onedrive + - GEOSITE,youtube,Youtube + - GEOSITE,telegram,Telegram + - GEOSITE,openai,OpenAI - GEOSITE,bilibili,哔哩哔哩 - GEOSITE,bahamut,巴哈姆特 - - GEOSITE,category-games,游戏平台 + - GEOSITE,category-games@cn,游戏平台(中国) + - GEOSITE,category-games,游戏平台(全球) - GEOSITE,geolocation-!cn,节点选择 - - GEOSITE,CN,全球直连 - - GEOIP,CN,全球直连 + - GEOSITE,CN,DIRECT + - GEOIP,CN,DIRECT - MATCH,漏网之鱼 diff --git a/utils/get.go b/utils/get.go index bcf8765..a7fbc96 100644 --- a/utils/get.go +++ b/utils/get.go @@ -13,17 +13,13 @@ func Get(url string) (resp *http.Response, err error) { retryDelay := time.Second // 延迟1秒再重试 for haveTried < retryTimes { client := &http.Client{} - client.Timeout = time.Second * 10 + //client.Timeout = time.Second * 10 req, err := http.NewRequest("GET", url, nil) if err != nil { haveTried++ time.Sleep(retryDelay) continue } - req.Header.Set( - "User-Agent", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", - ) get, err := client.Do(req) if err != nil { haveTried++