From c00b0b7c437a65dfef7813dddc4ff666bad1941c Mon Sep 17 00:00:00 2001 From: DHR60 Date: Thu, 11 Sep 2025 16:11:34 +0800 Subject: [PATCH] Add PolicyGroup include other Group support --- .../Singbox/CoreConfigSingboxService.cs | 5 ++ .../Singbox/SingboxOutboundService.cs | 50 +++++++++++++++---- .../V2ray/CoreConfigV2rayService.cs | 5 ++ .../CoreConfig/V2ray/V2rayOutboundService.cs | 42 +++++++++++++--- .../Views/AddGroupServerWindow.axaml.cs | 9 +++- .../v2rayN/Views/AddGroupServerWindow.xaml.cs | 9 +++- 6 files changed, 102 insertions(+), 18 deletions(-) diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/CoreConfigSingboxService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/CoreConfigSingboxService.cs index f938bc8a..61b43567 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/CoreConfigSingboxService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/CoreConfigSingboxService.cs @@ -408,6 +408,11 @@ public partial class CoreConfigSingboxService(Config config) var proxyProfiles = new List(); foreach (var it in selecteds) { + if (it.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) + { + var itemGroup = await AppManager.Instance.GetProfileItem(it.IndexId); + proxyProfiles.Add(itemGroup); + } if (!Global.SingboxSupportConfigType.Contains(it.ConfigType)) { continue; diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs index 701ca575..d4832ca2 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs @@ -410,7 +410,7 @@ public partial class CoreConfigSingboxService return 0; } - private async Task GenOutboundsList(List nodes, SingboxConfig singboxConfig, EMultipleLoad multipleLoad) + private async Task GenOutboundsList(List nodes, SingboxConfig singboxConfig, EMultipleLoad multipleLoad, string baseTagName = Global.ProxyTag) { try { @@ -438,6 +438,38 @@ public partial class CoreConfigSingboxService { index++; + if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) + { + ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem); + if (profileGroupItem == null || profileGroupItem.ChildItems.IsNullOrEmpty()) + { + continue; + } + var childProfiles = (await Task.WhenAll( + Utils.String2List(profileGroupItem.ChildItems) + .Where(p => !p.IsNullOrEmpty()) + .Select(AppManager.Instance.GetProfileItem) + )).Where(p => p != null).ToList(); + if (childProfiles.Count <= 0) + { + continue; + } + var childBaseTagName = $"{baseTagName}-{index}"; + var ret = node.ConfigType switch + { + EConfigType.PolicyGroup => + await GenOutboundsList(childProfiles, singboxConfig, profileGroupItem.MultipleLoad, childBaseTagName), + EConfigType.ProxyChain => + await GenChainOutboundsList(childProfiles, singboxConfig, childBaseTagName), + _ => throw new NotImplementedException() + }; + if (ret == 0) + { + proxyTags.Add(childBaseTagName); + } + continue; + } + // Handle proxy chain string? prevTag = null; var currentServer = await GenServer(node); @@ -450,7 +482,7 @@ public partial class CoreConfigSingboxService var subItem = await AppManager.Instance.GetSubItem(node.Subid); // current proxy - currentServer.tag = $"{Global.ProxyTag}-{index}"; + currentServer.tag = $"{baseTagName}-{index}"; proxyTags.Add(currentServer.tag); if (!node.Subid.IsNullOrEmpty()) @@ -467,7 +499,7 @@ public partial class CoreConfigSingboxService { var prevOutbound = JsonUtils.Deserialize(txtOutbound); await GenOutbound(prevNode, prevOutbound); - prevTag = $"prev-{Global.ProxyTag}-{++prevIndex}"; + prevTag = $"prev-{baseTagName}-{++prevIndex}"; prevOutbound.tag = prevTag; prevOutbounds.Add(prevOutbound); } @@ -508,7 +540,7 @@ public partial class CoreConfigSingboxService var outUrltest = new Outbound4Sbox { type = "urltest", - tag = $"{Global.ProxyTag}-auto", + tag = $"{baseTagName}-auto", outbounds = proxyTags, interrupt_exist_connections = false, }; @@ -522,7 +554,7 @@ public partial class CoreConfigSingboxService var outSelector = new Outbound4Sbox { type = "selector", - tag = Global.ProxyTag, + tag = baseTagName, outbounds = JsonUtils.DeepCopy(proxyTags), interrupt_exist_connections = false, }; @@ -580,7 +612,7 @@ public partial class CoreConfigSingboxService return null; } - private async Task GenChainOutboundsList(List nodes, SingboxConfig singboxConfig) + private async Task GenChainOutboundsList(List nodes, SingboxConfig singboxConfig, string baseTagName = Global.ProxyTag) { var resultOutbounds = new List(); var resultEndpoints = new List(); // For endpoints @@ -596,16 +628,16 @@ public partial class CoreConfigSingboxService if (i == 0) { - server.tag = Global.ProxyTag; + server.tag = baseTagName; } else { - server.tag = Global.ProxyTag + i.ToString(); + server.tag = baseTagName + i.ToString(); } if (i != nodes.Count - 1) { - server.detour = Global.ProxyTag + (i + 1).ToString(); + server.detour = baseTagName + (i + 1).ToString(); } if (server is Endpoints4Sbox endpoint) diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/CoreConfigV2rayService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/CoreConfigV2rayService.cs index ec44bbf4..3525383c 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/CoreConfigV2rayService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/CoreConfigV2rayService.cs @@ -137,6 +137,11 @@ public partial class CoreConfigV2rayService(Config config) var proxyProfiles = new List(); foreach (var it in selecteds) { + if (it.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) + { + var itemGroup = await AppManager.Instance.GetProfileItem(it.IndexId); + proxyProfiles.Add(itemGroup); + } if (!Global.XraySupportConfigType.Contains(it.ConfigType)) { continue; diff --git a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs index 565ec587..e827946f 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs @@ -552,7 +552,7 @@ public partial class CoreConfigV2rayService return 0; } - private async Task GenOutboundsList(List nodes, V2rayConfig v2rayConfig) + private async Task GenOutboundsList(List nodes, V2rayConfig v2rayConfig, string baseTagName = Global.ProxyTag) { try { @@ -577,6 +577,34 @@ public partial class CoreConfigV2rayService { index++; + if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) + { + ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem); + if (profileGroupItem == null || profileGroupItem.ChildItems.IsNullOrEmpty()) + { + continue; + } + var childProfiles = (await Task.WhenAll( + Utils.String2List(profileGroupItem.ChildItems) + .Where(p => !p.IsNullOrEmpty()) + .Select(AppManager.Instance.GetProfileItem) + )).Where(p => p != null).ToList(); + if (childProfiles.Count <= 0) + { + continue; + } + var childBaseTagName = $"{baseTagName}-{index}"; + var ret = node.ConfigType switch + { + EConfigType.PolicyGroup => + await GenOutboundsList(childProfiles, v2rayConfig, childBaseTagName), + EConfigType.ProxyChain => + await GenChainOutboundsList(childProfiles, v2rayConfig, childBaseTagName), + _ => throw new NotImplementedException() + }; + continue; + } + // Handle proxy chain string? prevTag = null; var currentOutbound = JsonUtils.Deserialize(txtOutbound); @@ -590,7 +618,7 @@ public partial class CoreConfigV2rayService // current proxy await GenOutbound(node, currentOutbound); - currentOutbound.tag = $"{Global.ProxyTag}-{index}"; + currentOutbound.tag = $"{baseTagName}-{index}"; if (!node.Subid.IsNullOrEmpty()) { @@ -606,7 +634,7 @@ public partial class CoreConfigV2rayService { var prevOutbound = JsonUtils.Deserialize(txtOutbound); await GenOutbound(prevNode, prevOutbound); - prevTag = $"prev-{Global.ProxyTag}-{++prevIndex}"; + prevTag = $"prev-{baseTagName}-{++prevIndex}"; prevOutbound.tag = prevTag; prevOutbounds.Add(prevOutbound); } @@ -693,7 +721,7 @@ public partial class CoreConfigV2rayService return null; } - private async Task GenChainOutboundsList(List nodes, V2rayConfig v2RayConfig) + private async Task GenChainOutboundsList(List nodes, V2rayConfig v2RayConfig, string baseTagName = Global.ProxyTag) { var resultOutbounds = new List(); for (var i = 0; i < nodes.Count; i++) @@ -714,18 +742,18 @@ public partial class CoreConfigV2rayService if (i == 0) { - outbound.tag = Global.ProxyTag; + outbound.tag = baseTagName; } else { - outbound.tag = Global.ProxyTag + i.ToString(); + outbound.tag = baseTagName + i.ToString(); } if (i != nodes.Count - 1) { outbound.streamSettings.sockopt = new() { - dialerProxy = Global.ProxyTag + (i + 1).ToString() + dialerProxy = baseTagName + (i + 1).ToString() }; } diff --git a/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs b/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs index ede6bc71..720e5c29 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs @@ -138,7 +138,14 @@ public partial class AddGroupServerWindow : WindowBase private async void MenuAddChild_Click(object? sender, RoutedEventArgs e) { var selectWindow = new ProfilesSelectWindow(); - selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom, EConfigType.PolicyGroup, EConfigType.ProxyChain }, exclude: true); + if (ViewModel?.SelectedSource?.ConfigType == EConfigType.PolicyGroup) + { + selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom }, exclude: true); + } + else + { + selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom, EConfigType.PolicyGroup, EConfigType.ProxyChain }, exclude: true); + } selectWindow.AllowMultiSelect(true); var result = await selectWindow.ShowDialog(this); if (result == true) diff --git a/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs b/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs index 839d6c4c..cf3fa354 100644 --- a/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs @@ -116,7 +116,14 @@ public partial class AddGroupServerWindow private async void MenuAddChild_Click(object sender, RoutedEventArgs e) { var selectWindow = new ProfilesSelectWindow(); - selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom, EConfigType.PolicyGroup, EConfigType.ProxyChain }, exclude: true); + if (ViewModel?.SelectedSource?.ConfigType == EConfigType.PolicyGroup) + { + selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom }, exclude: true); + } + else + { + selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom, EConfigType.PolicyGroup, EConfigType.ProxyChain }, exclude: true); + } selectWindow.AllowMultiSelect(true); if (selectWindow.ShowDialog() == true) {