This commit is contained in:
DHR60 2025-09-23 10:27:23 +08:00
parent aab6d3d136
commit 587686ffce
7 changed files with 124 additions and 340 deletions

View file

@ -32,6 +32,12 @@ public class ProfileItem : ReactiveObject
public string GetSummary() public string GetSummary()
{ {
var summary = $"[{(ConfigType).ToString()}] "; var summary = $"[{(ConfigType).ToString()}] ";
if (IsComplex())
{
summary += $"[{CoreType.ToString()}]{Remarks}";
}
else
{
var arrAddr = Address.Contains(':') ? Address.Split(':') : Address.Split('.'); var arrAddr = Address.Contains(':') ? Address.Split(':') : Address.Split('.');
var addr = arrAddr.Length switch var addr = arrAddr.Length switch
{ {
@ -39,12 +45,6 @@ public class ProfileItem : ReactiveObject
> 1 => $"***{arrAddr.Last()}", > 1 => $"***{arrAddr.Last()}",
_ => Address _ => Address
}; };
if (ConfigType is EConfigType.Custom or > EConfigType.Group)
{
summary += $"[{CoreType.ToString()}]{Remarks}";
}
else
{
summary += $"{Remarks}({addr}:{Port})"; summary += $"{Remarks}({addr}:{Port})";
} }
return summary; return summary;

View file

@ -15,35 +15,8 @@ public partial class CoreConfigSingboxService(Config config)
var ret = new RetResult(); var ret = new RetResult();
try try
{ {
if (node?.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
{
ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem);
if (profileGroupItem == null || profileGroupItem.ChildItems.IsNullOrEmpty())
{
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
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)
{
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
switch (node.ConfigType)
{
case EConfigType.PolicyGroup:
return await GenerateClientMultipleLoadConfig(childProfiles, profileGroupItem.MultipleLoad);
case EConfigType.ProxyChain:
return await GenerateClientChainConfig(childProfiles);
}
}
if (node == null if (node == null
|| node.Port <= 0) || !node.IsValid())
{ {
ret.Msg = ResUI.CheckServerSettings; ret.Msg = ResUI.CheckServerSettings;
return ret; return ret;
@ -56,6 +29,17 @@ public partial class CoreConfigSingboxService(Config config)
ret.Msg = ResUI.InitialConfiguration; ret.Msg = ResUI.InitialConfiguration;
if (node?.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
{
switch (node.ConfigType)
{
case EConfigType.PolicyGroup:
return await GenerateClientMultipleLoadConfig(node);
case EConfigType.ProxyChain:
return await GenerateClientChainConfig(node);
}
}
var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient); var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
if (result.IsNullOrEmpty()) if (result.IsNullOrEmpty())
{ {
@ -169,13 +153,10 @@ public partial class CoreConfigSingboxService(Config config)
continue; continue;
} }
var item = await AppManager.Instance.GetProfileItem(it.IndexId); var item = await AppManager.Instance.GetProfileItem(it.IndexId);
if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS) if (item is null || item.IsComplex() || !item.IsValid())
{
if (item is null || item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
{ {
continue; continue;
} }
}
//find unused port //find unused port
var port = initPort; var port = initPort;
@ -214,27 +195,6 @@ public partial class CoreConfigSingboxService(Config config)
singboxConfig.inbounds.Add(inbound); singboxConfig.inbounds.Add(inbound);
//outbound //outbound
if (item is null)
{
continue;
}
if (item.ConfigType == EConfigType.Shadowsocks
&& !Global.SsSecuritiesInSingbox.Contains(item.Security))
{
continue;
}
if (item.ConfigType == EConfigType.VLESS
&& !Global.Flows.Contains(item.Flow))
{
continue;
}
if (it.ConfigType is EConfigType.VLESS or EConfigType.Trojan
&& item.StreamSecurity == Global.StreamSecurityReality
&& item.PublicKey.IsNullOrEmpty())
{
continue;
}
var server = await GenServer(item); var server = await GenServer(item);
if (server is null) if (server is null)
{ {
@ -293,7 +253,8 @@ public partial class CoreConfigSingboxService(Config config)
var ret = new RetResult(); var ret = new RetResult();
try try
{ {
if (node is not { Port: > 0 }) if (node == null
|| !node.IsValid())
{ {
ret.Msg = ResUI.CheckServerSettings; ret.Msg = ResUI.CheckServerSettings;
return ret; return ret;
@ -371,7 +332,7 @@ public partial class CoreConfigSingboxService(Config config)
} }
} }
public async Task<RetResult> GenerateClientMultipleLoadConfig(List<ProfileItem> selecteds, EMultipleLoad multipleLoad) public async Task<RetResult> GenerateClientMultipleLoadConfig(ProfileItem parentNode)
{ {
var ret = new RetResult(); var ret = new RetResult();
try try
@ -405,53 +366,12 @@ public partial class CoreConfigSingboxService(Config config)
await GenRouting(singboxConfig); await GenRouting(singboxConfig);
await GenExperimental(singboxConfig); await GenExperimental(singboxConfig);
var proxyProfiles = new List<ProfileItem>(); var groupRet = await GenGroupOutbound(parentNode, singboxConfig);
foreach (var it in selecteds) if (groupRet != 0)
{
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;
}
if (it.Port <= 0)
{
continue;
}
var item = await AppManager.Instance.GetProfileItem(it.IndexId);
if (item is null)
{
continue;
}
if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS)
{
if (item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
{
continue;
}
}
if (item.ConfigType == EConfigType.Shadowsocks
&& !Global.SsSecuritiesInSingbox.Contains(item.Security))
{
continue;
}
if (item.ConfigType == EConfigType.VLESS && !Global.Flows.Contains(item.Flow))
{
continue;
}
//outbound
proxyProfiles.Add(item);
}
if (proxyProfiles.Count <= 0)
{ {
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }
await GenOutboundsListWithChain(proxyProfiles, singboxConfig, multipleLoad);
await GenDns(null, singboxConfig); await GenDns(null, singboxConfig);
await ConvertGeo2Ruleset(singboxConfig); await ConvertGeo2Ruleset(singboxConfig);
@ -469,7 +389,7 @@ public partial class CoreConfigSingboxService(Config config)
} }
} }
public async Task<RetResult> GenerateClientChainConfig(List<ProfileItem> selecteds) public async Task<RetResult> GenerateClientChainConfig(ProfileItem parentNode)
{ {
var ret = new RetResult(); var ret = new RetResult();
try try
@ -503,48 +423,12 @@ public partial class CoreConfigSingboxService(Config config)
await GenExperimental(singboxConfig); await GenExperimental(singboxConfig);
singboxConfig.outbounds.RemoveAt(0); singboxConfig.outbounds.RemoveAt(0);
var proxyProfiles = new List<ProfileItem>(); var groupRet = await GenGroupOutbound(parentNode, singboxConfig);
foreach (var it in selecteds) if (groupRet != 0)
{
if (!Global.SingboxSupportConfigType.Contains(it.ConfigType))
{
continue;
}
if (it.Port <= 0)
{
continue;
}
var item = await AppManager.Instance.GetProfileItem(it.IndexId);
if (item is null)
{
continue;
}
if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS)
{
if (item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
{
continue;
}
}
if (item.ConfigType == EConfigType.Shadowsocks
&& !Global.SsSecuritiesInSingbox.Contains(item.Security))
{
continue;
}
if (item.ConfigType == EConfigType.VLESS && !Global.Flows.Contains(item.Flow))
{
continue;
}
//outbound
proxyProfiles.Add(item);
}
if (proxyProfiles.Count <= 0)
{ {
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }
await GenChainOutboundsList(proxyProfiles, singboxConfig);
await GenDns(null, singboxConfig); await GenDns(null, singboxConfig);
await ConvertGeo2Ruleset(singboxConfig); await ConvertGeo2Ruleset(singboxConfig);

View file

@ -217,11 +217,21 @@ public partial class CoreConfigSingboxService
{ {
return -1; return -1;
} }
// remove custom nodes
// remove group nodes for proxy chain
var childProfiles = (await Task.WhenAll( var childProfiles = (await Task.WhenAll(
Utils.String2List(profileGroupItem.ChildItems) Utils.String2List(profileGroupItem.ChildItems)
.Where(p => !p.IsNullOrEmpty()) .Where(p => !p.IsNullOrEmpty())
.Select(AppManager.Instance.GetProfileItem) .Select(AppManager.Instance.GetProfileItem)
)).Where(p => p != null && p.IsValid()).ToList(); ))
.Where(p =>
p != null &&
p.IsValid() &&
p.ConfigType != EConfigType.Custom &&
(node.ConfigType == EConfigType.PolicyGroup || p.ConfigType < EConfigType.Group)
)
.ToList();
if (childProfiles.Count <= 0) if (childProfiles.Count <= 0)
{ {
return -1; return -1;

View file

@ -385,29 +385,8 @@ public partial class CoreConfigSingboxService
if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
{ {
ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem);
if (profileGroupItem == null || profileGroupItem.ChildItems.IsNullOrEmpty())
{
return Global.ProxyTag;
}
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)
{
return Global.ProxyTag;
}
var childBaseTagName = $"{Global.ProxyTag}-{node.IndexId}"; var childBaseTagName = $"{Global.ProxyTag}-{node.IndexId}";
var ret = node.ConfigType switch var ret = await GenGroupOutbound(node, singboxConfig, childBaseTagName);
{
EConfigType.PolicyGroup =>
await GenOutboundsListWithChain(childProfiles, singboxConfig, profileGroupItem.MultipleLoad, childBaseTagName),
EConfigType.ProxyChain =>
await GenChainOutboundsList(childProfiles, singboxConfig, childBaseTagName),
_ => throw new NotImplementedException()
};
if (ret == 0) if (ret == 0)
{ {
return childBaseTagName; return childBaseTagName;

View file

@ -15,35 +15,8 @@ public partial class CoreConfigV2rayService(Config config)
var ret = new RetResult(); var ret = new RetResult();
try try
{ {
if (node?.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
{
ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem);
if (profileGroupItem == null || profileGroupItem.ChildItems.IsNullOrEmpty())
{
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
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)
{
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
switch (node.ConfigType)
{
case EConfigType.PolicyGroup:
return await GenerateClientMultipleLoadConfig(childProfiles, profileGroupItem.MultipleLoad);
case EConfigType.ProxyChain:
return await GenerateClientChainConfig(childProfiles);
}
}
if (node == null if (node == null
|| node.Port <= 0) || !node.IsValid())
{ {
ret.Msg = ResUI.CheckServerSettings; ret.Msg = ResUI.CheckServerSettings;
return ret; return ret;
@ -57,6 +30,17 @@ public partial class CoreConfigV2rayService(Config config)
ret.Msg = ResUI.InitialConfiguration; ret.Msg = ResUI.InitialConfiguration;
if (node?.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
{
switch (node.ConfigType)
{
case EConfigType.PolicyGroup:
return await GenerateClientMultipleLoadConfig(node);
case EConfigType.ProxyChain:
return await GenerateClientChainConfig(node);
}
}
var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient); var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
if (result.IsNullOrEmpty()) if (result.IsNullOrEmpty())
{ {
@ -98,7 +82,7 @@ public partial class CoreConfigV2rayService(Config config)
} }
} }
public async Task<RetResult> GenerateClientMultipleLoadConfig(List<ProfileItem> selecteds, EMultipleLoad multipleLoad) public async Task<RetResult> GenerateClientMultipleLoadConfig(ProfileItem parentNode)
{ {
var ret = new RetResult(); var ret = new RetResult();
@ -134,57 +118,12 @@ public partial class CoreConfigV2rayService(Config config)
await GenDns(null, v2rayConfig); await GenDns(null, v2rayConfig);
await GenStatistic(v2rayConfig); await GenStatistic(v2rayConfig);
var proxyProfiles = new List<ProfileItem>(); var groupRet = await GenGroupOutbound(parentNode, v2rayConfig);
foreach (var it in selecteds) if (groupRet != 0)
{
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;
}
if (it.Port <= 0)
{
continue;
}
var item = await AppManager.Instance.GetProfileItem(it.IndexId);
if (item is null)
{
continue;
}
if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS)
{
if (item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
{
continue;
}
}
if (item.ConfigType == EConfigType.Shadowsocks
&& !Global.SsSecuritiesInSingbox.Contains(item.Security))
{
continue;
}
if (item.ConfigType == EConfigType.VLESS && !Global.Flows.Contains(item.Flow))
{
continue;
}
//outbound
proxyProfiles.Add(item);
}
if (proxyProfiles.Count <= 0)
{ {
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }
await GenOutboundsListWithChain(proxyProfiles, v2rayConfig);
//add balancers
await GenObservatory(v2rayConfig, multipleLoad);
await GenBalancer(v2rayConfig, multipleLoad);
var defaultBalancerTag = $"{Global.ProxyTag}{Global.BalancerTagSuffix}"; var defaultBalancerTag = $"{Global.ProxyTag}{Global.BalancerTagSuffix}";
@ -248,7 +187,7 @@ public partial class CoreConfigV2rayService(Config config)
} }
} }
public async Task<RetResult> GenerateClientChainConfig(List<ProfileItem> selecteds) public async Task<RetResult> GenerateClientChainConfig(ProfileItem parentNode)
{ {
var ret = new RetResult(); var ret = new RetResult();
@ -284,48 +223,12 @@ public partial class CoreConfigV2rayService(Config config)
await GenStatistic(v2rayConfig); await GenStatistic(v2rayConfig);
v2rayConfig.outbounds.RemoveAt(0); v2rayConfig.outbounds.RemoveAt(0);
var proxyProfiles = new List<ProfileItem>(); var groupRet = await GenGroupOutbound(parentNode, v2rayConfig);
foreach (var it in selecteds) if (groupRet != 0)
{
if (!Global.XraySupportConfigType.Contains(it.ConfigType))
{
continue;
}
if (it.Port <= 0)
{
continue;
}
var item = await AppManager.Instance.GetProfileItem(it.IndexId);
if (item is null)
{
continue;
}
if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS)
{
if (item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
{
continue;
}
}
if (item.ConfigType == EConfigType.Shadowsocks
&& !Global.SsSecuritiesInSingbox.Contains(item.Security))
{
continue;
}
if (item.ConfigType == EConfigType.VLESS && !Global.Flows.Contains(item.Flow))
{
continue;
}
//outbound
proxyProfiles.Add(item);
}
if (proxyProfiles.Count <= 0)
{ {
ret.Msg = ResUI.FailedGenDefaultConfiguration; ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret; return ret;
} }
await GenChainOutboundsList(proxyProfiles, v2rayConfig);
ret.Success = true; ret.Success = true;
@ -398,13 +301,10 @@ public partial class CoreConfigV2rayService(Config config)
continue; continue;
} }
var item = await AppManager.Instance.GetProfileItem(it.IndexId); var item = await AppManager.Instance.GetProfileItem(it.IndexId);
if (it.ConfigType is EConfigType.VMess or EConfigType.VLESS) if (item is null || item.IsComplex() || !item.IsValid())
{
if (item is null || item.Id.IsNullOrEmpty() || !Utils.IsGuidByParse(item.Id))
{ {
continue; continue;
} }
}
//find unused port //find unused port
var port = initPort; var port = initPort;
@ -432,28 +332,6 @@ public partial class CoreConfigV2rayService(Config config)
it.Port = port; it.Port = port;
it.AllowTest = true; it.AllowTest = true;
//outbound
if (item is null)
{
continue;
}
if (item.ConfigType == EConfigType.Shadowsocks
&& !Global.SsSecuritiesInXray.Contains(item.Security))
{
continue;
}
if (item.ConfigType == EConfigType.VLESS
&& !Global.Flows.Contains(item.Flow))
{
continue;
}
if (it.ConfigType is EConfigType.VLESS or EConfigType.Trojan
&& item.StreamSecurity == Global.StreamSecurityReality
&& item.PublicKey.IsNullOrEmpty())
{
continue;
}
//inbound //inbound
Inbounds4Ray inbound = new() Inbounds4Ray inbound = new()
{ {
@ -464,6 +342,7 @@ public partial class CoreConfigV2rayService(Config config)
inbound.tag = inbound.protocol + inbound.port.ToString(); inbound.tag = inbound.protocol + inbound.port.ToString();
v2rayConfig.inbounds.Add(inbound); v2rayConfig.inbounds.Add(inbound);
//outbound
var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound); var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
await GenOutbound(item, outbound); await GenOutbound(item, outbound);
outbound.tag = Global.ProxyTag + inbound.port.ToString(); outbound.tag = Global.ProxyTag + inbound.port.ToString();
@ -497,7 +376,8 @@ public partial class CoreConfigV2rayService(Config config)
var ret = new RetResult(); var ret = new RetResult();
try try
{ {
if (node is not { Port: > 0 }) if (node == null
|| !node.IsValid())
{ {
ret.Msg = ResUI.CheckServerSettings; ret.Msg = ResUI.CheckServerSettings;
return ret; return ret;

View file

@ -480,6 +480,62 @@ public partial class CoreConfigV2rayService
return 0; return 0;
} }
private async Task<int> GenGroupOutbound(ProfileItem node, V2rayConfig v2rayConfig, string baseTagName = Global.ProxyTag)
{
try
{
if (node.ConfigType is not (EConfigType.PolicyGroup or EConfigType.ProxyChain))
{
return -1;
}
ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem);
if (profileGroupItem is null || profileGroupItem.ChildItems.IsNullOrEmpty())
{
return -1;
}
// remove custom nodes
// remove group nodes for proxy chain
var childProfiles = (await Task.WhenAll(
Utils.String2List(profileGroupItem.ChildItems)
.Where(p => !p.IsNullOrEmpty())
.Select(AppManager.Instance.GetProfileItem)
))
.Where(p =>
p != null &&
p.IsValid() &&
p.ConfigType != EConfigType.Custom &&
(node.ConfigType == EConfigType.PolicyGroup || p.ConfigType < EConfigType.Group)
)
.ToList();
if (childProfiles.Count <= 0)
{
return -1;
}
switch (node.ConfigType)
{
case EConfigType.PolicyGroup:
await GenOutboundsListWithChain(childProfiles, v2rayConfig, baseTagName);
break;
case EConfigType.ProxyChain:
await GenChainOutboundsList(childProfiles, v2rayConfig, baseTagName);
break;
default:
break;
}
//add balancers
await GenObservatory(v2rayConfig, profileGroupItem.MultipleLoad, baseTagName);
await GenBalancer(v2rayConfig, profileGroupItem.MultipleLoad, baseTagName);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return await Task.FromResult(0);
}
private async Task<int> GenMoreOutbounds(ProfileItem node, V2rayConfig v2rayConfig) private async Task<int> GenMoreOutbounds(ProfileItem node, V2rayConfig v2rayConfig)
{ {
//fragment proxy //fragment proxy

View file

@ -141,33 +141,8 @@ public partial class CoreConfigV2rayService
if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain) if (node.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
{ {
ProfileGroupItemManager.Instance.TryGet(node.IndexId, out var profileGroupItem);
if (profileGroupItem == null || profileGroupItem.ChildItems.IsNullOrEmpty())
{
return Global.ProxyTag;
}
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)
{
return Global.ProxyTag;
}
var childBaseTagName = $"{Global.ProxyTag}-{node.IndexId}"; var childBaseTagName = $"{Global.ProxyTag}-{node.IndexId}";
var ret = node.ConfigType switch var ret = await GenGroupOutbound(node, v2rayConfig, childBaseTagName);
{
EConfigType.PolicyGroup =>
await GenOutboundsListWithChain(childProfiles, v2rayConfig, childBaseTagName),
EConfigType.ProxyChain =>
await GenChainOutboundsList(childProfiles, v2rayConfig, childBaseTagName),
_ => throw new NotImplementedException()
};
if (node.ConfigType == EConfigType.PolicyGroup)
{
await GenBalancer(v2rayConfig, profileGroupItem.MultipleLoad, childBaseTagName);
}
if (ret == 0) if (ret == 0)
{ {
return childBaseTagName; return childBaseTagName;