Internationalized code comments

This commit is contained in:
2dust 2025-04-09 16:48:38 +08:00
parent 5adae2dd2a
commit 321ec30f39
11 changed files with 336 additions and 124 deletions

View file

@ -8,7 +8,7 @@ public class AesUtils
private const int KeySize = 256; // AES-256 private const int KeySize = 256; // AES-256
private const int IvSize = 16; // AES block size private const int IvSize = 16; // AES block size
private const int Iterations = 10000; private const int Iterations = 10000;
private static readonly byte[] Salt = Encoding.ASCII.GetBytes("saltysalt".PadRight(16, ' ')); // google浏览器默认盐值 private static readonly byte[] Salt = Encoding.ASCII.GetBytes("saltysalt".PadRight(16, ' '));
private static readonly string DefaultPassword = Utils.GetMd5(Utils.GetHomePath() + "AesUtils"); private static readonly string DefaultPassword = Utils.GetMd5(Utils.GetHomePath() + "AesUtils");
/// <summary> /// <summary>

View file

@ -88,7 +88,7 @@ public class JsonUtils
{ {
WriteIndented = indented, WriteIndented = indented,
DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull, DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping // 避免转义加号 Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
}; };
result = JsonSerializer.Serialize(obj, options); result = JsonSerializer.Serialize(obj, options);
} }

View file

@ -11,7 +11,7 @@ public class YamlUtils
#region YAML #region YAML
/// <summary> /// <summary>
/// 反序列化成对象 /// Deserialize
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="str"></param> /// <param name="str"></param>
@ -34,7 +34,7 @@ public class YamlUtils
} }
/// <summary> /// <summary>
/// 序列化 /// Serialize
/// </summary> /// </summary>
/// <param name="obj"></param> /// <param name="obj"></param>
/// <returns></returns> /// <returns></returns>

View file

@ -3,9 +3,6 @@ using System.Text.RegularExpressions;
namespace ServiceLib.Handler; namespace ServiceLib.Handler;
/// <summary>
/// 本软件配置文件处理类
/// </summary>
public class ConfigHandler public class ConfigHandler
{ {
private static readonly string _configRes = Global.ConfigFileName; private static readonly string _configRes = Global.ConfigFileName;
@ -14,10 +11,12 @@ public class ConfigHandler
#region ConfigHandler #region ConfigHandler
/// <summary> /// <summary>
/// 载入配置文件 /// Load the application configuration file
/// If the file exists, deserialize it from JSON
/// If not found, create a new Config object with default settings
/// Initialize default values for missing configuration sections
/// </summary> /// </summary>
/// <param name="config"></param> /// <returns>Config object containing application settings or null if there's an error</returns>
/// <returns></returns>
public static Config? LoadConfig() public static Config? LoadConfig()
{ {
Config? config = null; Config? config = null;
@ -169,10 +168,11 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// 保参数 /// Save the configuration to a file
/// First writes to a temporary file, then replaces the original file
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Configuration object to be saved</param>
/// <returns></returns> /// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> SaveConfig(Config config) public static async Task<int> SaveConfig(Config config)
{ {
try try
@ -204,6 +204,13 @@ public class ConfigHandler
#region Server #region Server
/// <summary>
/// Add a server profile to the configuration
/// Dispatches the request to the appropriate method based on the config type
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">Server profile to add</param>
/// <returns>Result of the operation (0 if successful, -1 if failed)</returns>
public static async Task<int> AddServer(Config config, ProfileItem profileItem) public static async Task<int> AddServer(Config config, ProfileItem profileItem)
{ {
var item = await AppHandler.Instance.GetProfileItem(profileItem.IndexId); var item = await AppHandler.Instance.GetProfileItem(profileItem.IndexId);
@ -258,11 +265,13 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// Add or edit server /// Add or edit a VMess server
/// Validates and processes VMess-specific settings
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="profileItem"></param> /// <param name="profileItem">VMess profile to add</param>
/// <returns></returns> /// <param name="toFile">Whether to save to file</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddVMessServer(Config config, ProfileItem profileItem, bool toFile = true) public static async Task<int> AddVMessServer(Config config, ProfileItem profileItem, bool toFile = true)
{ {
profileItem.ConfigType = EConfigType.VMess; profileItem.ConfigType = EConfigType.VMess;
@ -291,11 +300,11 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// 移除服务器 /// Remove multiple servers from the configuration
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="indexes"></param> /// <param name="indexes">List of server profiles to remove</param>
/// <returns></returns> /// <returns>0 if successful</returns>
public static async Task<int> RemoveServers(Config config, List<ProfileItem> indexes) public static async Task<int> RemoveServers(Config config, List<ProfileItem> indexes)
{ {
var subid = "TempRemoveSubId"; var subid = "TempRemoveSubId";
@ -311,11 +320,12 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// 克隆服务器 /// Clone server profiles
/// Creates copies of the specified server profiles with "-clone" appended to the remarks
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="index"></param> /// <param name="indexes">List of server profiles to clone</param>
/// <returns></returns> /// <returns>0 if successful</returns>
public static async Task<int> CopyServer(Config config, List<ProfileItem> indexes) public static async Task<int> CopyServer(Config config, List<ProfileItem> indexes)
{ {
foreach (var it in indexes) foreach (var it in indexes)
@ -347,11 +357,12 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// 设置活动服务器 /// Set the default server by its index ID
/// Updates the configuration to use the specified server as default
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="item"></param> /// <param name="indexId">Index ID of the server to set as default</param>
/// <returns></returns> /// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> SetDefaultServerIndex(Config config, string? indexId) public static async Task<int> SetDefaultServerIndex(Config config, string? indexId)
{ {
if (indexId.IsNullOrEmpty()) if (indexId.IsNullOrEmpty())
@ -366,6 +377,13 @@ public class ConfigHandler
return 0; return 0;
} }
/// <summary>
/// Set a default server from the provided list of profiles
/// Ensures there's always a valid default server selected
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="lstProfile">List of profile models to choose from</param>
/// <returns>Result of SetDefaultServerIndex operation</returns>
public static async Task<int> SetDefaultServer(Config config, List<ProfileItemModel> lstProfile) public static async Task<int> SetDefaultServer(Config config, List<ProfileItemModel> lstProfile)
{ {
if (lstProfile.Exists(t => t.IndexId == config.IndexId)) if (lstProfile.Exists(t => t.IndexId == config.IndexId))
@ -386,6 +404,12 @@ public class ConfigHandler
return await SetDefaultServerIndex(config, item?.IndexId); return await SetDefaultServerIndex(config, item?.IndexId);
} }
/// <summary>
/// Get the current default server profile
/// If the current default is invalid, selects a new default
/// </summary>
/// <param name="config">Current configuration</param>
/// <returns>The default profile item or null if none exists</returns>
public static async Task<ProfileItem?> GetDefaultServer(Config config) public static async Task<ProfileItem?> GetDefaultServer(Config config)
{ {
var item = await AppHandler.Instance.GetProfileItem(config.IndexId); var item = await AppHandler.Instance.GetProfileItem(config.IndexId);
@ -400,13 +424,15 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// 移动服务器 /// Move a server in the list to a different position
/// Supports moving to top, up, down, bottom or specific position
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="lstProfile"></param> /// <param name="lstProfile">List of server profiles</param>
/// <param name="index"></param> /// <param name="index">Index of the server to move</param>
/// <param name="eMove"></param> /// <param name="eMove">Direction to move the server</param>
/// <returns></returns> /// <param name="pos">Target position when using EMove.Position</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> MoveServer(Config config, List<ProfileItem> lstProfile, int index, EMove eMove, int pos = -1) public static async Task<int> MoveServer(Config config, List<ProfileItem> lstProfile, int index, EMove eMove, int pos = -1)
{ {
int count = lstProfile.Count; int count = lstProfile.Count;
@ -474,11 +500,13 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// 添加自定义服务器 /// Add a custom server configuration from a file
/// Copies the configuration file to the app's config directory
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="profileItem"></param> /// <param name="profileItem">Profile item with the file path in Address</param>
/// <returns></returns> /// <param name="blDelete">Whether to delete the source file after copying</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddCustomServer(Config config, ProfileItem profileItem, bool blDelete) public static async Task<int> AddCustomServer(Config config, ProfileItem profileItem, bool blDelete)
{ {
var fileName = profileItem.Address; var fileName = profileItem.Address;
@ -517,11 +545,12 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// Add or edit server /// Edit an existing custom server configuration
/// Updates the server's properties without changing the file
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="profileItem"></param> /// <param name="profileItem">Profile item with updated properties</param>
/// <returns></returns> /// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> EditCustomServer(Config config, ProfileItem profileItem) public static async Task<int> EditCustomServer(Config config, ProfileItem profileItem)
{ {
var item = await AppHandler.Instance.GetProfileItem(profileItem.IndexId); var item = await AppHandler.Instance.GetProfileItem(profileItem.IndexId);
@ -551,11 +580,13 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// Add or edit server /// Add or edit a Shadowsocks server
/// Validates and processes Shadowsocks-specific settings
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="profileItem"></param> /// <param name="profileItem">Shadowsocks profile to add</param>
/// <returns></returns> /// <param name="toFile">Whether to save to file</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddShadowsocksServer(Config config, ProfileItem profileItem, bool toFile = true) public static async Task<int> AddShadowsocksServer(Config config, ProfileItem profileItem, bool toFile = true)
{ {
profileItem.ConfigType = EConfigType.Shadowsocks; profileItem.ConfigType = EConfigType.Shadowsocks;
@ -579,11 +610,13 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// Add or edit server /// Add or edit a SOCKS server
/// Processes SOCKS-specific settings
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="profileItem"></param> /// <param name="profileItem">SOCKS profile to add</param>
/// <returns></returns> /// <param name="toFile">Whether to save to file</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddSocksServer(Config config, ProfileItem profileItem, bool toFile = true) public static async Task<int> AddSocksServer(Config config, ProfileItem profileItem, bool toFile = true)
{ {
profileItem.ConfigType = EConfigType.SOCKS; profileItem.ConfigType = EConfigType.SOCKS;
@ -596,11 +629,13 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// Add or edit server /// Add or edit an HTTP server
/// Processes HTTP-specific settings
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="profileItem"></param> /// <param name="profileItem">HTTP profile to add</param>
/// <returns></returns> /// <param name="toFile">Whether to save to file</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddHttpServer(Config config, ProfileItem profileItem, bool toFile = true) public static async Task<int> AddHttpServer(Config config, ProfileItem profileItem, bool toFile = true)
{ {
profileItem.ConfigType = EConfigType.HTTP; profileItem.ConfigType = EConfigType.HTTP;
@ -613,11 +648,13 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// Add or edit server /// Add or edit a Trojan server
/// Validates and processes Trojan-specific settings
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="profileItem"></param> /// <param name="profileItem">Trojan profile to add</param>
/// <returns></returns> /// <param name="toFile">Whether to save to file</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddTrojanServer(Config config, ProfileItem profileItem, bool toFile = true) public static async Task<int> AddTrojanServer(Config config, ProfileItem profileItem, bool toFile = true)
{ {
profileItem.ConfigType = EConfigType.Trojan; profileItem.ConfigType = EConfigType.Trojan;
@ -639,11 +676,14 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// Add or edit server /// Add or edit a Hysteria2 server
/// Validates and processes Hysteria2-specific settings
/// Sets the core type to sing_box as required by Hysteria2
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="profileItem"></param> /// <param name="profileItem">Hysteria2 profile to add</param>
/// <returns></returns> /// <param name="toFile">Whether to save to file</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddHysteria2Server(Config config, ProfileItem profileItem, bool toFile = true) public static async Task<int> AddHysteria2Server(Config config, ProfileItem profileItem, bool toFile = true)
{ {
profileItem.ConfigType = EConfigType.Hysteria2; profileItem.ConfigType = EConfigType.Hysteria2;
@ -669,11 +709,14 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// Add or edit server /// Add or edit a TUIC server
/// Validates and processes TUIC-specific settings
/// Sets the core type to sing_box as required by TUIC
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="profileItem"></param> /// <param name="profileItem">TUIC profile to add</param>
/// <returns></returns> /// <param name="toFile">Whether to save to file</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddTuicServer(Config config, ProfileItem profileItem, bool toFile = true) public static async Task<int> AddTuicServer(Config config, ProfileItem profileItem, bool toFile = true)
{ {
profileItem.ConfigType = EConfigType.TUIC; profileItem.ConfigType = EConfigType.TUIC;
@ -708,11 +751,13 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// Add or edit server /// Add or edit a WireGuard server
/// Validates and processes WireGuard-specific settings
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="profileItem"></param> /// <param name="profileItem">WireGuard profile to add</param>
/// <returns></returns> /// <param name="toFile">Whether to save to file</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddWireguardServer(Config config, ProfileItem profileItem, bool toFile = true) public static async Task<int> AddWireguardServer(Config config, ProfileItem profileItem, bool toFile = true)
{ {
profileItem.ConfigType = EConfigType.WireGuard; profileItem.ConfigType = EConfigType.WireGuard;
@ -738,6 +783,15 @@ public class ConfigHandler
return 0; return 0;
} }
/// <summary>
/// Sort the server list by the specified column
/// Updates the sort order in the profile extension data
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="subId">Subscription ID to filter servers</param>
/// <param name="colName">Column name to sort by</param>
/// <param name="asc">Sort in ascending order if true, descending if false</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> SortServers(Config config, string subId, string colName, bool asc) public static async Task<int> SortServers(Config config, string subId, string colName, bool asc)
{ {
var lstModel = await AppHandler.Instance.ProfileItems(subId, ""); var lstModel = await AppHandler.Instance.ProfileItems(subId, "");
@ -831,11 +885,13 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// Add or edit server /// Add or edit a VLESS server
/// Validates and processes VLESS-specific settings
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="profileItem"></param> /// <param name="profileItem">VLESS profile to add</param>
/// <returns></returns> /// <param name="toFile">Whether to save to file</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddVlessServer(Config config, ProfileItem profileItem, bool toFile = true) public static async Task<int> AddVlessServer(Config config, ProfileItem profileItem, bool toFile = true)
{ {
profileItem.ConfigType = EConfigType.VLESS; profileItem.ConfigType = EConfigType.VLESS;
@ -867,6 +923,13 @@ public class ConfigHandler
return 0; return 0;
} }
/// <summary>
/// Remove duplicate servers from a subscription
/// Compares servers based on their properties rather than just names
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="subId">Subscription ID to deduplicate</param>
/// <returns>Tuple with total count and remaining count after deduplication</returns>
public static async Task<Tuple<int, int>> DedupServerList(Config config, string subId) public static async Task<Tuple<int, int>> DedupServerList(Config config, string subId)
{ {
var lstProfile = await AppHandler.Instance.ProfileItems(subId); var lstProfile = await AppHandler.Instance.ProfileItems(subId);
@ -898,6 +961,14 @@ public class ConfigHandler
return new Tuple<int, int>(lstProfile.Count, lstKeep.Count); return new Tuple<int, int>(lstProfile.Count, lstKeep.Count);
} }
/// <summary>
/// Common server addition logic used by all server types
/// Sets common properties and handles sorting and persistence
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">Profile item to add</param>
/// <param name="toFile">Whether to save to database</param>
/// <returns>0 if successful</returns>
public static async Task<int> AddServerCommon(Config config, ProfileItem profileItem, bool toFile = true) public static async Task<int> AddServerCommon(Config config, ProfileItem profileItem, bool toFile = true)
{ {
profileItem.ConfigVersion = 2; profileItem.ConfigVersion = 2;
@ -949,6 +1020,14 @@ public class ConfigHandler
return 0; return 0;
} }
/// <summary>
/// Compare two profile items to determine if they represent the same server
/// Used for deduplication and server matching
/// </summary>
/// <param name="o">First profile item</param>
/// <param name="n">Second profile item</param>
/// <param name="remarks">Whether to compare remarks</param>
/// <returns>True if the profiles match, false otherwise</returns>
private static bool CompareProfileItem(ProfileItem? o, ProfileItem? n, bool remarks) private static bool CompareProfileItem(ProfileItem? o, ProfileItem? n, bool remarks)
{ {
if (o == null || n == null) if (o == null || n == null)
@ -980,6 +1059,13 @@ public class ConfigHandler
} }
} }
/// <summary>
/// Remove a single server profile by its index ID
/// Deletes the configuration file if it's a custom config
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="indexId">Index ID of the profile to remove</param>
/// <returns>0 if successful</returns>
private static async Task<int> RemoveProfileItem(Config config, string indexId) private static async Task<int> RemoveProfileItem(Config config, string indexId)
{ {
try try
@ -1004,6 +1090,15 @@ public class ConfigHandler
return 0; return 0;
} }
/// <summary>
/// Create a custom server that combines multiple servers for load balancing
/// Generates a configuration file that references multiple servers
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="selecteds">Selected servers to combine</param>
/// <param name="coreType">Core type to use (Xray or sing_box)</param>
/// <param name="multipleLoad">Load balancing algorithm</param>
/// <returns>Result object with success state and data</returns>
public static async Task<RetResult> AddCustomServer4Multiple(Config config, List<ProfileItem> selecteds, ECoreType coreType, EMultipleLoad multipleLoad) public static async Task<RetResult> AddCustomServer4Multiple(Config config, List<ProfileItem> selecteds, ECoreType coreType, EMultipleLoad multipleLoad)
{ {
var indexId = Utils.GetMd5(Global.CoreMultipleLoadConfigFileName); var indexId = Utils.GetMd5(Global.CoreMultipleLoadConfigFileName);
@ -1047,6 +1142,14 @@ public class ConfigHandler
return result; 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
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="node">Server node that might need pre-SOCKS</param>
/// <param name="coreType">Core type being used</param>
/// <returns>A SOCKS profile item or null if not needed</returns>
public static async Task<ProfileItem?> GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType) public static async Task<ProfileItem?> GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType)
{ {
ProfileItem? itemSocks = null; ProfileItem? itemSocks = null;
@ -1076,6 +1179,13 @@ public class ConfigHandler
return itemSocks; return itemSocks;
} }
/// <summary>
/// Remove servers with invalid test results (timeout)
/// Useful for cleaning up subscription lists
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="subid">Subscription ID to filter servers</param>
/// <returns>Number of removed servers or -1 if failed</returns>
public static async Task<int> RemoveInvalidServerResult(Config config, string subid) public static async Task<int> RemoveInvalidServerResult(Config config, string subid)
{ {
var lstModel = await AppHandler.Instance.ProfileItems(subid, ""); var lstModel = await AppHandler.Instance.ProfileItems(subid, "");
@ -1099,12 +1209,14 @@ public class ConfigHandler
#region Batch add servers #region Batch add servers
/// <summary> /// <summary>
/// 批量添加服务器 /// Add multiple servers from string data (common protocols)
/// Parses the string data into server profiles
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="strData"></param> /// <param name="strData">String data containing server information</param>
/// <param name="subid"></param> /// <param name="subid">Subscription ID to associate with the servers</param>
/// <returns>成功导入的数量</returns> /// <param name="isSub">Whether this is from a subscription</param>
/// <returns>Number of successfully imported servers or -1 if failed</returns>
private static async Task<int> AddBatchServersCommon(Config config, string strData, string subid, bool isSub) private static async Task<int> AddBatchServersCommon(Config config, string strData, string subid, bool isSub)
{ {
if (strData.IsNullOrEmpty()) if (strData.IsNullOrEmpty())
@ -1184,6 +1296,15 @@ public class ConfigHandler
return countServers; return countServers;
} }
/// <summary>
/// Add servers from custom configuration formats (sing-box, v2ray, etc.)
/// Handles various configuration formats and imports them as custom configs
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="strData">String data containing server information</param>
/// <param name="subid">Subscription ID to associate with the servers</param>
/// <param name="isSub">Whether this is from a subscription</param>
/// <returns>Number of successfully imported servers or -1 if failed</returns>
private static async Task<int> AddBatchServers4Custom(Config config, string strData, string subid, bool isSub) private static async Task<int> AddBatchServers4Custom(Config config, string strData, string subid, bool isSub)
{ {
if (strData.IsNullOrEmpty()) if (strData.IsNullOrEmpty())
@ -1282,6 +1403,15 @@ public class ConfigHandler
} }
} }
/// <summary>
/// Add Shadowsocks servers from SIP008 format
/// SIP008 is a JSON-based format for Shadowsocks servers
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="strData">String data in SIP008 format</param>
/// <param name="subid">Subscription ID to associate with the servers</param>
/// <param name="isSub">Whether this is from a subscription</param>
/// <returns>Number of successfully imported servers or -1 if failed</returns>
private static async Task<int> AddBatchServers4SsSIP008(Config config, string strData, string subid, bool isSub) private static async Task<int> AddBatchServers4SsSIP008(Config config, string strData, string subid, bool isSub)
{ {
if (strData.IsNullOrEmpty()) if (strData.IsNullOrEmpty())
@ -1314,6 +1444,15 @@ public class ConfigHandler
return -1; return -1;
} }
/// <summary>
/// Main entry point for adding batch servers from various formats
/// Tries different parsing methods to import as many servers as possible
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="strData">String data containing server information</param>
/// <param name="subid">Subscription ID to associate with the servers</param>
/// <param name="isSub">Whether this is from a subscription</param>
/// <returns>Number of successfully imported servers or -1 if failed</returns>
public static async Task<int> AddBatchServers(Config config, string strData, string subid, bool isSub) public static async Task<int> AddBatchServers(Config config, string strData, string subid, bool isSub)
{ {
if (strData.IsNullOrEmpty()) if (strData.IsNullOrEmpty())
@ -1386,11 +1525,12 @@ public class ConfigHandler
#region Sub & Group #region Sub & Group
/// <summary> /// <summary>
/// add sub /// Add a subscription item from URL
/// Creates a new subscription with default settings
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="url"></param> /// <param name="url">Subscription URL</param>
/// <returns></returns> /// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddSubItem(Config config, string url) public static async Task<int> AddSubItem(Config config, string url)
{ {
//already exists //already exists
@ -1422,6 +1562,12 @@ public class ConfigHandler
return await AddSubItem(config, subItem); return await AddSubItem(config, subItem);
} }
/// <summary>
/// Add or update a subscription item
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="subItem">Subscription item to add or update</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddSubItem(Config config, SubItem subItem) public static async Task<int> AddSubItem(Config config, SubItem subItem)
{ {
var item = await AppHandler.Instance.GetSubItem(subItem.Id); var item = await AppHandler.Instance.GetSubItem(subItem.Id);
@ -1473,11 +1619,12 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// 移除服务器 /// Remove servers associated with a subscription ID
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="config">Current configuration</param>
/// <param name="subid"></param> /// <param name="subid">Subscription ID</param>
/// <returns></returns> /// <param name="isSub">Whether to only remove servers marked as subscription items</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> RemoveServersViaSubid(Config config, string subid, bool isSub) public static async Task<int> RemoveServersViaSubid(Config config, string subid, bool isSub)
{ {
if (subid.IsNullOrEmpty()) if (subid.IsNullOrEmpty())
@ -1501,6 +1648,12 @@ public class ConfigHandler
return 0; return 0;
} }
/// <summary>
/// Delete a subscription item and all its associated servers
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="id">Subscription ID to delete</param>
/// <returns>0 if successful</returns>
public static async Task<int> DeleteSubItem(Config config, string id) public static async Task<int> DeleteSubItem(Config config, string id)
{ {
var item = await AppHandler.Instance.GetSubItem(id); var item = await AppHandler.Instance.GetSubItem(id);
@ -1514,6 +1667,13 @@ public class ConfigHandler
return 0; return 0;
} }
/// <summary>
/// Move servers to a different group (subscription)
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="lstProfile">List of profiles to move</param>
/// <param name="subid">Target subscription ID</param>
/// <returns>0 if successful</returns>
public static async Task<int> MoveToGroup(Config config, List<ProfileItem> lstProfile, string subid) public static async Task<int> MoveToGroup(Config config, List<ProfileItem> lstProfile, string subid)
{ {
foreach (var item in lstProfile) foreach (var item in lstProfile)
@ -1529,6 +1689,12 @@ public class ConfigHandler
#region Routing #region Routing
/// <summary>
/// Save a routing item to the database
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="item">Routing item to save</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> SaveRoutingItem(Config config, RoutingItem item) public static async Task<int> SaveRoutingItem(Config config, RoutingItem item)
{ {
if (item.Id.IsNullOrEmpty()) if (item.Id.IsNullOrEmpty())
@ -1547,11 +1713,11 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// AddBatchRoutingRules /// Add multiple routing rules to a routing item
/// </summary> /// </summary>
/// <param name="config"></param> /// <param name="routingItem">Routing item to add rules to</param>
/// <param name="strData"></param> /// <param name="strData">JSON string containing rules data</param>
/// <returns></returns> /// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddBatchRoutingRules(RoutingItem routingItem, string strData) public static async Task<int> AddBatchRoutingRules(RoutingItem routingItem, string strData)
{ {
if (strData.IsNullOrEmpty()) if (strData.IsNullOrEmpty())
@ -1588,12 +1754,14 @@ public class ConfigHandler
} }
/// <summary> /// <summary>
/// MoveRoutingRule /// Move a routing rule within a rules list
/// Supports moving to top, up, down, bottom or specific position
/// </summary> /// </summary>
/// <param name="routingItem"></param> /// <param name="rules">List of routing rules</param>
/// <param name="index"></param> /// <param name="index">Index of the rule to move</param>
/// <param name="eMove"></param> /// <param name="eMove">Direction to move the rule</param>
/// <returns></returns> /// <param name="pos">Target position when using EMove.Position</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> MoveRoutingRule(List<RulesItem> rules, int index, EMove eMove, int pos = -1) public static async Task<int> MoveRoutingRule(List<RulesItem> rules, int index, EMove eMove, int pos = -1)
{ {
int count = rules.Count; int count = rules.Count;
@ -1664,6 +1832,12 @@ public class ConfigHandler
return await Task.FromResult(0); return await Task.FromResult(0);
} }
/// <summary>
/// Set the default routing configuration
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="routingItem">Routing item to set as default</param>
/// <returns>0 if successful</returns>
public static async Task<int> SetDefaultRouting(Config config, RoutingItem routingItem) public static async Task<int> SetDefaultRouting(Config config, RoutingItem routingItem)
{ {
if (await SQLiteHelper.Instance.TableAsync<RoutingItem>().Where(t => t.Id == routingItem.Id).CountAsync() > 0) if (await SQLiteHelper.Instance.TableAsync<RoutingItem>().Where(t => t.Id == routingItem.Id).CountAsync() > 0)
@ -1676,6 +1850,12 @@ public class ConfigHandler
return 0; return 0;
} }
/// <summary>
/// Get the current default routing configuration
/// If no default is set, selects the first available routing item
/// </summary>
/// <param name="config">Current configuration</param>
/// <returns>The default routing item</returns>
public static async Task<RoutingItem> GetDefaultRouting(Config config) public static async Task<RoutingItem> GetDefaultRouting(Config config)
{ {
var item = await AppHandler.Instance.GetRoutingItem(config.RoutingBasicItem.RoutingIndexId); var item = await AppHandler.Instance.GetRoutingItem(config.RoutingBasicItem.RoutingIndexId);
@ -1689,6 +1869,12 @@ public class ConfigHandler
return item; return item;
} }
/// <summary>
/// Initialize routing rules from built-in or external templates
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="blImportAdvancedRules">Whether to import advanced rules</param>
/// <returns>0 if successful</returns>
public static async Task<int> InitRouting(Config config, bool blImportAdvancedRules = false) public static async Task<int> InitRouting(Config config, bool blImportAdvancedRules = false)
{ {
if (config.ConstItem.RouteRulesTemplateSourceUrl.IsNullOrEmpty()) if (config.ConstItem.RouteRulesTemplateSourceUrl.IsNullOrEmpty())
@ -1703,6 +1889,13 @@ public class ConfigHandler
return 0; return 0;
} }
/// <summary>
/// Initialize routing rules from external templates
/// Downloads and processes routing templates from a URL
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="blImportAdvancedRules">Whether to import advanced rules</param>
/// <returns>0 if successful</returns>
public static async Task<int> InitExternalRouting(Config config, bool blImportAdvancedRules = false) public static async Task<int> InitExternalRouting(Config config, bool blImportAdvancedRules = false)
{ {
var downloadHandle = new DownloadService(); var downloadHandle = new DownloadService();
@ -1751,6 +1944,13 @@ public class ConfigHandler
return 0; return 0;
} }
/// <summary>
/// Initialize built-in routing rules
/// Creates default routing configurations (whitelist, blacklist, global)
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="blImportAdvancedRules">Whether to import advanced rules</param>
/// <returns>0 if successful</returns>
public static async Task<int> InitBuiltinRouting(Config config, bool blImportAdvancedRules = false) public static async Task<int> InitBuiltinRouting(Config config, bool blImportAdvancedRules = false)
{ {
var ver = "V3-"; var ver = "V3-";
@ -1804,6 +2004,10 @@ public class ConfigHandler
return 0; return 0;
} }
/// <summary>
/// Remove a routing item from the database
/// </summary>
/// <param name="routingItem">Routing item to remove</param>
public static async Task RemoveRoutingItem(RoutingItem routingItem) public static async Task RemoveRoutingItem(RoutingItem routingItem)
{ {
await SQLiteHelper.Instance.DeleteAsync(routingItem); await SQLiteHelper.Instance.DeleteAsync(routingItem);
@ -1813,6 +2017,12 @@ public class ConfigHandler
#region DNS #region DNS
/// <summary>
/// Initialize built-in DNS configurations
/// Creates default DNS items for V2Ray and sing-box
/// </summary>
/// <param name="config">Current configuration</param>
/// <returns>0 if successful</returns>
public static async Task<int> InitBuiltinDNS(Config config) public static async Task<int> InitBuiltinDNS(Config config)
{ {
var items = await AppHandler.Instance.DNSItems(); var items = await AppHandler.Instance.DNSItems();
@ -1836,6 +2046,12 @@ public class ConfigHandler
return 0; return 0;
} }
/// <summary>
/// Save a DNS item to the database
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="item">DNS item to save</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> SaveDNSItems(Config config, DNSItem item) public static async Task<int> SaveDNSItems(Config config, DNSItem item)
{ {
if (item == null) if (item == null)
@ -1858,6 +2074,13 @@ public class ConfigHandler
} }
} }
/// <summary>
/// Get an external DNS configuration from URL
/// Downloads and processes DNS templates
/// </summary>
/// <param name="type">Core type (Xray or sing-box)</param>
/// <param name="url">URL of the DNS template</param>
/// <returns>DNS item with configuration from the URL</returns>
public static async Task<DNSItem> GetExternalDNSItem(ECoreType type, string url) public static async Task<DNSItem> GetExternalDNSItem(ECoreType type, string url)
{ {
var currentItem = await AppHandler.Instance.GetDNSItem(type); var currentItem = await AppHandler.Instance.GetDNSItem(type);
@ -1889,6 +2112,13 @@ public class ConfigHandler
#region Regional Presets #region Regional Presets
/// <summary>
/// Apply regional presets for geo-specific configurations
/// Sets up geo files, routing rules, and DNS for specific regions
/// </summary>
/// <param name="config">Current configuration</param>
/// <param name="type">Type of preset (Default, Russia, Iran)</param>
/// <returns>True if successful</returns>
public static async Task<bool> ApplyRegionalPreset(Config config, EPresetType type) public static async Task<bool> ApplyRegionalPreset(Config config, EPresetType type)
{ {
switch (type) switch (type)

View file

@ -8,10 +8,13 @@ public class BaseFmt
{ {
if (Utils.IsIpv6(address)) if (Utils.IsIpv6(address))
{ {
// 检查地址是否已经被方括号包围,如果没有,则添加方括号 // Check if the address is already surrounded by square brackets, if not, add square brackets
return address.StartsWith('[') && address.EndsWith(']') ? address : $"[{address}]"; return address.StartsWith('[') && address.EndsWith(']') ? address : $"[{address}]";
} }
return address; // 如果不是IPv6地址直接返回原地址 else
{
return address;
}
} }
protected static int GetStdTransport(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery) protected static int GetStdTransport(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery)

View file

@ -1,8 +1,5 @@
namespace ServiceLib.Models; namespace ServiceLib.Models;
/// <summary>
/// 本软件配置文件实体类
/// </summary>
[Serializable] [Serializable]
public class Config public class Config
{ {

View file

@ -1,8 +1,5 @@
namespace ServiceLib.Models; namespace ServiceLib.Models;
/// <summary>
/// Tcp伪装http的Request只要Host
/// </summary>
public class V2rayTcpRequest public class V2rayTcpRequest
{ {
/// <summary> /// <summary>

View file

@ -13,13 +13,6 @@ public class CoreConfigClashService
_config = config; _config = config;
} }
/// <summary>
/// 生成配置文件
/// </summary>
/// <param name="node"></param>
/// <param name="fileName"></param>
/// <param name="msg"></param>
/// <returns></returns>
public async Task<RetResult> GenerateClientCustomConfig(ProfileItem node, string? fileName) public async Task<RetResult> GenerateClientCustomConfig(ProfileItem node, string? fileName)
{ {
var ret = new RetResult(); var ret = new RetResult();

View file

@ -661,7 +661,7 @@ public class CoreConfigV2rayService
{ {
usersItem = vnextItem.users.First(); usersItem = vnextItem.users.First();
} }
//远程服务器用户ID
usersItem.id = node.Id; usersItem.id = node.Id;
usersItem.alterId = node.AlterId; usersItem.alterId = node.AlterId;
usersItem.email = Global.UserEMail; usersItem.email = Global.UserEMail;
@ -1143,7 +1143,7 @@ public class CoreConfigV2rayService
obj["servers"] = JsonUtils.SerializeToNode(servers); obj["servers"] = JsonUtils.SerializeToNode(servers);
} }
// 追加至 dns 设置 // Append to dns settings
if (item.UseSystemHosts) if (item.UseSystemHosts)
{ {
var systemHosts = Utils.GetSystemHosts(); var systemHosts = Utils.GetSystemHosts();

View file

@ -19,7 +19,7 @@ public partial class App : Application
} }
/// <summary> /// <summary>
/// 只打开一个进程 /// Open only one process
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
protected override void OnStartup(StartupEventArgs e) protected override void OnStartup(StartupEventArgs e)

View file

@ -12,10 +12,6 @@ internal static class WindowsUtils
{ {
private static readonly string _tag = "WindowsUtils"; private static readonly string _tag = "WindowsUtils";
/// <summary>
/// 获取剪贴板数
/// </summary>
/// <returns></returns>
public static string? GetClipboardData() public static string? GetClipboardData()
{ {
var strData = string.Empty; var strData = string.Empty;
@ -35,10 +31,6 @@ internal static class WindowsUtils
return strData; return strData;
} }
/// <summary>
/// 拷贝至剪贴板
/// </summary>
/// <returns></returns>
public static void SetClipboardData(string strData) public static void SetClipboardData(string strData)
{ {
try try