feat(proxy): enhance proxy group handling and sorting logic

This commit is contained in:
Chang lue Tsen 2025-07-16 14:17:36 -04:00 committed by Leif Draven
parent 979e39b9e5
commit 97024dd1df
6 changed files with 113 additions and 37 deletions

View File

@ -12,8 +12,8 @@ const (
RelayModeNone = "none"
RelayModeAll = "all"
RelayModeRandom = "random"
RuleGroupType = "ban"
RuleGroupAuto = "auto"
RuleGroupTypeBan = "ban"
RuleGroupTypeAuto = "auto"
)
type ServerFilter struct {

View File

@ -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,
},
}
}

View File

@ -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)
}

View File

@ -26,6 +26,7 @@ type Group struct {
Proxies []string
URL string
Interval int
Direct bool
}
type GroupType string

View File

@ -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,

View File

@ -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 {
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: "智能线路",
proxyGroup = append(proxyGroup, proxy.Group{
Name: "Auto Select",
Type: proxy.GroupTypeURLTest,
Proxies: make([]string, 0),
URL: "https://www.gstatic.com/generate_204",
Interval: 300,
},
{
Name: "手动选择",
})
// 设置手动选择分组
proxyGroup = append(proxyGroup, proxy.Group{
Name: "Selection",
Type: proxy.GroupTypeSelect,
Proxies: []string{"智能线路"},
},
}...)
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
}