mirror of https://github.com/2dust/v2rayN
Add custom sing-box rule-set support
parent
8d21f9b900
commit
124cbfadb4
|
@ -57,11 +57,14 @@ namespace v2rayN
|
||||||
/// 取得存储资源
|
/// 取得存储资源
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string? LoadResource(string res)
|
public static string? LoadResource(string? res)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!File.Exists(res)) return null;
|
if (!File.Exists(res))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return File.ReadAllText(res);
|
return File.ReadAllText(res);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
@ -895,18 +895,45 @@ namespace v2rayN.Handler
|
||||||
ruleSets.AddRange(dnsRule.rule_set);
|
ruleSets.AddRange(dnsRule.rule_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//load custom ruleset file
|
||||||
|
List<Ruleset4Sbox> customRulesets = [];
|
||||||
|
if (_config.routingBasicItem.enableRoutingAdvanced)
|
||||||
|
{
|
||||||
|
var routing = ConfigHandler.GetDefaultRouting(_config);
|
||||||
|
if (!Utils.IsNullOrEmpty(routing.customRulesetPath4Singbox))
|
||||||
|
{
|
||||||
|
var result = Utils.LoadResource(routing.customRulesetPath4Singbox);
|
||||||
|
if (!Utils.IsNullOrEmpty(result))
|
||||||
|
{
|
||||||
|
customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])
|
||||||
|
.Where(t => t.tag != null)
|
||||||
|
.Where(t => t.type != null)
|
||||||
|
.Where(t => t.format != null)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Add ruleset srs
|
//Add ruleset srs
|
||||||
singboxConfig.route.rule_set = [];
|
singboxConfig.route.rule_set = [];
|
||||||
foreach (var item in new HashSet<string>(ruleSets))
|
foreach (var item in new HashSet<string>(ruleSets))
|
||||||
{
|
{
|
||||||
singboxConfig.route.rule_set.Add(new()
|
var customRuleset = customRulesets.FirstOrDefault(t => t.tag != null && t.tag.Equals(item));
|
||||||
|
if (customRuleset != null)
|
||||||
{
|
{
|
||||||
type = "remote",
|
singboxConfig.route.rule_set.Add(customRuleset);
|
||||||
format = "binary",
|
}
|
||||||
tag = item,
|
else
|
||||||
url = string.Format(Global.SingboxRulesetUrl, item.StartsWith(geosite) ? geosite : geoip, item),
|
{
|
||||||
download_detour = Global.ProxyTag
|
singboxConfig.route.rule_set.Add(new()
|
||||||
});
|
{
|
||||||
|
type = "remote",
|
||||||
|
format = "binary",
|
||||||
|
tag = item,
|
||||||
|
url = string.Format(Global.SingboxRulesetUrl, item.StartsWith(geosite) ? geosite : geoip, item),
|
||||||
|
download_detour = Global.ProxyTag
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -182,16 +182,11 @@ namespace v2rayN.Models
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class RoutingBasicItem
|
public class RoutingBasicItem
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 域名解析策略
|
|
||||||
/// </summary>
|
|
||||||
public string domainStrategy { get; set; }
|
public string domainStrategy { get; set; }
|
||||||
|
|
||||||
public string domainStrategy4Singbox { get; set; }
|
public string domainStrategy4Singbox { get; set; }
|
||||||
|
|
||||||
public string domainMatcher { get; set; }
|
public string domainMatcher { get; set; }
|
||||||
public string routingIndexId { get; set; }
|
public string routingIndexId { get; set; }
|
||||||
public bool enableRoutingAdvanced { get; set; }
|
public bool enableRoutingAdvanced { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace v2rayN.Models
|
||||||
public bool enabled { get; set; } = true;
|
public bool enabled { get; set; } = true;
|
||||||
public bool locked { get; set; }
|
public bool locked { get; set; }
|
||||||
public string customIcon { get; set; }
|
public string customIcon { get; set; }
|
||||||
|
public string customRulesetPath4Singbox { get; set; }
|
||||||
public string domainStrategy { get; set; }
|
public string domainStrategy { get; set; }
|
||||||
public string domainStrategy4Singbox { get; set; }
|
public string domainStrategy4Singbox { get; set; }
|
||||||
public int sort { get; set; }
|
public int sort { get; set; }
|
||||||
|
|
|
@ -238,7 +238,9 @@
|
||||||
public string? tag { get; set; }
|
public string? tag { get; set; }
|
||||||
public string? type { get; set; }
|
public string? type { get; set; }
|
||||||
public string? format { get; set; }
|
public string? format { get; set; }
|
||||||
|
public string? path { get; set; }
|
||||||
public string? url { get; set; }
|
public string? url { get; set; }
|
||||||
public string? download_detour { get; set; }
|
public string? download_detour { get; set; }
|
||||||
|
public string? update_interval { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1210,4 +1210,7 @@
|
||||||
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
||||||
<value>Enable cache file for sing-box (ruleset files)</value>
|
<value>Enable cache file for sing-box (ruleset files)</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
|
||||||
|
<value>Custom the rule-set of sing-box</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -1207,4 +1207,7 @@
|
||||||
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
||||||
<value>启用sing-box(规则集文件)的缓存文件</value>
|
<value>启用sing-box(规则集文件)的缓存文件</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
|
||||||
|
<value>自定义sing-box rule-set</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -1180,4 +1180,7 @@
|
||||||
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
||||||
<value>啟用sing-box(規則集文件)的緩存文件</value>
|
<value>啟用sing-box(規則集文件)的緩存文件</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
|
||||||
|
<value>自訂sing-box rule-set</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -192,6 +192,7 @@ namespace v2rayN.ViewModels
|
||||||
remarks = item.remarks,
|
remarks = item.remarks,
|
||||||
url = item.url,
|
url = item.url,
|
||||||
customIcon = item.customIcon,
|
customIcon = item.customIcon,
|
||||||
|
customRulesetPath4Singbox = item.customRulesetPath4Singbox,
|
||||||
sort = item.sort,
|
sort = item.sort,
|
||||||
};
|
};
|
||||||
_routingItems.Add(it);
|
_routingItems.Add(it);
|
||||||
|
|
|
@ -88,6 +88,7 @@
|
||||||
Style="{StaticResource ToolbarTextBlock}">
|
Style="{StaticResource ToolbarTextBlock}">
|
||||||
<Hyperlink Click="linkDnsObjectDoc_Click">
|
<Hyperlink Click="linkDnsObjectDoc_Click">
|
||||||
<TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" />
|
<TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" />
|
||||||
|
<materialDesign:PackIcon Kind="Link" />
|
||||||
</Hyperlink>
|
</Hyperlink>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<Button
|
<Button
|
||||||
|
@ -120,6 +121,7 @@
|
||||||
Style="{StaticResource ToolbarTextBlock}">
|
Style="{StaticResource ToolbarTextBlock}">
|
||||||
<Hyperlink Click="linkDnsSingboxObjectDoc_Click">
|
<Hyperlink Click="linkDnsSingboxObjectDoc_Click">
|
||||||
<TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" />
|
<TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" />
|
||||||
|
<materialDesign:PackIcon Kind="Link" />
|
||||||
</Hyperlink>
|
</Hyperlink>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<Button
|
<Button
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:conv="clr-namespace:v2rayN.Converters"
|
xmlns:conv="clr-namespace:v2rayN.Converters"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:reactiveui="http://reactiveui.net"
|
xmlns:reactiveui="http://reactiveui.net"
|
||||||
xmlns:resx="clr-namespace:v2rayN.Resx"
|
xmlns:resx="clr-namespace:v2rayN.Resx"
|
||||||
|
@ -83,6 +84,7 @@
|
||||||
Style="{StaticResource ToolbarTextBlock}">
|
Style="{StaticResource ToolbarTextBlock}">
|
||||||
<Hyperlink Click="linkRuleobjectDoc_Click">
|
<Hyperlink Click="linkRuleobjectDoc_Click">
|
||||||
<TextBlock Text="{x:Static resx:ResUI.TbRuleobjectDoc}" />
|
<TextBlock Text="{x:Static resx:ResUI.TbRuleobjectDoc}" />
|
||||||
|
<materialDesign:PackIcon Kind="Link" />
|
||||||
</Hyperlink>
|
</Hyperlink>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
|
||||||
|
|
|
@ -114,17 +114,36 @@
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
Text="{x:Static resx:ResUI.LvRemarks}" />
|
Text="{x:Static resx:ResUI.LvRemarks}" />
|
||||||
<TextBox
|
<StackPanel
|
||||||
x:Name="txtRemarks"
|
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Width="400"
|
Orientation="Horizontal">
|
||||||
Margin="4"
|
|
||||||
HorizontalAlignment="Left"
|
<TextBox
|
||||||
VerticalAlignment="Top"
|
x:Name="txtRemarks"
|
||||||
AcceptsReturn="True"
|
Grid.Row="0"
|
||||||
Style="{StaticResource DefTextBox}"
|
Grid.Column="1"
|
||||||
TextWrapping="Wrap" />
|
Width="300"
|
||||||
|
Margin="4"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
AcceptsReturn="True"
|
||||||
|
Style="{StaticResource DefTextBox}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Margin="4"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
|
Text="{x:Static resx:ResUI.LvSort}" />
|
||||||
|
<TextBox
|
||||||
|
x:Name="txtSort"
|
||||||
|
Width="100"
|
||||||
|
Margin="4"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
AcceptsReturn="True"
|
||||||
|
Style="{StaticResource DefTextBox}" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
|
@ -190,11 +209,11 @@
|
||||||
Style="{StaticResource DefTextBox}"
|
Style="{StaticResource DefTextBox}"
|
||||||
TextWrapping="Wrap" />
|
TextWrapping="Wrap" />
|
||||||
<Button
|
<Button
|
||||||
x:Name="btnBrowse"
|
x:Name="btnBrowseCustomIcon"
|
||||||
Grid.Row="3"
|
Grid.Row="3"
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Margin="2,0,8,0"
|
Margin="2,0,8,0"
|
||||||
Click="btnBrowse_Click"
|
Click="btnBrowseCustomIcon_Click"
|
||||||
Content="{x:Static resx:ResUI.TbBrowse}"
|
Content="{x:Static resx:ResUI.TbBrowse}"
|
||||||
Style="{StaticResource DefButton}" />
|
Style="{StaticResource DefButton}" />
|
||||||
|
|
||||||
|
@ -203,17 +222,30 @@
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Margin="4"
|
Margin="4"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
Style="{StaticResource ToolbarTextBlock}">
|
||||||
Text="{x:Static resx:ResUI.LvSort}" />
|
<Hyperlink Click="linkCustomRulesetPath4Singbox">
|
||||||
|
<TextBlock Text="{x:Static resx:ResUI.LvCustomRulesetPath4Singbox}" />
|
||||||
|
<materialDesign:PackIcon Kind="Link" />
|
||||||
|
</Hyperlink>
|
||||||
|
</TextBlock>
|
||||||
<TextBox
|
<TextBox
|
||||||
x:Name="txtSort"
|
x:Name="txtCustomRulesetPath4Singbox"
|
||||||
Grid.Row="4"
|
Grid.Row="4"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Width="200"
|
Width="600"
|
||||||
Margin="4"
|
Margin="4"
|
||||||
HorizontalAlignment="Left"
|
VerticalAlignment="Top"
|
||||||
AcceptsReturn="True"
|
AcceptsReturn="True"
|
||||||
Style="{StaticResource DefTextBox}" />
|
Style="{StaticResource DefTextBox}"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
|
<Button
|
||||||
|
x:Name="btnBrowseCustomRulesetPath4Singbox"
|
||||||
|
Grid.Row="4"
|
||||||
|
Grid.Column="2"
|
||||||
|
Margin="2,0,8,0"
|
||||||
|
Click="btnBrowseCustomRulesetPath4Singbox_Click"
|
||||||
|
Content="{x:Static resx:ResUI.TbBrowse}"
|
||||||
|
Style="{StaticResource DefButton}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<TabControl x:Name="tabAdvanced">
|
<TabControl x:Name="tabAdvanced">
|
||||||
|
|
|
@ -51,6 +51,7 @@ namespace v2rayN.Views
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.SelectedRouting.url, v => v.txtUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedRouting.url, v => v.txtUrl.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedRouting.customIcon, v => v.txtCustomIcon.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedRouting.customIcon, v => v.txtCustomIcon.Text).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.SelectedRouting.customRulesetPath4Singbox, v => v.txtCustomRulesetPath4Singbox.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedRouting.sort, v => v.txtSort.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedRouting.sort, v => v.txtSort.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.RuleAddCmd, v => v.menuRuleAdd).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.RuleAddCmd, v => v.menuRuleAdd).DisposeWith(disposables);
|
||||||
|
@ -128,7 +129,7 @@ namespace v2rayN.Views
|
||||||
lstRules.SelectAll();
|
lstRules.SelectAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnBrowse_Click(object sender, System.Windows.RoutedEventArgs e)
|
private void btnBrowseCustomIcon_Click(object sender, System.Windows.RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (UI.OpenFileDialog(out string fileName,
|
if (UI.OpenFileDialog(out string fileName,
|
||||||
"PNG,ICO|*.png;*.ico") != true)
|
"PNG,ICO|*.png;*.ico") != true)
|
||||||
|
@ -138,5 +139,21 @@ namespace v2rayN.Views
|
||||||
|
|
||||||
txtCustomIcon.Text = fileName;
|
txtCustomIcon.Text = fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void btnBrowseCustomRulesetPath4Singbox_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (UI.OpenFileDialog(out string fileName,
|
||||||
|
"Config|*.json|All|*.*") != true)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
txtCustomRulesetPath4Singbox.Text = fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void linkCustomRulesetPath4Singbox(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Utils.ProcessStart("https://github.com/2dust/v2rayCustomRoutingList/blob/master/singbox_custom_ruleset_example.json");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -90,6 +90,7 @@
|
||||||
Style="{StaticResource ToolbarTextBlock}">
|
Style="{StaticResource ToolbarTextBlock}">
|
||||||
<Hyperlink Click="linkdomainStrategy_Click">
|
<Hyperlink Click="linkdomainStrategy_Click">
|
||||||
<TextBlock Text="{x:Static resx:ResUI.TbdomainStrategy}" />
|
<TextBlock Text="{x:Static resx:ResUI.TbdomainStrategy}" />
|
||||||
|
<materialDesign:PackIcon Kind="Link" />
|
||||||
</Hyperlink>
|
</Hyperlink>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<ComboBox
|
<ComboBox
|
||||||
|
@ -115,6 +116,7 @@
|
||||||
Style="{StaticResource ToolbarTextBlock}">
|
Style="{StaticResource ToolbarTextBlock}">
|
||||||
<Hyperlink Click="linkdomainStrategy4Singbox_Click">
|
<Hyperlink Click="linkdomainStrategy4Singbox_Click">
|
||||||
<TextBlock Text="{x:Static resx:ResUI.TbdomainStrategy4Singbox}" />
|
<TextBlock Text="{x:Static resx:ResUI.TbdomainStrategy4Singbox}" />
|
||||||
|
<materialDesign:PackIcon Kind="Link" />
|
||||||
</Hyperlink>
|
</Hyperlink>
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
<ComboBox
|
<ComboBox
|
||||||
|
|
Loading…
Reference in New Issue