mirror of
https://github.com/2dust/v2rayN.git
synced 2026-02-28 21:23:04 +00:00
Add region group
This commit is contained in:
parent
94f15b9150
commit
d4df6b91f0
15 changed files with 136 additions and 3 deletions
|
|
@ -90,8 +90,6 @@ public class Global
|
|||
|
||||
public const int Hysteria2DefaultHopInt = 10;
|
||||
|
||||
public const string PolicyGroupDefaultAllFilter = "^(?!.*(剩余|过期|到期|重置)).*$";
|
||||
|
||||
public static readonly List<string> IEProxyProtocols =
|
||||
[
|
||||
"{ip}:{http_port}",
|
||||
|
|
|
|||
|
|
@ -1163,6 +1163,16 @@ public static class ConfigHandler
|
|||
return 0;
|
||||
}
|
||||
|
||||
private const string PolicyGroupDefaultAllFilter = "^(?!.*(?:剩余|过期|到期|重置)).*$";
|
||||
|
||||
/// <summary>
|
||||
/// Combines a region pattern with PolicyGroupDefaultAllFilter so results must
|
||||
/// match the region keyword AND not contain expiry/traffic noise words.
|
||||
/// Result pattern: ^(?!.*(?:剩余|过期|到期|重置)).*(?:regionPattern).*$
|
||||
/// </summary>
|
||||
private static string CombineWithDefaultAllFilter(string regionPattern)
|
||||
=> $"^(?!.*(?:剩余|过期|到期|重置)).*(?:{regionPattern}).*$";
|
||||
|
||||
/// <summary>
|
||||
/// Create a group server that combines multiple servers for load balancing
|
||||
/// Generates a PolicyGroup profile with references to the sub-items
|
||||
|
|
@ -1195,7 +1205,7 @@ public static class ConfigHandler
|
|||
MultipleLoad = EMultipleLoad.LeastPing,
|
||||
GroupType = profile.ConfigType.ToString(),
|
||||
SubChildItems = subId,
|
||||
Filter = Global.PolicyGroupDefaultAllFilter,
|
||||
Filter = PolicyGroupDefaultAllFilter,
|
||||
};
|
||||
profile.SetProtocolExtra(extraItem);
|
||||
var ret = await AddServerCommon(config, profile, true);
|
||||
|
|
@ -1204,6 +1214,76 @@ public static class ConfigHandler
|
|||
return result;
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, string> PolicyGroupRegionFilters = new()
|
||||
{
|
||||
{ "JP", "日本|[Jj][Pp]|🇯🇵" },
|
||||
{ "US", "美国|[Uu][Ss]|🇺🇸" },
|
||||
{ "HK", "香港|[Hh][Kk]|🇭🇰" },
|
||||
{ "TW", "台湾|[Tt][Ww]|🇹🇼" },
|
||||
{ "KR", "韩国|[Kk][Rr]|🇰🇷" },
|
||||
{ "SG", "新加坡|[Ss][Gg]|🇸🇬" },
|
||||
{ "DE", "德国|[Dd][Ee]|🇩🇪" },
|
||||
{ "FR", "法国|[Ff][Rr]|🇫🇷" },
|
||||
{ "GB", "英国|[Gg][Bb]|🇬🇧" },
|
||||
{ "CA", "加拿大|[Cc][Aa]|🇨🇦" },
|
||||
{ "AU", "澳大利亚|[Aa][Uu]|🇦🇺" },
|
||||
{ "RU", "俄罗斯|[Rr][Uu]|🇷🇺" },
|
||||
{ "BR", "巴西|[Bb][Rr]|🇧🇷" },
|
||||
{ "IN", "印度|[Ii][Nn]|🇮🇳" },
|
||||
{ "VN", "越南|[Vv][Nn]|🇻🇳" },
|
||||
{ "ID", "印度尼西亚|[Ii][Dd]|🇮🇩" },
|
||||
{ "MX", "墨西哥|[Mm][Xx]|🇲🇽" }
|
||||
};
|
||||
|
||||
public static async Task<RetResult> AddGroupRegionServer(Config config, SubItem? subItem)
|
||||
{
|
||||
var result = new RetResult();
|
||||
List<string> indexIdList = [];
|
||||
|
||||
foreach (var regionFilter in PolicyGroupRegionFilters)
|
||||
{
|
||||
var indexId = Utils.GetGuid(false);
|
||||
var subId = subItem?.Id;
|
||||
|
||||
var remark = subItem is null ? ResUI.TbConfigTypePolicyGroup : $"{subItem.Remarks} - {ResUI.TbConfigTypePolicyGroup} - {regionFilter.Key}";
|
||||
var profile = new ProfileItem
|
||||
{
|
||||
IndexId = indexId,
|
||||
CoreType = ECoreType.Xray,
|
||||
ConfigType = EConfigType.PolicyGroup,
|
||||
Remarks = remark,
|
||||
IsSub = false
|
||||
};
|
||||
if (!subId.IsNullOrEmpty())
|
||||
{
|
||||
profile.Subid = subId;
|
||||
}
|
||||
var extraItem = new ProtocolExtraItem
|
||||
{
|
||||
MultipleLoad = EMultipleLoad.LeastPing,
|
||||
GroupType = profile.ConfigType.ToString(),
|
||||
SubChildItems = subId,
|
||||
Filter = CombineWithDefaultAllFilter(regionFilter.Value),
|
||||
};
|
||||
profile.SetProtocolExtra(extraItem);
|
||||
|
||||
var childProfile = await GroupProfileManager.GetChildProfileItemsByProtocolExtra(extraItem);
|
||||
if (childProfile.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var ret = await AddServerCommon(config, profile, true);
|
||||
if (ret == 0)
|
||||
{
|
||||
indexIdList.Add(indexId);
|
||||
}
|
||||
}
|
||||
result.Success = indexIdList.Count > 0;
|
||||
result.Data = indexIdList;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a SOCKS server profile for pre-SOCKS functionality
|
||||
/// Used when TUN mode is enabled or when a custom config has a pre-SOCKS port
|
||||
|
|
|
|||
9
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
9
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
|
|
@ -1023,6 +1023,15 @@ namespace ServiceLib.Resx {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Group by Region 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string menuGenRegionGroup {
|
||||
get {
|
||||
return ResourceManager.GetString("menuGenRegionGroup", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Global Hotkey Setting 的本地化字符串。
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1668,4 +1668,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
|||
<data name="menuAllServers" xml:space="preserve">
|
||||
<value>All configurations</value>
|
||||
</data>
|
||||
<data name="menuGenRegionGroup" xml:space="preserve">
|
||||
<value>Group by Region</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1665,4 +1665,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
|||
<data name="menuAllServers" xml:space="preserve">
|
||||
<value>All configurations</value>
|
||||
</data>
|
||||
<data name="menuGenRegionGroup" xml:space="preserve">
|
||||
<value>Group by Region</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
|
|||
|
|
@ -1668,4 +1668,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
|||
<data name="menuAllServers" xml:space="preserve">
|
||||
<value>All configurations</value>
|
||||
</data>
|
||||
<data name="menuGenRegionGroup" xml:space="preserve">
|
||||
<value>Group by Region</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1668,4 +1668,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
|||
<data name="menuAllServers" xml:space="preserve">
|
||||
<value>All configurations</value>
|
||||
</data>
|
||||
<data name="menuGenRegionGroup" xml:space="preserve">
|
||||
<value>Group by Region</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1668,4 +1668,7 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
|||
<data name="menuAllServers" xml:space="preserve">
|
||||
<value>All configurations</value>
|
||||
</data>
|
||||
<data name="menuGenRegionGroup" xml:space="preserve">
|
||||
<value>Group by Region</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1665,4 +1665,7 @@
|
|||
<data name="menuAllServers" xml:space="preserve">
|
||||
<value>全部配置项</value>
|
||||
</data>
|
||||
<data name="menuGenRegionGroup" xml:space="preserve">
|
||||
<value>按地区分组</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -1665,4 +1665,7 @@
|
|||
<data name="menuAllServers" xml:space="preserve">
|
||||
<value>All configurations</value>
|
||||
</data>
|
||||
<data name="menuGenRegionGroup" xml:space="preserve">
|
||||
<value>Group by Region</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -45,6 +45,7 @@ public class ProfilesViewModel : MyReactiveObject
|
|||
public ReactiveCommand<Unit, Unit> SetDefaultServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> ShareServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> GenGroupAllServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> GenGroupRegionServerCmd { get; }
|
||||
|
||||
//servers move
|
||||
public ReactiveCommand<Unit, Unit> MoveTopCmd { get; }
|
||||
|
|
@ -133,6 +134,10 @@ public class ProfilesViewModel : MyReactiveObject
|
|||
{
|
||||
await GenGroupAllServer();
|
||||
}, canEditRemove);
|
||||
GenGroupRegionServerCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await GenGroupRegionServer();
|
||||
}, canEditRemove);
|
||||
|
||||
//servers move
|
||||
MoveTopCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
|
|
@ -623,6 +628,19 @@ public class ProfilesViewModel : MyReactiveObject
|
|||
await RefreshServers();
|
||||
}
|
||||
|
||||
private async Task GenGroupRegionServer()
|
||||
{
|
||||
var ret = await ConfigHandler.AddGroupRegionServer(_config, SelectedSub);
|
||||
if (ret.Success != true)
|
||||
{
|
||||
NoticeManager.Instance.Enqueue(ResUI.OperationFailed);
|
||||
return;
|
||||
}
|
||||
var indexIdList = ret.Data as List<string>;
|
||||
_pendingSelectIndexId = indexIdList?.FirstOrDefault();
|
||||
await RefreshServers();
|
||||
}
|
||||
|
||||
public async Task SortServer(string colName)
|
||||
{
|
||||
if (colName.IsNullOrEmpty())
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@
|
|||
<Separator />
|
||||
<MenuItem Header="{x:Static resx:ResUI.menuGenGroupServer}">
|
||||
<MenuItem x:Name="menuGenGroupAllServer" Header="{x:Static resx:ResUI.menuAllServers}" />
|
||||
<MenuItem x:Name="menuGenGroupRegionServer" Header="{x:Static resx:ResUI.menuGenRegionGroup}" />
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</DataGrid.ContextMenu>
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ public partial class ProfilesView : ReactiveUserControl<ProfilesViewModel>
|
|||
this.BindCommand(ViewModel, vm => vm.SetDefaultServerCmd, v => v.menuSetDefaultServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ShareServerCmd, v => v.menuShareServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.GenGroupAllServerCmd, v => v.menuGenGroupAllServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.GenGroupRegionServerCmd, v => v.menuGenGroupRegionServer).DisposeWith(disposables);
|
||||
|
||||
//servers move
|
||||
//this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.cmbMoveToGroup.ItemsSource).DisposeWith(disposables);
|
||||
|
|
|
|||
|
|
@ -245,6 +245,10 @@
|
|||
x:Name="menuGenGroupAllServer"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuAllServers}" />
|
||||
<MenuItem
|
||||
x:Name="menuGenGroupRegionServer"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuGenRegionGroup}" />
|
||||
</MenuItem>
|
||||
</ContextMenu>
|
||||
</DataGrid.ContextMenu>
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public partial class ProfilesView
|
|||
this.BindCommand(ViewModel, vm => vm.SetDefaultServerCmd, v => v.menuSetDefaultServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ShareServerCmd, v => v.menuShareServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.GenGroupAllServerCmd, v => v.menuGenGroupAllServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.GenGroupRegionServerCmd, v => v.menuGenGroupRegionServer).DisposeWith(disposables);
|
||||
|
||||
//servers move
|
||||
this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.cmbMoveToGroup.ItemsSource).DisposeWith(disposables);
|
||||
|
|
|
|||
Loading…
Reference in a new issue