fix: drop nodes that fail geo detection in collection rename
Nodes whose country cannot be detected are now filtered out instead of kept with their original name. This prevents unlabelled/unrenamed nodes from appearing in collection output.
This commit is contained in:
@@ -30,17 +30,18 @@ func resolveRenameOptions(opts *model.RenameOptions) model.RenameOptions {
|
||||
|
||||
// RenameCollectionNodes renames proxy nodes in the collection-level format:
|
||||
//
|
||||
// [emoji country flag] [alias] [country name] [city] [-1...-N]
|
||||
// [emoji country flag] [alias] [country name] [city] [01...NN]
|
||||
//
|
||||
// The alias is read from each node's "_sourceAlias" field (tagged by the
|
||||
// subscription service from the source's Alias). Geographic info (flag,
|
||||
// country, city) is auto-detected from the node's original name and server.
|
||||
//
|
||||
// Nodes are grouped by their **display baseName** (the name without the index
|
||||
// suffix) and numbered sequentially within each group, starting at 1. This
|
||||
// ensures that nodes producing the same display name get unique suffixes
|
||||
// (-1, -2, -3, …) in a single pass, so EnsureUniqueProxyNames never needs to
|
||||
// append a secondary suffix.
|
||||
// suffix) and numbered sequentially within each group, starting at 1.
|
||||
//
|
||||
// Nodes whose geographic info cannot be detected (no country found) are
|
||||
// dropped from the output — they cannot be meaningfully renamed and would
|
||||
// appear as unlabelled entries in the collection.
|
||||
//
|
||||
// opts controls which fields are included in the output. A nil opts means all
|
||||
// fields are included (full default format).
|
||||
@@ -54,13 +55,12 @@ func RenameCollectionNodes(proxies []model.ProxyNode, opts *model.RenameOptions)
|
||||
// First pass: compute display baseName (without index) for each node.
|
||||
type nodeInfo struct {
|
||||
proxy model.ProxyNode
|
||||
baseName string // display name without index suffix; "" means skip rename
|
||||
baseName string // display name without index suffix; "" means geo failed
|
||||
}
|
||||
|
||||
infos := make([]nodeInfo, len(proxies))
|
||||
for i, proxy := range proxies {
|
||||
infos := make([]nodeInfo, 0, len(proxies))
|
||||
for _, proxy := range proxies {
|
||||
if proxy == nil {
|
||||
infos[i] = nodeInfo{proxy: proxy}
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ func RenameCollectionNodes(proxies []model.ProxyNode, opts *model.RenameOptions)
|
||||
|
||||
geo := util.DetectGeoWithServer(name, server)
|
||||
if geo.CountryName == "" {
|
||||
infos[i] = nodeInfo{proxy: proxy}
|
||||
// Geo detection failed — skip this node
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -96,34 +96,22 @@ func RenameCollectionNodes(proxies []model.ProxyNode, opts *model.RenameOptions)
|
||||
parts = append(parts, geo.CityCN)
|
||||
}
|
||||
|
||||
infos[i] = nodeInfo{
|
||||
infos = append(infos, nodeInfo{
|
||||
proxy: proxy,
|
||||
baseName: strings.Join(parts, " "),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Count group sizes by baseName.
|
||||
baseCounts := make(map[string]int)
|
||||
for _, info := range infos {
|
||||
if info.baseName != "" {
|
||||
baseCounts[info.baseName]++
|
||||
}
|
||||
baseCounts[info.baseName]++
|
||||
}
|
||||
|
||||
// Second pass: assign names with sequential numbering.
|
||||
counters := make(map[string]int)
|
||||
results := make([]model.ProxyNode, len(proxies))
|
||||
for i, info := range infos {
|
||||
if info.proxy == nil {
|
||||
results[i] = info.proxy
|
||||
continue
|
||||
}
|
||||
if info.baseName == "" {
|
||||
// Geo detection failed — keep original name.
|
||||
results[i] = info.proxy
|
||||
continue
|
||||
}
|
||||
|
||||
results := make([]model.ProxyNode, 0, len(infos))
|
||||
for _, info := range infos {
|
||||
counters[info.baseName]++
|
||||
total := baseCounts[info.baseName]
|
||||
|
||||
@@ -135,7 +123,7 @@ func RenameCollectionNodes(proxies []model.ProxyNode, opts *model.RenameOptions)
|
||||
next := cloneProxy(info.proxy)
|
||||
delete(next, "_sourceAlias")
|
||||
next["name"] = name
|
||||
results[i] = next
|
||||
results = append(results, next)
|
||||
}
|
||||
|
||||
return results
|
||||
|
||||
@@ -110,12 +110,8 @@ func TestRenameCollectionNodes_UnknownCountry(t *testing.T) {
|
||||
{"name": "Unknown Node", "type": "ss", "_sourceAlias": "A"},
|
||||
}
|
||||
result := RenameCollectionNodes(proxies, nil)
|
||||
if len(result) != 1 {
|
||||
t.Fatalf("expected 1 node, got %d", len(result))
|
||||
}
|
||||
// Should keep original name
|
||||
if result[0]["name"] != "Unknown Node" {
|
||||
t.Errorf("expected original name, got %q", result[0]["name"])
|
||||
if len(result) != 0 {
|
||||
t.Fatalf("expected 0 nodes (geo detection failed, should be filtered), got %d", len(result))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user