Compare commits

...

4 commits

Author SHA1 Message Date
2dust
06cec89ec9 up 7.19.3
Some checks failed
release Linux / build (Release) (push) Has been cancelled
release macOS / build (Release) (push) Has been cancelled
release Windows desktop (Avalonia UI) / build (Release) (push) Has been cancelled
release Windows / build (Release) (push) Has been cancelled
release Linux / rpm (push) Has been cancelled
2026-03-10 17:38:03 +08:00
2dust
26f65dd3b2 Code cleanup: pattern matching and minor fixes 2026-03-10 17:19:21 +08:00
2dust
0c2114d2e1 Refactor SRS rule collection and add DNS parsing 2026-03-10 15:29:36 +08:00
DHR60
4af528f8e2
Typo (#8917) 2026-03-10 14:10:23 +08:00
11 changed files with 87 additions and 39 deletions

View file

@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<Version>7.19.2</Version>
<Version>7.19.3</Version>
</PropertyGroup>
<PropertyGroup>

View file

@ -95,7 +95,7 @@ public class Global
public const string PolicyGroupDefaultAllFilter = $"^(?!.*(?:{PolicyGroupExcludeKeywords})).*$";
public static readonly List<string> PolicyGroupDefaultFilterList =
public static readonly List<string> PolicyGroupDefaultFilterList =
[
// All nodes (exclude traffic/expiry info)
PolicyGroupDefaultAllFilter,

View file

@ -81,7 +81,9 @@ public class NodeValidator
{
var transportError = ValidateSingboxTransport(item.ConfigType, net);
if (transportError != null)
{
v.Error(transportError);
}
if (!Global.SingboxSupportConfigType.Contains(item.ConfigType))
{

View file

@ -1040,8 +1040,8 @@ public static class ConfigHandler
if (profileItem.StreamSecurity.IsNotEmpty())
{
if (profileItem.StreamSecurity != Global.StreamSecurity
&& profileItem.StreamSecurity != Global.StreamSecurityReality)
if (profileItem.StreamSecurity is not Global.StreamSecurity
and not Global.StreamSecurityReality)
{
profileItem.StreamSecurity = string.Empty;
}

View file

@ -9,6 +9,6 @@ public class ServerTestItem
public EConfigType ConfigType { get; set; }
public bool AllowTest { get; set; }
public int QueueNum { get; set; }
public required ProfileItem Profile { get; set; }
public ProfileItem Profile { get; set; }
public ECoreType CoreType { get; set; }
}

View file

@ -243,7 +243,6 @@ public partial class CoreConfigSingboxService
if (Utils.IsIpv6(predefined))
{
rule.answer = new List<string> { $"*. IN AAAA {predefined}" };
}
else
{

View file

@ -321,19 +321,19 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
{
outbound.streamSettings ??= new();
outbound.streamSettings.sockopt ??= new();
outbound.streamSettings.sockopt.dialerProxy = "tun-project-ss";
outbound.streamSettings.sockopt.dialerProxy = "tun-protect-ss";
}
// ech protected
foreach (var outbound in _coreConfig.outbounds
.Where(outbound => outbound.streamSettings?.tlsSettings?.echConfigList?.IsNullOrEmpty() == false))
{
outbound.streamSettings!.tlsSettings!.echSockopt ??= new();
outbound.streamSettings.tlsSettings.echSockopt.dialerProxy = "tun-project-ss";
outbound.streamSettings.tlsSettings.echSockopt.dialerProxy = "tun-protect-ss";
}
_coreConfig.outbounds.Add(new CoreConfigV2rayService(context with
{
Node = protectNode,
}).BuildProxyOutbound("tun-project-ss"));
}).BuildProxyOutbound("tun-protect-ss"));
_coreConfig.routing.rules ??= [];
var hasBalancer = _coreConfig.routing.balancers is { Count: > 0 };

View file

@ -363,44 +363,36 @@ public class UpdateService(Config config, Func<bool, string, Task> updateFunc)
var geoipFiles = new List<string>();
var geoSiteFiles = new List<string>();
//Collect used files list
// Collect from routing rules
var routingItems = await AppManager.Instance.RoutingItems();
foreach (var routing in routingItems)
{
var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);
foreach (var item in rules ?? [])
{
foreach (var ip in item.Ip ?? [])
{
var prefix = "geoip:";
if (ip.StartsWith(prefix))
{
geoipFiles.Add(ip.Substring(prefix.Length));
}
}
foreach (var domain in item.Domain ?? [])
{
var prefix = "geosite:";
if (domain.StartsWith(prefix))
{
geoSiteFiles.Add(domain.Substring(prefix.Length));
}
}
AddPrefixedItems(item.Ip, "geoip:", geoipFiles);
AddPrefixedItems(item.Domain, "geosite:", geoSiteFiles);
}
}
//append dns items TODO
geoSiteFiles.Add("google");
geoSiteFiles.Add("cn");
geoSiteFiles.Add("geolocation-cn");
geoSiteFiles.Add("category-ads-all");
// Collect from DNS configuration
var dnsItem = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);
if (dnsItem != null)
{
ExtractDnsRuleSets(dnsItem.NormalDNS, geoipFiles, geoSiteFiles);
ExtractDnsRuleSets(dnsItem.TunDNS, geoipFiles, geoSiteFiles);
}
// Append default items
geoSiteFiles.AddRange(["google", "cn", "geolocation-cn", "category-ads-all"]);
// Download files
var path = Utils.GetBinPath("srss");
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
foreach (var item in geoipFiles.Distinct())
{
await UpdateSrsFile("geoip", item);
@ -412,6 +404,63 @@ public class UpdateService(Config config, Func<bool, string, Task> updateFunc)
}
}
private void AddPrefixedItems(List<string>? items, string prefix, List<string> output)
{
if (items == null)
{
return;
}
foreach (var item in items)
{
if (item.StartsWith(prefix))
{
output.Add(item.Substring(prefix.Length));
}
}
}
private void ExtractDnsRuleSets(string? dnsJson, List<string> geoipFiles, List<string> geoSiteFiles)
{
if (string.IsNullOrEmpty(dnsJson))
{
return;
}
try
{
var dns = JsonUtils.Deserialize<Dns4Sbox>(dnsJson);
if (dns?.rules != null)
{
foreach (var rule in dns.rules)
{
ExtractSrsRuleSets(rule, geoipFiles, geoSiteFiles);
}
}
}
catch { }
}
private void ExtractSrsRuleSets(Rule4Sbox? rule, List<string> geoipFiles, List<string> geoSiteFiles)
{
if (rule == null)
{
return;
}
AddPrefixedItems(rule.rule_set, "geosite-", geoSiteFiles);
AddPrefixedItems(rule.rule_set, "geoip-", geoipFiles);
// Handle nested rules recursively
if (rule.rules != null)
{
foreach (var nestedRule in rule.rules)
{
ExtractSrsRuleSets(nestedRule, geoipFiles, geoSiteFiles);
}
}
}
private async Task UpdateSrsFile(string type, string srsName)
{
var srsUrl = string.IsNullOrEmpty(_config.ConstItem.SrsSourceUrl)

View file

@ -8,9 +8,9 @@ public partial class ClashConnectionsView : ReactiveUserControl<ClashConnections
public ClashConnectionsView()
{
InitializeComponent();
_config = AppManager.Instance.Config;
ViewModel = new ClashConnectionsViewModel(UpdateViewHandler);
btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click;
@ -65,7 +65,7 @@ public partial class ClashConnectionsView : ReactiveUserControl<ClashConnections
{
ViewModel?.ClashConnectionClose(false);
}
#region UI
private void RestoreUI()

View file

@ -97,8 +97,7 @@ public partial class ProfilesSelectWindow
private void LstProfiles_ColumnHeader_Click(object sender, RoutedEventArgs e)
{
var colHeader = sender as DataGridColumnHeader;
if (colHeader == null || colHeader.TabIndex < 0 || colHeader.Column == null)
if (sender is not DataGridColumnHeader colHeader || colHeader.TabIndex < 0 || colHeader.Column == null)
{
return;
}

View file

@ -233,8 +233,7 @@ public partial class ProfilesView
private void LstProfiles_ColumnHeader_Click(object sender, RoutedEventArgs e)
{
var colHeader = sender as DataGridColumnHeader;
if (colHeader == null || colHeader.TabIndex < 0 || colHeader.Column == null)
if (sender is not DataGridColumnHeader colHeader || colHeader.TabIndex < 0 || colHeader.Column == null)
{
return;
}