diff --git a/internal/model/server/server.go b/internal/model/server/server.go index beae1c5..dff001d 100644 --- a/internal/model/server/server.go +++ b/internal/model/server/server.go @@ -9,11 +9,11 @@ import ( ) const ( - RelayModeNone = "none" - RelayModeAll = "all" - RelayModeRandom = "random" - RuleGroupType = "ban" - RuleGroupAuto = "auto" + RelayModeNone = "none" + RelayModeAll = "all" + RelayModeRandom = "random" + RuleGroupTypeBan = "ban" + RuleGroupTypeAuto = "auto" ) type ServerFilter struct { diff --git a/pkg/adapter/adapter.go b/pkg/adapter/adapter.go index f687663..10dfb44 100644 --- a/pkg/adapter/adapter.go +++ b/pkg/adapter/adapter.go @@ -26,17 +26,21 @@ type Adapter struct { func NewAdapter(cfg *Config) *Adapter { // 转换服务器列表 proxies := adapterProxies(cfg.Nodes) - // 生成代理组 - proxyGroup, nodes := generateProxyGroup(proxies) - + defaultGroup := FindDefaultGroup(cfg.Rules) // 转换规则组 g, r := adapterRules(cfg.Rules) + // 生成代理组 + proxyGroup, nodes := generateProxyGroup(proxies) + // 加入兜底节点 for i, group := range g { + if group.Direct { + continue + } if len(group.Proxies) == 0 { - p := append([]string{"智能线路"}, nodes...) - g[i].Proxies = append(p, "REJECT", "DIRECT") + p := append([]string{"Auto Select", "Selection"}, nodes...) + g[i].Proxies = append(p, "DIRECT") } } @@ -44,12 +48,14 @@ func NewAdapter(cfg *Config) *Adapter { proxyGroup = RemoveEmptyGroup(append(proxyGroup, g...)) // 处理标签 proxyGroup = adapterTags(cfg.Tags, proxyGroup) + return &Adapter{ Adapter: proxy.Adapter{ Proxies: proxies, - Group: proxyGroup, + Group: SortGroups(proxyGroup, defaultGroup), Rules: r, Nodes: nodes, + Default: defaultGroup, }, } } diff --git a/pkg/adapter/clash/clash.go b/pkg/adapter/clash/clash.go index 1a6bc68..e4c59dd 100644 --- a/pkg/adapter/clash/clash.go +++ b/pkg/adapter/clash/clash.go @@ -45,7 +45,7 @@ func (c *Clash) Build(uuid string) ([]byte, error) { }) } rawConfig.ProxyGroups = groups - rawConfig.Rules = append(c.Rules, "MATCH,手动选择") + rawConfig.Rules = append(c.Rules, fmt.Sprintf("MATCH,%s", c.Default)) return yaml.Marshal(&rawConfig) } diff --git a/pkg/adapter/proxy/proxy.go b/pkg/adapter/proxy/proxy.go index 458ac7b..22f1303 100644 --- a/pkg/adapter/proxy/proxy.go +++ b/pkg/adapter/proxy/proxy.go @@ -26,6 +26,7 @@ type Group struct { Proxies []string URL string Interval int + Direct bool } type GroupType string diff --git a/pkg/adapter/singbox/build.go b/pkg/adapter/singbox/build.go index dc2d27e..8962c2b 100644 --- a/pkg/adapter/singbox/build.go +++ b/pkg/adapter/singbox/build.go @@ -79,7 +79,7 @@ func BuildSingbox(adapter proxy.Adapter, uuid string) ([]byte, error) { rawConfig["outbounds"] = proxies route := RouteOptions{ - Final: "手动选择", + Final: adapter.Default, Rules: []Rule{ { Inbound: []string{ @@ -114,7 +114,7 @@ func BuildSingbox(adapter proxy.Adapter, uuid string) ([]byte, error) { }, { ClashMode: "global", - Outbound: "手动选择", + Outbound: adapter.Default, }, { IPIsPrivate: true, diff --git a/pkg/adapter/uilts.go b/pkg/adapter/uilts.go index 309b32e..cfe9f3e 100644 --- a/pkg/adapter/uilts.go +++ b/pkg/adapter/uilts.go @@ -99,11 +99,29 @@ func addProxyToGroup(proxyName, groupName string, groups []proxy.Group) []proxy. func adapterRules(groups []*server.RuleGroup) (proxyGroup []proxy.Group, rules []string) { for _, group := range groups { - proxyGroup = append(proxyGroup, proxy.Group{ - Name: group.Name, - Type: proxy.GroupTypeSelect, - Proxies: RemoveEmptyString(strings.Split(group.Tags, ",")), - }) + switch group.Type { + case server.RuleGroupTypeBan: + proxyGroup = append(proxyGroup, proxy.Group{ + Name: group.Name, + Type: proxy.GroupTypeSelect, + Proxies: []string{"REJECT", "DIRECT"}, + Direct: true, + }) + case server.RuleGroupTypeAuto: + proxyGroup = append(proxyGroup, proxy.Group{ + Name: group.Name, + Type: proxy.GroupTypeURLTest, + URL: "https://www.gstatic.com/generate_204", + Proxies: RemoveEmptyString(strings.Split(group.Tags, ",")), + }) + default: + proxyGroup = append(proxyGroup, proxy.Group{ + Name: group.Name, + Type: proxy.GroupTypeSelect, + Proxies: RemoveEmptyString(strings.Split(group.Tags, ",")), + }) + } + rules = append(rules, strings.Split(group.Rules, "\n")...) } return @@ -122,29 +140,26 @@ func adapterTags(tags map[string][]*server.Server, group []proxy.Group) (proxyGr } func generateProxyGroup(servers []proxy.Proxy) (proxyGroup []proxy.Group, nodes []string) { + proxyGroup = append(proxyGroup, proxy.Group{ + Name: "Auto Select", + Type: proxy.GroupTypeURLTest, + Proxies: make([]string, 0), + URL: "https://www.gstatic.com/generate_204", + Interval: 300, + }) + // 设置手动选择分组 - proxyGroup = append(proxyGroup, []proxy.Group{ - { - Name: "智能线路", - Type: proxy.GroupTypeURLTest, - Proxies: make([]string, 0), - URL: "https://www.gstatic.com/generate_204", - Interval: 300, - }, - { - Name: "手动选择", - Type: proxy.GroupTypeSelect, - Proxies: []string{"智能线路"}, - }, - }...) + proxyGroup = append(proxyGroup, proxy.Group{ + Name: "Selection", + Type: proxy.GroupTypeSelect, + Proxies: []string{"Auto Select"}, + }) for _, node := range servers { - proxyGroup = addProxyToGroup(node.Name, "智能线路", proxyGroup) - proxyGroup = addProxyToGroup(node.Name, "手动选择", proxyGroup) + proxyGroup = addProxyToGroup(node.Name, "Auto Select", proxyGroup) + proxyGroup = addProxyToGroup(node.Name, "Selection", proxyGroup) nodes = append(nodes, node.Name) } - - proxyGroup = addProxyToGroup("DIRECT", "手动选择", proxyGroup) return proxyGroup, tool.RemoveDuplicateElements(nodes...) } @@ -206,6 +221,7 @@ func RemoveEmptyString(arr []string) []string { return result } +// RemoveEmptyGroup removes empty groups from the provided slice of proxy groups. func RemoveEmptyGroup(arr []proxy.Group) []proxy.Group { var result []proxy.Group var removeNames []string @@ -221,3 +237,56 @@ func RemoveEmptyGroup(arr []proxy.Group) []proxy.Group { } return result } + +// FindDefaultGroup finds the default rule group from a list of rule groups. +func FindDefaultGroup(groups []*server.RuleGroup) string { + for _, group := range groups { + if group.Default { + return group.Name + } + } + return "智能线路" +} + +// SortGroups sorts the provided slice of proxy groups by their names. +func SortGroups(groups []proxy.Group, defaultName string) []proxy.Group { + var sortedGroups []proxy.Group + var selectedGroup proxy.Group + // 在所有分组找到默认分组并将他放到第一个 + for _, group := range groups { + if group.Name == defaultName { + group.Proxies = tool.RemoveStringElement(group.Proxies, defaultName, "REJECT") + sortedGroups = append([]proxy.Group{group}, sortedGroups...) + continue + } else if group.Name == "Selection" { + group.Proxies = tool.RemoveStringElement(group.Proxies, defaultName) + selectedGroup = group + continue + } else if group.Name == "Auto Select" { + group.Proxies = tool.RemoveStringElement(group.Proxies, defaultName, group.Name) + sortedGroups = append([]proxy.Group{group}, sortedGroups...) + continue + } + sortedGroups = append(sortedGroups, group) + } + // 将手动选择分组放到最后 + if selectedGroup.Name != "" { + sortedGroups = append(sortedGroups, selectedGroup) + } + return sortedGroups + +} + +// RemoveElementByName removes elements from the slice of proxy groups by their names. +func RemoveElementByName(groups []proxy.Group, names ...string) []proxy.Group { + for i := 0; i < len(groups); i++ { + for _, name := range names { + if groups[i].Name == name { + groups = append(groups[:i], groups[i+1:]...) + i-- // Adjust index after removal + break // Exit inner loop to avoid index out of range + } + } + } + return groups +}