Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Refactor
  • Loading branch information
DHR60 committed Feb 5, 2026
commit a6b12aa718778a05f6901bdff2ac4cf07a7ca118
62 changes: 16 additions & 46 deletions v2rayN/ServiceLib/Handler/ConfigHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ public static async Task<int> AddServer(Config config, ProfileItem profileItem)
item.CertSha = profileItem.CertSha;
item.EchConfigList = profileItem.EchConfigList;
item.EchForceQuery = profileItem.EchForceQuery;
item.JsonData = profileItem.JsonData;
}

var ret = item.ConfigType switch
Expand Down Expand Up @@ -360,11 +361,6 @@ public static async Task<int> CopyServer(Config config, List<ProfileItem> indexe
{
}
}
else if (profileItem.ConfigType.IsGroupType())
{
var profileGroupItem = await AppManager.Instance.GetProfileGroupItem(it.IndexId);
await AddGroupServerCommon(config, profileItem, profileGroupItem, true);
}
else
{
await AddServerCommon(config, profileItem, true);
Expand Down Expand Up @@ -967,9 +963,11 @@ public static async Task<int> AddVlessServer(Config config, ProfileItem profileI
profileItem.Path = profileItem.Path.TrimEx();
profileItem.StreamSecurity = profileItem.StreamSecurity.TrimEx();

if (!Global.Flows.Contains(profileItem.Flow))
var extraItem = profileItem.GetExtraItem();

if (!Global.Flows.Contains(extraItem.Flow ?? string.Empty))
{
profileItem.Flow = Global.Flows.First();
extraItem.Flow = Global.Flows.First();
}
if (profileItem.Id.IsNullOrEmpty())
{
Expand All @@ -980,6 +978,8 @@ public static async Task<int> AddVlessServer(Config config, ProfileItem profileI
profileItem.Security = Global.None;
}

profileItem.SetExtraItem(extraItem);

await AddServerCommon(config, profileItem, toFile);

return 0;
Expand Down Expand Up @@ -1082,37 +1082,6 @@ public static async Task<int> AddServerCommon(Config config, ProfileItem profile
return 0;
}

public static async Task<int> AddGroupServerCommon(Config config, ProfileItem profileItem, ProfileGroupItem profileGroupItem, bool toFile = true)
{
var maxSort = -1;
if (profileItem.IndexId.IsNullOrEmpty())
{
profileItem.IndexId = Utils.GetGuid(false);
maxSort = ProfileExManager.Instance.GetMaxSort();
}
var groupType = profileItem.ConfigType == EConfigType.ProxyChain ? EConfigType.ProxyChain.ToString() : profileGroupItem.MultipleLoad.ToString();
profileItem.Address = $"{profileItem.CoreType}-{groupType}";
if (maxSort > 0)
{
ProfileExManager.Instance.SetSort(profileItem.IndexId, maxSort + 1);
}
if (toFile)
{
await SQLiteHelper.Instance.ReplaceAsync(profileItem);
if (profileGroupItem != null)
{
profileGroupItem.IndexId = profileItem.IndexId;
await ProfileGroupItemManager.Instance.SaveItemAsync(profileGroupItem);
}
else
{
ProfileGroupItemManager.Instance.GetOrCreateAndMarkDirty(profileItem.IndexId);
await ProfileGroupItemManager.Instance.SaveTo();
}
}
return 0;
}

/// <summary>
/// Compare two profile items to determine if they represent the same server
/// Used for deduplication and server matching
Expand All @@ -1128,6 +1097,8 @@ private static bool CompareProfileItem(ProfileItem? o, ProfileItem? n, bool rema
return false;
}

var extraItem = o.GetExtraItem();

return o.ConfigType == n.ConfigType
&& AreEqual(o.Address, n.Address)
&& o.Port == n.Port
Expand All @@ -1138,7 +1109,7 @@ private static bool CompareProfileItem(ProfileItem? o, ProfileItem? n, bool rema
&& AreEqual(o.RequestHost, n.RequestHost)
&& AreEqual(o.Path, n.Path)
&& (o.ConfigType == EConfigType.Trojan || o.StreamSecurity == n.StreamSecurity)
&& AreEqual(o.Flow, n.Flow)
&& AreEqual(extraItem.Flow, extraItem.Flow)
&& AreEqual(o.Sni, n.Sni)
&& AreEqual(o.Alpn, n.Alpn)
&& AreEqual(o.Fingerprint, n.Fingerprint)
Expand Down Expand Up @@ -1199,7 +1170,7 @@ public static async Task<RetResult> AddGroupServer4Multiple(Config config, List<
var indexId = Utils.GetGuid(false);
var childProfileIndexId = Utils.List2String(selecteds.Select(p => p.IndexId).ToList());

var remark = subId.IsNullOrEmpty() ? string.Empty : $"{(await AppManager.Instance.GetSubItem(subId)).Remarks} ";
var remark = subId.IsNullOrEmpty() ? string.Empty : $"{(await AppManager.Instance.GetSubItem(subId))?.Remarks} ";
if (coreType == ECoreType.Xray)
{
remark += multipleLoad switch
Expand Down Expand Up @@ -1233,13 +1204,12 @@ public static async Task<RetResult> AddGroupServer4Multiple(Config config, List<
{
profile.Subid = subId;
}
var profileGroup = new ProfileGroupItem
var extraItem = new ProtocolExtraItem
{
ChildItems = childProfileIndexId,
MultipleLoad = multipleLoad,
IndexId = indexId,
ChildItems = childProfileIndexId, MultipleLoad = multipleLoad,
};
var ret = await AddGroupServerCommon(config, profile, profileGroup, true);
profile.SetExtraItem(extraItem);
var ret = await AddServerCommon(config, profile, true);
result.Success = ret == 0;
result.Data = indexId;
return result;
Expand All @@ -1261,7 +1231,7 @@ public static async Task<RetResult> AddGroupServer4Multiple(Config config, List<
var tun2SocksAddress = node.Address;
if (node.ConfigType.IsGroupType())
{
var lstAddresses = (await ProfileGroupItemManager.GetAllChildDomainAddresses(node.IndexId)).ToList();
var lstAddresses = (await GroupProfileManager.GetAllChildDomainAddresses(node)).ToList();
if (lstAddresses.Count > 0)
{
tun2SocksAddress = Utils.List2String(lstAddresses);
Expand Down
9 changes: 6 additions & 3 deletions v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ protected static string GetIpv6(string address)

protected static int ToUriQuery(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery)
{
if (item.Flow.IsNotEmpty())
var extraItem = item.GetExtraItem();
if (!extraItem.Flow.IsNullOrEmpty())
{
dicQuery.Add("flow", item.Flow);
dicQuery.Add("flow", extraItem.Flow);
}

if (item.StreamSecurity.IsNotEmpty())
Expand Down Expand Up @@ -208,7 +209,9 @@ private static int ToUriQueryAllowInsecure(ProfileItem item, ref Dictionary<stri

protected static int ResolveUriQuery(NameValueCollection query, ref ProfileItem item)
{
item.Flow = GetQueryValue(query, "flow");
var extraItem = item.GetExtraItem();
extraItem.Flow = GetQueryValue(query, "flow");
item.SetExtraItem(extraItem);
item.StreamSecurity = GetQueryValue(query, "security");
item.Sni = GetQueryValue(query, "sni");
item.Alpn = GetQueryDecoded(query, "alpn");
Expand Down
11 changes: 8 additions & 3 deletions v2rayN/ServiceLib/Handler/Fmt/Hysteria2Fmt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ public class Hysteria2Fmt : BaseFmt
var query = Utils.ParseQueryString(url.Query);
ResolveUriQuery(query, ref item);
item.Path = GetQueryDecoded(query, "obfs-password");
item.Ports = GetQueryDecoded(query, "mport");
if (item.CertSha.IsNullOrEmpty())
{
item.CertSha = GetQueryDecoded(query, "pinSHA256");
}
ProtocolExtraItem extraItem = new()
{
Ports = GetQueryDecoded(query, "mport")
};
item.SetExtraItem(extraItem);

return item;
}
Expand All @@ -55,9 +59,10 @@ public class Hysteria2Fmt : BaseFmt
dicQuery.Add("obfs", "salamander");
dicQuery.Add("obfs-password", Utils.UrlEncode(item.Path));
}
if (item.Ports.IsNotEmpty())
var extra = item.GetExtraItem();
if (extra?.Ports?.IsNotEmpty() ?? false)
{
dicQuery.Add("mport", Utils.UrlEncode(item.Ports.Replace(':', '-')));
dicQuery.Add("mport", Utils.UrlEncode(extra.Ports.Replace(':', '-')));
}
if (!item.CertSha.IsNullOrEmpty())
{
Expand Down
9 changes: 7 additions & 2 deletions v2rayN/ServiceLib/Handler/Fmt/VmessFmt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ public class VmessFmt : BaseFmt
{
return null;
}

var extraItem = item?.GetExtraItem();
var vmessQRCode = new VmessQRCode
{
v = item.ConfigVersion,
ps = item.Remarks.TrimEx(),
add = item.Address,
port = item.Port,
id = item.Id,
aid = item.AlterId,
aid = int.TryParse(extraItem?.AlterId, out var result) ? result : 0,
scy = item.Security,
net = item.Network,
type = item.HeaderType,
Expand Down Expand Up @@ -76,7 +78,10 @@ public class VmessFmt : BaseFmt
item.Address = Utils.ToString(vmessQRCode.add);
item.Port = vmessQRCode.port;
item.Id = Utils.ToString(vmessQRCode.id);
item.AlterId = vmessQRCode.aid;
item.SetExtraItem(new ProtocolExtraItem
{
AlterId = vmessQRCode.aid.ToString(),
});
item.Security = Utils.ToString(vmessQRCode.scy);

item.Security = vmessQRCode.scy.IsNotEmpty() ? vmessQRCode.scy : Global.DefaultSecurity;
Expand Down
27 changes: 7 additions & 20 deletions v2rayN/ServiceLib/Manager/ActionPrecheckManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ private async Task<List<string>> ValidateNormalNode(ProfileItem item, ECoreType?
}
}

var extraItem = item.GetExtraItem();

switch (item.ConfigType)
{
case EConfigType.VMess:
Expand All @@ -144,7 +146,7 @@ private async Task<List<string>> ValidateNormalNode(ProfileItem item, ECoreType?
errors.Add(string.Format(ResUI.InvalidProperty, "Id"));
}

if (!Global.Flows.Contains(item.Flow))
if (!Global.Flows.Contains(extraItem.Flow ?? string.Empty))
{
errors.Add(string.Format(ResUI.InvalidProperty, "Flow"));
}
Expand Down Expand Up @@ -202,37 +204,22 @@ private async Task<List<string>> ValidateGroupNode(ProfileItem item, ECoreType?
{
var errors = new List<string>();

ProfileGroupItemManager.Instance.TryGet(item.IndexId, out var group);
if (group is null || group.NotHasChild())
{
errors.Add(string.Format(ResUI.GroupEmpty, item.Remarks));
return errors;
}

var hasCycle = ProfileGroupItemManager.HasCycle(item.IndexId);
var hasCycle = await GroupProfileManager.HasCycle(item.IndexId, item.GetExtraItem());
if (hasCycle)
{
errors.Add(string.Format(ResUI.GroupSelfReference, item.Remarks));
return errors;
}

var childIds = new List<string>();
var subItems = await ProfileGroupItemManager.GetSubChildProfileItems(group);
childIds.AddRangeSafe(subItems.Select(p => p.IndexId));
childIds.AddRangeSafe(Utils.String2List(group.ChildItems));
var (childItems, _) = await GroupProfileManager.GetChildProfileItems(item);

foreach (var child in childIds)
foreach (var childItem in childItems)
{
var childErrors = new List<string>();
if (child.IsNullOrEmpty())
{
continue;
}

var childItem = await AppManager.Instance.GetProfileItem(child);
if (childItem is null)
{
childErrors.Add(string.Format(ResUI.NodeTagNotExist, child));
childErrors.Add(string.Format(ResUI.NodeTagNotExist, ""));
continue;
}

Expand Down
45 changes: 36 additions & 9 deletions v2rayN/ServiceLib/Manager/AppManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ public bool InitComponents()
_ = StatePort;
_ = StatePort2;

_ = MigrateProfileExtra();

return true;
}

Expand Down Expand Up @@ -225,15 +227,6 @@ from ProfileItem a
return await SQLiteHelper.Instance.TableAsync<ProfileItem>().FirstOrDefaultAsync(it => it.Remarks == remarks);
}

public async Task<ProfileGroupItem?> GetProfileGroupItem(string indexId)
{
if (indexId.IsNullOrEmpty())
{
return null;
}
return await SQLiteHelper.Instance.TableAsync<ProfileGroupItem>().FirstOrDefaultAsync(it => it.IndexId == indexId);
}

public async Task<List<RoutingItem>?> RoutingItems()
{
return await SQLiteHelper.Instance.TableAsync<RoutingItem>().OrderBy(t => t.Sort).ToListAsync();
Expand Down Expand Up @@ -264,6 +257,40 @@ from ProfileItem a
return await SQLiteHelper.Instance.TableAsync<FullConfigTemplateItem>().FirstOrDefaultAsync(it => it.CoreType == eCoreType);
}

public async Task MigrateProfileExtra()
{
var list = await SQLiteHelper.Instance.TableAsync<ProfileItem>().ToListAsync();
foreach (var item in list)
{
if (!item.JsonData.IsNullOrEmpty())
{
return;
}
ProtocolExtraItem extra = new()
{
AlterId = item.AlterId.ToString(),
Flow = item.Flow.IsNotEmpty() ? item.Flow : null,
Ports = item.Ports.IsNotEmpty() ? item.Ports : null,
};
if (item.ConfigType is EConfigType.PolicyGroup or EConfigType.ProxyChain)
{
extra.GroupType = nameof(item.ConfigType);
ProfileGroupItemManager.Instance.TryGet(item.IndexId, out var groupItem);
if (groupItem != null && !groupItem.NotHasChild())
{
extra.ChildItems = groupItem.ChildItems;
extra.SubChildItems = groupItem.SubChildItems;
extra.Filter = groupItem.Filter;
extra.MultipleLoad = groupItem.MultipleLoad;
}
}
item.SetExtraItem(extra);
await SQLiteHelper.Instance.UpdateAsync(item);
}

await ProfileGroupItemManager.Instance.ClearAll();
}

#endregion SqliteHelper

#region Core Type
Expand Down
Loading