using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using Netch.Utils; namespace Netch.Models { public class Mode { public readonly string? FullName; /// /// 规则 /// public readonly List Rule = new(); /// /// 绕过中国(0. 不绕过 1. 绕过) /// public bool BypassChina { get; set; } /// /// 备注 /// public string Remark { get; set; } = ""; /// /// 类型 /// /// 0. Socks5 + 进程加速 /// /// 1. Socks5 + TUN/TAP 规则内 IP CIDR 加速 /// /// 2. Socks5 + TUN/TAP 全局,绕过规则内 IP CIDR /// /// 3. Socks5 + HTTP 代理(设置到系统代理) /// /// 4. Socks5 代理(不设置到系统代理) /// /// 5. Socks5 + HTTP 代理(不设置到系统代理) /// /// public int Type { get; set; } = 0; public Mode(string fullName) { FullName = fullName; } public Mode() { } /// /// 文件相对路径(必须是存在的文件) /// public string? RelativePath => FullName == null ? null : ModeHelper.GetRelativePath(FullName); public List FullRule { get { var result = new List(); foreach (var s in Rule) { if (string.IsNullOrWhiteSpace(s)) continue; if (s.StartsWith("//")) continue; if (s.StartsWith("#include")) { var relativePath = new StringBuilder(s.Substring(8).Trim()); relativePath.Replace("<", ""); relativePath.Replace(">", ""); relativePath.Replace(".h", ".txt"); var mode = Global.Modes.FirstOrDefault(m => m!.FullName != null && m.RelativePath!.Equals(relativePath.ToString())); if (mode == null) { Logging.Warning($"{relativePath} file included in {Remark} not found"); } else if (mode == this) { Logging.Warning("Can't self-reference"); } else { if (mode.Type != Type) { Logging.Warning($"{mode.Remark}'s mode is not as same as {Remark}'s mode"); } else { if (mode.Rule.Any(rule => rule.StartsWith("#include"))) Logging.Warning("Cannot reference mode that reference other mode"); else result.AddRange(mode.FullRule); } } } else { result.Add(s); } } return result; } } public void WriteFile(string? fullName = null) { if (fullName != null) throw new NotImplementedException(); var dir = Path.GetDirectoryName(FullName)!; if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); // 写入到模式文件里 File.WriteAllText(FullName!, ToFileString()); } /// /// 获取备注 /// /// 备注 public override string ToString() { return $"[{Type + 1}] {i18N.Translate(Remark)}"; } /// /// 获取模式文件字符串 /// /// 模式文件字符串 public string ToFileString() { return $"# {Remark}, {Type}, {(BypassChina ? 1 : 0)}{Global.EOF}{string.Join(Global.EOF, Rule)}"; } } public static class ModeExtension { /// 是否会转发 UDP public static bool TestNatRequired(this Mode mode) { return mode.Type is 0 or 2; } /// Socks5 分流是否能被有效实施 public static bool ClientRouting(this Mode mode) { return mode.Type is not (1 or 2); } } }