Skip to content

Commit

Permalink
External routing rules templates + regional presets support (#5840)
Browse files Browse the repository at this point in the history
* External routing rules templates + auto download geo file if repo changed

* Regional presets support
  • Loading branch information
runetfreedom authored Oct 16, 2024
1 parent a5122b6 commit 2edbbc5
Show file tree
Hide file tree
Showing 18 changed files with 272 additions and 16 deletions.
8 changes: 8 additions & 0 deletions v2rayN/ServiceLib/Enums/EPresetType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace ServiceLib.Enums
{
public enum EPresetType
{
Default = 0,
Russia = 1,
}
}
5 changes: 5 additions & 0 deletions v2rayN/ServiceLib/Global.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ public class Global
@"https://raw.githubusercontent.com/runetfreedom/russia-v2ray-rules-dat/refs/heads/release/sing-box/rule-set-{0}/{1}.srs",
};

public static readonly List<string> RoutingRulesSources = new() {
"", //Default
@"https://raw.githubusercontent.com/runetfreedom/russia-v2ray-custom-routing-list/refs/heads/main/template.json",
};

public static readonly Dictionary<string, string> UserAgentTexts = new()
{
{"chrome","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" },
Expand Down
114 changes: 102 additions & 12 deletions v2rayN/ServiceLib/Handler/ConfigHandler.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Data;
using ServiceLib.Common;
using System.Data;
using System.Text.Json.Nodes;
using System.Text.RegularExpressions;

namespace ServiceLib.Handler
Expand Down Expand Up @@ -1616,6 +1618,79 @@ public static RoutingItem GetDefaultRouting(Config config)
return item;
}

public static int InitRouting(Config config, bool blImportAdvancedRules = false)
{
if (!String.IsNullOrEmpty(config.constItem.routeRulesTemplateSourceUrl))
{
InitExternalRouting(config, blImportAdvancedRules);
}
else
{
InitBuiltinRouting(config, blImportAdvancedRules);
}

if (GetLockedRoutingItem(config) == null)
{
var item1 = new RoutingItem()
{
remarks = "locked",
url = string.Empty,
locked = true,
};
AddBatchRoutingRules(ref item1, Utils.GetEmbedText(Global.CustomRoutingFileName + "locked"));
}

return 0;
}

public static int InitExternalRouting(Config config, bool blImportAdvancedRules = false)
{
DownloadService downloadHandle = new DownloadService();
var templateContent = Task.Run(() => downloadHandle.TryDownloadString(config.constItem.routeRulesTemplateSourceUrl, false, "")).Result;
if (String.IsNullOrEmpty(templateContent))
return InitBuiltinRouting(config, blImportAdvancedRules); // fallback

var template = JsonUtils.Deserialize<RoutingTemplate>(templateContent);
if (template == null)
return InitBuiltinRouting(config, blImportAdvancedRules); // fallback

var items = AppHandler.Instance.RoutingItems();
var maxSort = items.Count;

if (blImportAdvancedRules || items.Where(t => t.remarks.StartsWith(template.version)).ToList().Count <= 0)
{
for (var i = 0; i < template.routingItems.Length; i++)
{
var item = template.routingItems[i];

if (String.IsNullOrEmpty(item.url) && String.IsNullOrEmpty(item.ruleSet))
continue;

var ruleSetsString = !String.IsNullOrEmpty(item.ruleSet)
? item.ruleSet
: Task.Run(() => downloadHandle.TryDownloadString(item.url, false, "")).Result;

if (String.IsNullOrEmpty(ruleSetsString))
continue;

item.remarks = $"{template.version}-{item.remarks}";
item.enabled = true;
item.sort = ++maxSort;
item.url = string.Empty;

AddBatchRoutingRules(ref item, ruleSetsString);

//first rule as default at first startup
if (!blImportAdvancedRules && i == 0)
{
SetDefaultRouting(config, item);
}
}
}

return 0;
}

public static int InitBuiltinRouting(Config config, bool blImportAdvancedRules = false)
{
var ver = "V3-";
Expand Down Expand Up @@ -1655,17 +1730,6 @@ public static int InitBuiltinRouting(Config config, bool blImportAdvancedRules =
SetDefaultRouting(config, item2);
}
}

if (GetLockedRoutingItem(config) == null)
{
var item1 = new RoutingItem()
{
remarks = "locked",
url = string.Empty,
locked = true,
};
AddBatchRoutingRules(ref item1, Utils.GetEmbedText(Global.CustomRoutingFileName + "locked"));
}
return 0;
}

Expand Down Expand Up @@ -1724,5 +1788,31 @@ public static int SaveDNSItems(Config config, DNSItem item)
}

#endregion DNS

#region Presets

public static bool ApplyPreset(Config config, EPresetType type)
{
switch (type)
{
case EPresetType.Default:
config.constItem.geoSourceUrl = "";
config.constItem.srsSourceUrl = "";
config.constItem.routeRulesTemplateSourceUrl = "";

return true;

case EPresetType.Russia:
config.constItem.geoSourceUrl = Global.GeoFilesSources[1];
config.constItem.srsSourceUrl = Global.SingboxRulesetSources[1];
config.constItem.routeRulesTemplateSourceUrl = Global.RoutingRulesSources[1];

return true;
}

return false;
}

#endregion
}
}
1 change: 1 addition & 0 deletions v2rayN/ServiceLib/Models/ConfigItems.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public class ConstItem
public string subConvertUrl { get; set; } = string.Empty;
public string? geoSourceUrl { get; set; }
public string? srsSourceUrl { get; set; }
public string? routeRulesTemplateSourceUrl { get; set; }
}

[Serializable]
Expand Down
9 changes: 9 additions & 0 deletions v2rayN/ServiceLib/Models/RoutingTemplate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace ServiceLib.Models
{
[Serializable]
public class RoutingTemplate
{
public string version { get; set; }
public RoutingItem[] routingItems { get; set; }
}
}
38 changes: 38 additions & 0 deletions v2rayN/ServiceLib/Resx/ResUI.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions v2rayN/ServiceLib/Resx/ResUI.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1336,4 +1336,16 @@
<data name="UpgradeAppNotExistTip" xml:space="preserve">
<value>UpgradeApp does not exist</value>
</data>
<data name="TbSettingsRoutingRulesSource" xml:space="preserve">
<value>Routing rules source (optional)</value>
</data>
<data name="menuPresets" xml:space="preserve">
<value>Regional presets</value>
</data>
<data name="menuPresetsDefault" xml:space="preserve">
<value>Default</value>
</data>
<data name="menuPresetsRussia" xml:space="preserve">
<value>Russia</value>
</data>
</root>
35 changes: 33 additions & 2 deletions v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ public class MainWindowViewModel : MyReactiveObject
public ReactiveCommand<Unit, Unit> ClearServerStatisticsCmd { get; }
public ReactiveCommand<Unit, Unit> OpenTheFileLocationCmd { get; }

//Presets
public ReactiveCommand<Unit, Unit> PresetDefaultCmd { get; }
public ReactiveCommand<Unit, Unit> PresetRussiaCmd { get; }

public ReactiveCommand<Unit, Unit> ReloadCmd { get; }

[Reactive]
Expand Down Expand Up @@ -181,14 +185,24 @@ public MainWindowViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
await Reload();
});

PresetDefaultCmd = ReactiveCommand.CreateFromTask(async () =>
{
await ApplyPreset(EPresetType.Default);
});

PresetRussiaCmd = ReactiveCommand.CreateFromTask(async () =>
{
await ApplyPreset(EPresetType.Russia);
});

#endregion WhenAnyValue && ReactiveCommand

AutoHideStartup();
}

private void Init()
{
ConfigHandler.InitBuiltinRouting(_config);
ConfigHandler.InitRouting(_config);
ConfigHandler.InitBuiltinDNS(_config);
CoreHandler.Instance.Init(_config, UpdateHandler);
TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler);
Expand Down Expand Up @@ -431,7 +445,7 @@ private async Task RoutingSettingAsync()
var ret = await _updateView?.Invoke(EViewAction.RoutingSettingWindow, null);
if (ret == true)
{
ConfigHandler.InitBuiltinRouting(_config);
ConfigHandler.InitRouting(_config);
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();
Reload();
}
Expand Down Expand Up @@ -543,5 +557,22 @@ private void AutoHideStartup()
}

#endregion core job

#region Presets

public async Task ApplyPreset(EPresetType type)
{
ConfigHandler.ApplyPreset(_config, type);

await new UpdateService().UpdateGeoFileAll(_config, UpdateHandler);

ConfigHandler.InitRouting(_config);
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();

ConfigHandler.SaveConfig(_config, false);
Reload();
}

#endregion
}
}
3 changes: 3 additions & 0 deletions v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public class OptionSettingViewModel : MyReactiveObject
[Reactive] public int MainGirdOrientation { get; set; }
[Reactive] public string GeoFileSourceUrl { get; set; }
[Reactive] public string SrsFileSourceUrl { get; set; }
[Reactive] public string RoutingRulesSourceUrl { get; set; }

#endregion UI

Expand Down Expand Up @@ -168,6 +169,7 @@ public OptionSettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView
MainGirdOrientation = (int)_config.uiItem.mainGirdOrientation;
GeoFileSourceUrl = _config.constItem.geoSourceUrl;
SrsFileSourceUrl = _config.constItem.srsSourceUrl;
RoutingRulesSourceUrl = _config.constItem.routeRulesTemplateSourceUrl;

#endregion UI

Expand Down Expand Up @@ -322,6 +324,7 @@ private async Task SaveSettingAsync()
_config.uiItem.mainGirdOrientation = (EGirdOrientation)MainGirdOrientation;
_config.constItem.geoSourceUrl = GeoFileSourceUrl;
_config.constItem.srsSourceUrl = SrsFileSourceUrl;
_config.constItem.routeRulesTemplateSourceUrl = RoutingRulesSourceUrl;

//systemProxy
_config.systemProxyItem.systemProxyExceptions = systemProxyExceptions;
Expand Down
4 changes: 2 additions & 2 deletions v2rayN/ServiceLib/ViewModels/RoutingSettingViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public RoutingSettingViewModel(Func<EViewAction, object?, Task<bool>>? updateVie
_updateView = updateView;
SelectedSource = new();

ConfigHandler.InitBuiltinRouting(_config);
ConfigHandler.InitRouting(_config);

enableRoutingAdvanced = _config.routingBasicItem.enableRoutingAdvanced;
domainStrategy = _config.routingBasicItem.domainStrategy;
Expand Down Expand Up @@ -286,7 +286,7 @@ public async Task RoutingAdvancedSetDefault()

private async Task RoutingAdvancedImportRules()
{
if (ConfigHandler.InitBuiltinRouting(_config, true) == 0)
if (ConfigHandler.InitRouting(_config, true) == 0)
{
RefreshRoutingItems();
IsModified = true;
Expand Down
4 changes: 4 additions & 0 deletions v2rayN/v2rayN.Desktop/Views/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@
<MenuItem x:Name="menuRoutingSetting" Header="{x:Static resx:ResUI.menuRoutingSetting}" />
<MenuItem x:Name="menuDNSSetting" Header="{x:Static resx:ResUI.menuDNSSetting}" />
<MenuItem x:Name="menuGlobalHotkeySetting" Header="{x:Static resx:ResUI.menuGlobalHotkeySetting}" />
<MenuItem Header="{x:Static resx:ResUI.menuPresets}">
<MenuItem x:Name="menuPresetsDefault" Header="{x:Static resx:ResUI.menuPresetsDefault}" />
<MenuItem x:Name="menuPresetsRussia" Header="{x:Static resx:ResUI.menuPresetsRussia}" />
</MenuItem>
<Separator />
<MenuItem x:Name="menuRebootAsAdmin" Header="{x:Static resx:ResUI.menuRebootAsAdmin}" />
<MenuItem x:Name="menuSettingsSetUWP" Header="{x:Static resx:ResUI.TbSettingsSetUWP}" />
Expand Down
2 changes: 2 additions & 0 deletions v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ public MainWindow()
this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.PresetDefaultCmd, v => v.menuPresetsDefault).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.PresetRussiaCmd, v => v.menuPresetsRussia).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
Expand Down
Loading

0 comments on commit 2edbbc5

Please sign in to comment.