From 72635ce0fc08933f4f32b25c82c16b8418f795ea Mon Sep 17 00:00:00 2001 From: nitezs Date: Fri, 15 Sep 2023 00:13:45 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=9B=BD?= =?UTF-8?q?=E5=AE=B6=E7=AD=96=E7=95=A5=E7=BB=84=E6=8E=92=E5=BA=8F=E7=AD=96?= =?UTF-8?q?=E7=95=A5=20feat:=20=E6=94=AF=E6=8C=81=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E6=A8=A1=E6=9D=BF=20mod:=20Rule-Provider=20?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E8=87=AA=E5=AE=9A=E4=B9=89=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 22 +++++++------- api/controller/default.go | 38 +++++++++++++++++++---- model/proxy_group.go | 58 ++++++++++++++++++++++++++++++++++++ model/sub.go | 11 ------- templates/template_meta.yaml | 1 - utils/proxy.go | 46 +++++++++++++++------------- validator/sub.go | 11 ++++++- 7 files changed, 138 insertions(+), 49 deletions(-) create mode 100644 model/proxy_group.go diff --git a/README.md b/README.md index 873dbdb..898acb3 100644 --- a/README.md +++ b/README.md @@ -41,16 +41,17 @@ 获取 Clash/Clash.Meta 配置链接 -| Query 参数 | 类型 | 是否必须 | 说明 | -|--------------|--------|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| sub | string | sub/proxy 至少有一项存在 | 订阅链接(可以输入多个,用 `,` 分隔) | -| proxy | string | sub/proxy 至少有一项存在 | 节点分享链接(可以输入多个,用 `,` 分隔) | -| refresh | bool | 否(默认 `false`) | 强制刷新配置(默认缓存 5 分钟) | -| template | string | 否 | 外部模板 | -| ruleProvider | string | 否 | 格式 `[Behavior,Url,Group,Prepend],[Behavior,Url,Group,Prepend],...`,其中 `Group` 是该规则集所走的策略组名,`Prepend` 为 bool 类型,如果为 `true` 规则将被添加到规则列表顶部,否则添加到规则列表底部(会调整到MATCH规则之前) | -| rule | string | 否 | 格式 `[Rule,Prepend],[Rule,Prepend]...`,其中 `Prepend` 为 bool 类型,如果为 `true` 规则将被添加到规则列表顶部,否则添加到规则列表底部(会调整到MATCH规则之前) | -| autoTest | bool | 否(默认 `false`) | 指定国家策略组是否自动测速 | -| lazy | bool | 否(默认 `false`) | 自动测速是否启用 lazy | +| 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 | +| countryGroupSort | string | 否 | `nameasc` | 国家策略组排序策略,可选值 `nameasc`、`namedesc`、`sizeasc`、`sizedesc` | ## 默认模板 @@ -63,3 +64,4 @@ ## TODO +- [ ] 可视化面板 \ No newline at end of file diff --git a/api/controller/default.go b/api/controller/default.go index 55760a6..07e2785 100644 --- a/api/controller/default.go +++ b/api/controller/default.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "errors" "gopkg.in/yaml.v3" + "net/url" "regexp" "strings" "sub2clash/model" @@ -17,13 +18,13 @@ func BuildSub(query validator.SubQuery, template string) ( *model.Subscription, error, ) { // 定义变量 - var externalTemplate = query.Template != "" var temp *model.Subscription var sub *model.Subscription var err error var templateBytes []byte // 加载模板 - if !externalTemplate { + _, err = url.ParseRequestURI(template) + if err != nil { templateBytes, err = utils.LoadTemplate(template) if err != nil { return nil, errors.New("加载模板失败: " + err.Error()) @@ -63,10 +64,14 @@ func BuildSub(query validator.SubQuery, template string) ( } else { proxyList = sub.Proxies } - utils.AddProxy(temp, query.AutoTest, query.Lazy, proxyList...) + utils.AddProxy(sub, query.AutoTest, query.Lazy, query.Sort, proxyList...) } // 处理自定义代理 - utils.AddProxy(temp, query.AutoTest, query.Lazy, utils.ParseProxy(query.Proxies...)...) + utils.AddProxy( + sub, query.AutoTest, query.Lazy, query.Sort, + utils.ParseProxy(query.Proxies...)..., + ) + MergeSubAndTemplate(temp, sub) // 处理自定义规则 for _, v := range query.Rules { if v.Prepend { @@ -88,13 +93,34 @@ func BuildSub(query validator.SubQuery, template string) ( } if v.Prepend { utils.PrependRuleProvider( - temp, name, v.Group, provider, + temp, v.Name, v.Group, provider, ) } else { utils.AppenddRuleProvider( - temp, name, v.Group, provider, + temp, v.Name, v.Group, provider, ) } } return temp, nil } + +func MergeSubAndTemplate(temp *model.Subscription, sub *model.Subscription) { + // 只合并节点、策略组 + // 统计所有国家策略组名称 + var newCountryGroupNames []string + for _, proxyGroup := range sub.ProxyGroups { + if proxyGroup.IsCountryGrop { + newCountryGroupNames = append( + newCountryGroupNames, proxyGroup.Name, + ) + } + } + // 将订阅中的节点添加到模板中 + temp.Proxies = append(temp.Proxies, sub.Proxies...) + // 将订阅中的策略组添加到模板中 + for i := range temp.ProxyGroups { + temp.ProxyGroups[i].Proxies = append(temp.ProxyGroups[i].Proxies, newCountryGroupNames...) + } + temp.ProxyGroups = append(temp.ProxyGroups, sub.ProxyGroups...) + temp.Rules = append(temp.Rules, sub.Rules...) +} diff --git a/model/proxy_group.go b/model/proxy_group.go new file mode 100644 index 0000000..26179c6 --- /dev/null +++ b/model/proxy_group.go @@ -0,0 +1,58 @@ +package model + +import ( + "golang.org/x/text/collate" + "golang.org/x/text/language" +) + +type ProxyGroup struct { + Name string `yaml:"name,omitempty"` + Type string `yaml:"type,omitempty"` + Proxies []string `yaml:"proxies,omitempty"` + IsCountryGrop bool `yaml:"-"` + Url string `yaml:"url,omitempty"` + Interval int `yaml:"interval,omitempty"` + Tolerance int `yaml:"tolerance,omitempty"` + Lazy bool `yaml:"lazy"` + Size int `yaml:"-"` +} + +type ProxyGroupsSortByName []ProxyGroup +type ProxyGroupsSortBySize []ProxyGroup + +func (p ProxyGroupsSortByName) Len() int { + return len(p) +} +func (p ProxyGroupsSortBySize) Len() int { + return len(p) +} + +func (p ProxyGroupsSortByName) Less(i, j int) bool { + // 定义一组备选语言:首选英语,其次中文 + tags := []language.Tag{ + language.English, + language.Chinese, + } + matcher := language.NewMatcher(tags) + + // 假设我们的请求语言是 "zh"(中文),则使用匹配器找到最佳匹配的语言 + bestMatch, _, _ := matcher.Match(language.Make("zh")) + // 使用最佳匹配的语言进行排序 + c := collate.New(bestMatch) + + return c.CompareString(p[i].Name, p[j].Name) < 0 +} + +func (p ProxyGroupsSortBySize) Less(i, j int) bool { + if p[i].Size == p[j].Size { + return p[i].Name < p[j].Name + } + return p[i].Size < p[j].Size +} + +func (p ProxyGroupsSortByName) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} +func (p ProxyGroupsSortBySize) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} diff --git a/model/sub.go b/model/sub.go index 4d8d3d4..9043450 100644 --- a/model/sub.go +++ b/model/sub.go @@ -13,17 +13,6 @@ type Subscription struct { RuleProviders map[string]RuleProvider `yaml:"rule-providers,omitempty,omitempty"` } -type ProxyGroup struct { - Name string `yaml:"name,omitempty"` - Type string `yaml:"type,omitempty"` - Proxies []string `yaml:"proxies,omitempty"` - IsCountryGrop bool `yaml:"-"` - Url string `yaml:"url,omitempty"` - Interval int `yaml:"interval,omitempty"` - Tolerance int `yaml:"tolerance,omitempty"` - Lazy bool `yaml:"lazy"` -} - type RuleProvider struct { Type string `yaml:"type,omitempty"` Behavior string `yaml:"behavior,omitempty"` diff --git a/templates/template_meta.yaml b/templates/template_meta.yaml index 1cf3788..7287b80 100644 --- a/templates/template_meta.yaml +++ b/templates/template_meta.yaml @@ -57,6 +57,5 @@ rules: - GEOIP,CN,全球直连 - GEOSITE,category-games,游戏平台 - GEOSITE,geolocation-!cn,节点选择 - - GEOIP,ad,广告拦截 - GEOSITE,category-ads-all,广告拦截 - MATCH,漏网之鱼 \ No newline at end of file diff --git a/utils/proxy.go b/utils/proxy.go index 9283e6e..130f771 100644 --- a/utils/proxy.go +++ b/utils/proxy.go @@ -1,6 +1,7 @@ package utils import ( + "sort" "strings" "sub2clash/model" "sub2clash/parser" @@ -27,35 +28,30 @@ func GetContryName(proxy model.Proxy) string { return "其他地区" } -var skipGroups = map[string]bool{ - "手动切换": true, - "全球直连": true, - "广告拦截": true, - "应用净化": true, -} - -func AddProxy(sub *model.Subscription, autotest bool, lazy bool, proxies ...model.Proxy) { +func AddProxy( + sub *model.Subscription, autotest bool, lazy bool, sortStrategy string, + proxies ...model.Proxy, +) { newCountryGroupNames := make([]string, 0) - + // 添加节点 for _, proxy := range proxies { sub.Proxies = append(sub.Proxies, proxy) - haveProxyGroup := false countryName := GetContryName(proxy) - for i := range sub.ProxyGroups { group := &sub.ProxyGroups[i] if group.Name == countryName { group.Proxies = append(group.Proxies, proxy.Name) + group.Size++ haveProxyGroup = true } if group.Name == "手动切换" { group.Proxies = append(group.Proxies, proxy.Name) + group.Size++ } } - if !haveProxyGroup { var newGroup model.ProxyGroup if !autotest { @@ -64,6 +60,7 @@ func AddProxy(sub *model.Subscription, autotest bool, lazy bool, proxies ...mode Type: "select", Proxies: []string{proxy.Name}, IsCountryGrop: true, + Size: 1, } } else { newGroup = model.ProxyGroup{ @@ -75,24 +72,33 @@ func AddProxy(sub *model.Subscription, autotest bool, lazy bool, proxies ...mode Interval: 300, Tolerance: 50, Lazy: lazy, + Size: 1, } } sub.ProxyGroups = append(sub.ProxyGroups, newGroup) newCountryGroupNames = append(newCountryGroupNames, countryName) } } - + // 统计国家策略组数量 + countryGroupCount := 0 for i := range sub.ProxyGroups { if sub.ProxyGroups[i].IsCountryGrop { - continue - } - if !skipGroups[sub.ProxyGroups[i].Name] { - combined := make([]string, len(newCountryGroupNames)+len(sub.ProxyGroups[i].Proxies)) - copy(combined, newCountryGroupNames) - copy(combined[len(newCountryGroupNames):], sub.ProxyGroups[i].Proxies) - sub.ProxyGroups[i].Proxies = combined + countryGroupCount++ } } + // 对国家策略组进行排序 + switch sortStrategy { + case "sizeasc": + sort.Sort(model.ProxyGroupsSortBySize(sub.ProxyGroups[:countryGroupCount])) + case "sizedesc": + sort.Sort(sort.Reverse(model.ProxyGroupsSortBySize(sub.ProxyGroups[:countryGroupCount]))) + case "nameasc": + sort.Sort(model.ProxyGroupsSortByName(sub.ProxyGroups[:countryGroupCount])) + case "namedesc": + sort.Sort(sort.Reverse(model.ProxyGroupsSortByName(sub.ProxyGroups[:countryGroupCount]))) + default: + sort.Sort(model.ProxyGroupsSortByName(sub.ProxyGroups[:countryGroupCount])) + } } func ParseProxy(proxies ...string) []model.Proxy { diff --git a/validator/sub.go b/validator/sub.go index c903dd5..24405fd 100644 --- a/validator/sub.go +++ b/validator/sub.go @@ -1,6 +1,8 @@ package validator import ( + "crypto/md5" + "encoding/hex" "errors" "github.com/gin-gonic/gin" "net/url" @@ -21,6 +23,7 @@ type SubQuery struct { Rules []RuleStruct `form:"-" binding:""` AutoTest bool `form:"autoTest,default=false" binding:""` Lazy bool `form:"lazy,default=false" binding:""` + Sort string `form:"sort" binding:""` } type RuleProviderStruct struct { @@ -28,6 +31,7 @@ type RuleProviderStruct struct { Url string Group string Prepend bool + Name string } type RuleStruct struct { @@ -87,7 +91,7 @@ func ParseQuery(c *gin.Context) (SubQuery, error) { for i := range ruleProviders { length := len(ruleProviders) parts := strings.Split(ruleProviders[length-i-1][1], ",") - if len(parts) != 4 { + if len(parts) < 4 { return SubQuery{}, errors.New("参数错误: ruleProvider 格式错误") } u := parts[1] @@ -100,12 +104,17 @@ func ParseQuery(c *gin.Context) (SubQuery, error) { if err != nil { return SubQuery{}, errors.New("参数错误: " + err.Error()) } + if len(parts) == 4 { + hash := md5.Sum([]byte(u)) + parts = append(parts, hex.EncodeToString(hash[:])) + } query.RuleProviders = append( query.RuleProviders, RuleProviderStruct{ Behavior: parts[0], Url: u, Group: parts[2], Prepend: parts[3] == "true", + Name: parts[4], }, ) } From 0f2dba21ebbed04c716abd7b74133c0ac952ec6b Mon Sep 17 00:00:00 2001 From: nitezs Date: Fri, 15 Sep 2023 00:17:32 +0800 Subject: [PATCH 2/8] =?UTF-8?q?mod:=20=E5=A2=9E=E5=8A=A0=20dev=20=E5=88=86?= =?UTF-8?q?=E6=94=AF=E7=9A=84=20docker=20=E9=95=9C=E5=83=8F=E6=9E=84?= =?UTF-8?q?=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 77da130..98a87df 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -27,5 +27,5 @@ jobs: context: . file: ./Dockerfile push: true - tags: ghcr.io/${{ github.repository }}:latest + tags: ghcr.io/${{ github.repository }}:dev From f6273947e7cb703994acd19343e50d784c4f2501 Mon Sep 17 00:00:00 2001 From: nitezs Date: Fri, 15 Sep 2023 00:31:57 +0800 Subject: [PATCH 3/8] mod --- .github/workflows/docker.yml | 4 ++-- api/controller/default.go | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 98a87df..278d03b 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,8 +2,8 @@ name: Build and Push to GHCR on: push: - tags: - - '*' + branches: + - dev workflow_dispatch: jobs: diff --git a/api/controller/default.go b/api/controller/default.go index 07e2785..38c1a53 100644 --- a/api/controller/default.go +++ b/api/controller/default.go @@ -107,11 +107,11 @@ func BuildSub(query validator.SubQuery, template string) ( func MergeSubAndTemplate(temp *model.Subscription, sub *model.Subscription) { // 只合并节点、策略组 // 统计所有国家策略组名称 - var newCountryGroupNames []string + var countryGroupNames []string for _, proxyGroup := range sub.ProxyGroups { if proxyGroup.IsCountryGrop { - newCountryGroupNames = append( - newCountryGroupNames, proxyGroup.Name, + countryGroupNames = append( + countryGroupNames, proxyGroup.Name, ) } } @@ -119,8 +119,7 @@ func MergeSubAndTemplate(temp *model.Subscription, sub *model.Subscription) { temp.Proxies = append(temp.Proxies, sub.Proxies...) // 将订阅中的策略组添加到模板中 for i := range temp.ProxyGroups { - temp.ProxyGroups[i].Proxies = append(temp.ProxyGroups[i].Proxies, newCountryGroupNames...) + temp.ProxyGroups[i].Proxies = append(temp.ProxyGroups[i].Proxies, countryGroupNames...) } temp.ProxyGroups = append(temp.ProxyGroups, sub.ProxyGroups...) - temp.Rules = append(temp.Rules, sub.Rules...) } From fe2f47865ebded2e76d154311f456c03e257a88e Mon Sep 17 00:00:00 2001 From: nitezs Date: Fri, 15 Sep 2023 08:26:48 +0800 Subject: [PATCH 4/8] fix --- README.md | 22 +++++++++++----------- api/controller/default.go | 3 +++ validator/sub.go | 29 ++++++----------------------- 3 files changed, 20 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 898acb3..836a407 100644 --- a/README.md +++ b/README.md @@ -41,17 +41,17 @@ 获取 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 | -| countryGroupSort | string | 否 | `nameasc` | 国家策略组排序策略,可选值 `nameasc`、`namedesc`、`sizeasc`、`sizedesc` | +| 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` | ## 默认模板 diff --git a/api/controller/default.go b/api/controller/default.go index 38c1a53..4ca33a5 100644 --- a/api/controller/default.go +++ b/api/controller/default.go @@ -23,6 +23,9 @@ func BuildSub(query validator.SubQuery, template string) ( var err error var templateBytes []byte // 加载模板 + if query.Template != "" { + template = query.Template + } _, err = url.ParseRequestURI(template) if err != nil { templateBytes, err = utils.LoadTemplate(template) diff --git a/validator/sub.go b/validator/sub.go index 24405fd..bd2b649 100644 --- a/validator/sub.go +++ b/validator/sub.go @@ -6,6 +6,7 @@ import ( "errors" "github.com/gin-gonic/gin" "net/url" + "os" "regexp" "strings" ) @@ -50,7 +51,6 @@ func ParseQuery(c *gin.Context) (SubQuery, error) { if query.Sub != "" { query.Subs = strings.Split(query.Sub, ",") for i := range query.Subs { - query.Subs[i], _ = url.QueryUnescape(query.Subs[i]) if _, err := url.ParseRequestURI(query.Subs[i]); err != nil { return SubQuery{}, errors.New("参数错误: " + err.Error()) } @@ -60,32 +60,19 @@ func ParseQuery(c *gin.Context) (SubQuery, error) { } if query.Proxy != "" { query.Proxies = strings.Split(query.Proxy, ",") - for i := range query.Proxies { - query.Proxies[i], _ = url.QueryUnescape(query.Proxies[i]) - if _, err := url.ParseRequestURI(query.Proxies[i]); err != nil { - return SubQuery{}, errors.New("参数错误: " + err.Error()) - } - } } else { query.Proxies = nil } if query.Template != "" { - unescape, err := url.QueryUnescape(query.Template) + uri, err := url.ParseRequestURI(query.Template) if err != nil { - return SubQuery{}, errors.New("参数错误: " + err.Error()) + if strings.Contains(query.Template, string(os.PathSeparator)) { + return SubQuery{}, err + } } - uri, err := url.ParseRequestURI(unescape) query.Template = uri.String() - if err != nil { - return SubQuery{}, errors.New("参数错误: " + err.Error()) - } } if query.RuleProvider != "" { - var err error - query.RuleProvider, err = url.QueryUnescape(query.RuleProvider) - if err != nil { - return SubQuery{}, errors.New("参数错误: " + err.Error()) - } reg := regexp.MustCompile(`\[(.*?)\]`) ruleProviders := reg.FindAllStringSubmatch(query.RuleProvider, -1) for i := range ruleProviders { @@ -95,15 +82,11 @@ func ParseQuery(c *gin.Context) (SubQuery, error) { return SubQuery{}, errors.New("参数错误: ruleProvider 格式错误") } u := parts[1] - u, err = url.QueryUnescape(u) - if err != nil { - return SubQuery{}, errors.New("参数错误: " + err.Error()) - } uri, err := url.ParseRequestURI(u) - u = uri.String() if err != nil { return SubQuery{}, errors.New("参数错误: " + err.Error()) } + u = uri.String() if len(parts) == 4 { hash := md5.Sum([]byte(u)) parts = append(parts, hex.EncodeToString(hash[:])) From 282649aca0b4755ad218bea28b455258342bac15 Mon Sep 17 00:00:00 2001 From: nitezs Date: Fri, 15 Sep 2023 08:51:22 +0800 Subject: [PATCH 5/8] fix --- api/controller/default.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/api/controller/default.go b/api/controller/default.go index 4ca33a5..6f9a0c5 100644 --- a/api/controller/default.go +++ b/api/controller/default.go @@ -121,8 +121,25 @@ func MergeSubAndTemplate(temp *model.Subscription, sub *model.Subscription) { // 将订阅中的节点添加到模板中 temp.Proxies = append(temp.Proxies, sub.Proxies...) // 将订阅中的策略组添加到模板中 + skipGroups := []string{"全球直连", "广告拦截", "手动切换"} for i := range temp.ProxyGroups { - temp.ProxyGroups[i].Proxies = append(temp.ProxyGroups[i].Proxies, countryGroupNames...) + 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 !skip { + temp.ProxyGroups[i].Proxies = append(temp.ProxyGroups[i].Proxies, countryGroupNames...) + } } temp.ProxyGroups = append(temp.ProxyGroups, sub.ProxyGroups...) } From 4e7d84499f4883cc884fdd187568d2048653853a Mon Sep 17 00:00:00 2001 From: nitezs Date: Fri, 15 Sep 2023 09:15:24 +0800 Subject: [PATCH 6/8] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=20Dockerfile=20?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Dockerfile b/Dockerfile index 374494a..9f1a96a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,6 +14,9 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o sub2clash FROM alpine:latest +# 设置工作目录 +WORKDIR /app + # 从 builder 镜像中复制出编译好的二进制文件 COPY --from=builder /app/sub2clash /app/sub2clash From 1f38125e85d3de3039a1bc1a8316ba688e02ddb9 Mon Sep 17 00:00:00 2001 From: nitezs Date: Fri, 15 Sep 2023 09:59:21 +0800 Subject: [PATCH 7/8] =?UTF-8?q?update:=20=E4=BF=AE=E6=94=B9=20docker.yml?= =?UTF-8?q?=20=E9=95=9C=E5=83=8F=E6=9E=84=E5=BB=BA=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/docker.yml | 62 +++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 278d03b..5dcd8de 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -4,6 +4,8 @@ on: push: branches: - dev + tags: + - '*' workflow_dispatch: jobs: @@ -11,21 +13,51 @@ jobs: runs-on: ubuntu-latest steps: - - name: Check out code - uses: actions/checkout@v3 + - name: Check out code + uses: actions/checkout@v3 - - name: Login to GitHub Container Registry - uses: docker/login-action@v1 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Build and push Docker image - uses: docker/build-push-action@v2 - with: - context: . - file: ./Dockerfile - push: true - tags: ghcr.io/${{ github.repository }}:dev + - name: Set tag name + id: set_tag + run: | + if [[ $GITHUB_REF == refs/heads/* ]]; then + echo "::set-output name=tag::$(echo $GITHUB_REF | cut -d'/' -f3)" + else + echo "::set-output name=tag::${{ github.ref_name }}" + fi + + - name: Check if triggered by tag + id: check_tag + run: | + if [[ "${{ github.ref }}" == refs/tags/* ]]; then + echo "::set-output name=triggered_by_tag::true" + else + echo "::set-output name=triggered_by_tag::false" + fi + + - name: Build and push Docker image for dev branch + if: steps.check_tag.outputs.triggered_by_tag == 'false' + uses: docker/build-push-action@v2 + with: + context: . + file: ./Dockerfile + push: true + tags: ghcr.io/${{ github.repository }}:${{ steps.set_tag.outputs.tag }} + + - name: Build and push Docker image for tags + if: steps.check_tag.outputs.triggered_by_tag == 'true' + uses: docker/build-push-action@v2 + with: + context: . + file: ./Dockerfile + push: true + tags: | + ghcr.io/${{ github.repository }}:${{ steps.set_tag.outputs.tag }} + ghcr.io/${{ github.repository }}:latest From 8e531836850c6978d5499a3e7d17ba33e8e54e87 Mon Sep 17 00:00:00 2001 From: nitezs Date: Fri, 15 Sep 2023 10:29:10 +0800 Subject: [PATCH 8/8] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=A7=84=E5=88=99?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E9=A1=BA=E5=BA=8F=E9=94=99=E8=AF=AF=EF=BC=8C?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E6=97=A0=E6=B3=95=E6=8B=A6=E6=88=AA=E5=B9=BF?= =?UTF-8?q?=E5=91=8A=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/template_meta.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/template_meta.yaml b/templates/template_meta.yaml index 7287b80..ea0bcf0 100644 --- a/templates/template_meta.yaml +++ b/templates/template_meta.yaml @@ -50,12 +50,12 @@ proxy-groups: rules: - GEOSITE,private,全球直连 - GEOIP,private,全球直连 + - GEOSITE,category-ads-all,广告拦截 + - GEOSITE,CN,全球直连 + - GEOIP,CN,全球直连 - GEOSITE,biliintl,哔哩哔哩 - GEOSITE,bilibili,哔哩哔哩 - GEOSITE,bahamut,巴哈姆特 - - GEOSITE,CN,全球直连 - - GEOIP,CN,全球直连 - GEOSITE,category-games,游戏平台 - GEOSITE,geolocation-!cn,节点选择 - - GEOSITE,category-ads-all,广告拦截 - MATCH,漏网之鱼 \ No newline at end of file