101 lines
3.0 KiB
Go
101 lines
3.0 KiB
Go
package corecfg
|
|
|
|
import "gitea.epss.net.cn/klesh/ss/internal/automation"
|
|
|
|
// deepMerge merges dict2 into dict1 in place and returns dict1, mirroring
|
|
// corecfg_manager.py's module-level deep_merge(): nested maps recurse,
|
|
// matching lists are concatenated, everything else is overwritten by dict2.
|
|
func deepMerge(dict1, dict2 map[string]interface{}) map[string]interface{} {
|
|
for k, v := range dict2 {
|
|
existing, exists := dict1[k]
|
|
if exists {
|
|
existingMap, existingIsMap := existing.(map[string]interface{})
|
|
vMap, vIsMap := v.(map[string]interface{})
|
|
if existingIsMap && vIsMap {
|
|
dict1[k] = deepMerge(existingMap, vMap)
|
|
continue
|
|
}
|
|
|
|
existingList, existingIsList := existing.([]interface{})
|
|
vList, vIsList := v.([]interface{})
|
|
if existingIsList && vIsList {
|
|
dict1[k] = append(existingList, vList...)
|
|
continue
|
|
}
|
|
}
|
|
dict1[k] = v
|
|
}
|
|
return dict1
|
|
}
|
|
|
|
// popFirstProxyGroup removes and returns data["proxy-groups"]' first entry —
|
|
// by convention a subscription's default selector group, the one its own
|
|
// rules point at — so mergeProxySelection can fold every subscription's
|
|
// default selector into one combined group. Returns nil if there is none.
|
|
func popFirstProxyGroup(data map[string]interface{}) map[string]interface{} {
|
|
groupsRaw, ok := data["proxy-groups"].([]interface{})
|
|
if !ok || len(groupsRaw) == 0 {
|
|
return nil
|
|
}
|
|
|
|
group, ok := groupsRaw[0].(map[string]interface{})
|
|
if !ok {
|
|
return nil
|
|
}
|
|
|
|
data["proxy-groups"] = groupsRaw[1:]
|
|
return group
|
|
}
|
|
|
|
// selectionGroupName is the name given to the proxy-group produced by
|
|
// folding every merged subscription's default selector group together.
|
|
const selectionGroupName = "Proxy Selection"
|
|
|
|
// mergeProxySelection collapses each subscription's default selector group
|
|
// (already popped off by popFirstProxyGroup) into a single combined group
|
|
// named selectionGroupName, covering every subscription's proxies, and
|
|
// rewrites every rule/group reference to the old per-subscription groups so
|
|
// they point at it instead.
|
|
func mergeProxySelection(combined map[string]interface{}, groups []map[string]interface{}) {
|
|
if len(groups) == 0 {
|
|
return
|
|
}
|
|
|
|
rename := make(map[string]string, len(groups))
|
|
seen := make(map[string]bool)
|
|
var groupType interface{}
|
|
var mergedProxies []interface{}
|
|
|
|
for _, group := range groups {
|
|
if name, ok := group["name"].(string); ok {
|
|
rename[name] = selectionGroupName
|
|
}
|
|
if groupType == nil {
|
|
groupType = group["type"]
|
|
}
|
|
if list, ok := group["proxies"].([]interface{}); ok {
|
|
for _, p := range list {
|
|
name, ok := p.(string)
|
|
if ok && seen[name] {
|
|
continue
|
|
}
|
|
if ok {
|
|
seen[name] = true
|
|
}
|
|
mergedProxies = append(mergedProxies, p)
|
|
}
|
|
}
|
|
}
|
|
|
|
merged := map[string]interface{}{
|
|
"name": selectionGroupName,
|
|
"type": groupType,
|
|
"proxies": mergedProxies,
|
|
}
|
|
|
|
existing, _ := combined["proxy-groups"].([]interface{})
|
|
combined["proxy-groups"] = append([]interface{}{merged}, existing...)
|
|
|
|
automation.RewriteReferences(combined, rename)
|
|
}
|