Merge branch '2dust:master' into accessibility

This commit is contained in:
Reza Bakhshi Laktasaraei 2025-04-11 03:43:14 +03:30 committed by GitHub
commit ee6ca1b364
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 637 additions and 339 deletions

View file

@ -1,7 +1,7 @@
<Project>
<PropertyGroup>
<Version>7.11.0</Version>
<Version>7.11.1</Version>
</PropertyGroup>
<PropertyGroup>

View file

@ -8,7 +8,7 @@ public class AesUtils
private const int KeySize = 256; // AES-256
private const int IvSize = 16; // AES block size
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");
/// <summary>

View file

@ -1,3 +1,4 @@
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
@ -86,7 +87,8 @@ public class JsonUtils
var options = new JsonSerializerOptions
{
WriteIndented = indented,
DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull
DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
result = JsonSerializer.Serialize(obj, options);
}

View file

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

View file

@ -125,7 +125,7 @@ public class Global
[
"",
@"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/{0}.dat",
@"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-v2ray-rules@release/{0}.dat"
@"https://github.com/Chocolate4U/Iran-v2ray-rules/releases/latest/download/{0}.dat"
];
public static readonly List<string> SingboxRulesetSources =

View file

@ -3,9 +3,6 @@ using System.Text.RegularExpressions;
namespace ServiceLib.Handler;
/// <summary>
/// 本软件配置文件处理类
/// </summary>
public class ConfigHandler
{
private static readonly string _configRes = Global.ConfigFileName;
@ -14,10 +11,12 @@ public class ConfigHandler
#region ConfigHandler
/// <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>
/// <param name="config"></param>
/// <returns></returns>
/// <returns>Config object containing application settings or null if there's an error</returns>
public static Config? LoadConfig()
{
Config? config = null;
@ -169,10 +168,11 @@ public class ConfigHandler
}
/// <summary>
/// 保参数
/// Save the configuration to a file
/// First writes to a temporary file, then replaces the original file
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
/// <param name="config">Configuration object to be saved</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> SaveConfig(Config config)
{
try
@ -204,6 +204,13 @@ public class ConfigHandler
#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)
{
var item = await AppHandler.Instance.GetProfileItem(profileItem.IndexId);
@ -258,11 +265,13 @@ public class ConfigHandler
}
/// <summary>
/// Add or edit server
/// Add or edit a VMess server
/// Validates and processes VMess-specific settings
/// </summary>
/// <param name="config"></param>
/// <param name="profileItem"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">VMess profile to add</param>
/// <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)
{
profileItem.ConfigType = EConfigType.VMess;
@ -291,11 +300,11 @@ public class ConfigHandler
}
/// <summary>
/// 移除服务器
/// Remove multiple servers from the configuration
/// </summary>
/// <param name="config"></param>
/// <param name="indexes"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="indexes">List of server profiles to remove</param>
/// <returns>0 if successful</returns>
public static async Task<int> RemoveServers(Config config, List<ProfileItem> indexes)
{
var subid = "TempRemoveSubId";
@ -311,11 +320,12 @@ public class ConfigHandler
}
/// <summary>
/// 克隆服务器
/// Clone server profiles
/// Creates copies of the specified server profiles with "-clone" appended to the remarks
/// </summary>
/// <param name="config"></param>
/// <param name="index"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="indexes">List of server profiles to clone</param>
/// <returns>0 if successful</returns>
public static async Task<int> CopyServer(Config config, List<ProfileItem> indexes)
{
foreach (var it in indexes)
@ -347,11 +357,12 @@ public class ConfigHandler
}
/// <summary>
/// 设置活动服务器
/// Set the default server by its index ID
/// Updates the configuration to use the specified server as default
/// </summary>
/// <param name="config"></param>
/// <param name="item"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="indexId">Index ID of the server to set as default</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> SetDefaultServerIndex(Config config, string? indexId)
{
if (indexId.IsNullOrEmpty())
@ -366,6 +377,13 @@ public class ConfigHandler
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)
{
if (lstProfile.Exists(t => t.IndexId == config.IndexId))
@ -386,6 +404,12 @@ public class ConfigHandler
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)
{
var item = await AppHandler.Instance.GetProfileItem(config.IndexId);
@ -400,13 +424,15 @@ public class ConfigHandler
}
/// <summary>
/// 移动服务器
/// Move a server in the list to a different position
/// Supports moving to top, up, down, bottom or specific position
/// </summary>
/// <param name="config"></param>
/// <param name="lstProfile"></param>
/// <param name="index"></param>
/// <param name="eMove"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="lstProfile">List of server profiles</param>
/// <param name="index">Index of the server to move</param>
/// <param name="eMove">Direction to move the server</param>
/// <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)
{
int count = lstProfile.Count;
@ -474,11 +500,13 @@ public class ConfigHandler
}
/// <summary>
/// 添加自定义服务器
/// Add a custom server configuration from a file
/// Copies the configuration file to the app's config directory
/// </summary>
/// <param name="config"></param>
/// <param name="profileItem"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">Profile item with the file path in Address</param>
/// <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)
{
var fileName = profileItem.Address;
@ -517,11 +545,12 @@ public class ConfigHandler
}
/// <summary>
/// Add or edit server
/// Edit an existing custom server configuration
/// Updates the server's properties without changing the file
/// </summary>
/// <param name="config"></param>
/// <param name="profileItem"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">Profile item with updated properties</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> EditCustomServer(Config config, ProfileItem profileItem)
{
var item = await AppHandler.Instance.GetProfileItem(profileItem.IndexId);
@ -551,11 +580,13 @@ public class ConfigHandler
}
/// <summary>
/// Add or edit server
/// Add or edit a Shadowsocks server
/// Validates and processes Shadowsocks-specific settings
/// </summary>
/// <param name="config"></param>
/// <param name="profileItem"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">Shadowsocks profile to add</param>
/// <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)
{
profileItem.ConfigType = EConfigType.Shadowsocks;
@ -579,11 +610,13 @@ public class ConfigHandler
}
/// <summary>
/// Add or edit server
/// Add or edit a SOCKS server
/// Processes SOCKS-specific settings
/// </summary>
/// <param name="config"></param>
/// <param name="profileItem"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">SOCKS profile to add</param>
/// <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)
{
profileItem.ConfigType = EConfigType.SOCKS;
@ -596,11 +629,13 @@ public class ConfigHandler
}
/// <summary>
/// Add or edit server
/// Add or edit an HTTP server
/// Processes HTTP-specific settings
/// </summary>
/// <param name="config"></param>
/// <param name="profileItem"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">HTTP profile to add</param>
/// <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)
{
profileItem.ConfigType = EConfigType.HTTP;
@ -613,11 +648,13 @@ public class ConfigHandler
}
/// <summary>
/// Add or edit server
/// Add or edit a Trojan server
/// Validates and processes Trojan-specific settings
/// </summary>
/// <param name="config"></param>
/// <param name="profileItem"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">Trojan profile to add</param>
/// <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)
{
profileItem.ConfigType = EConfigType.Trojan;
@ -639,11 +676,14 @@ public class ConfigHandler
}
/// <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>
/// <param name="config"></param>
/// <param name="profileItem"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">Hysteria2 profile to add</param>
/// <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)
{
profileItem.ConfigType = EConfigType.Hysteria2;
@ -669,11 +709,14 @@ public class ConfigHandler
}
/// <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>
/// <param name="config"></param>
/// <param name="profileItem"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">TUIC profile to add</param>
/// <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)
{
profileItem.ConfigType = EConfigType.TUIC;
@ -708,15 +751,16 @@ public class ConfigHandler
}
/// <summary>
/// Add or edit server
/// Add or edit a WireGuard server
/// Validates and processes WireGuard-specific settings
/// </summary>
/// <param name="config"></param>
/// <param name="profileItem"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">WireGuard profile to add</param>
/// <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)
{
profileItem.ConfigType = EConfigType.WireGuard;
profileItem.CoreType = ECoreType.sing_box;
profileItem.Address = profileItem.Address.TrimEx();
profileItem.Id = profileItem.Id.TrimEx();
@ -739,6 +783,15 @@ public class ConfigHandler
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)
{
var lstModel = await AppHandler.Instance.ProfileItems(subId, "");
@ -832,11 +885,13 @@ public class ConfigHandler
}
/// <summary>
/// Add or edit server
/// Add or edit a VLESS server
/// Validates and processes VLESS-specific settings
/// </summary>
/// <param name="config"></param>
/// <param name="profileItem"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="profileItem">VLESS profile to add</param>
/// <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)
{
profileItem.ConfigType = EConfigType.VLESS;
@ -868,6 +923,13 @@ public class ConfigHandler
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)
{
var lstProfile = await AppHandler.Instance.ProfileItems(subId);
@ -899,6 +961,14 @@ public class ConfigHandler
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)
{
profileItem.ConfigVersion = 2;
@ -950,6 +1020,14 @@ public class ConfigHandler
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)
{
if (o == null || n == null)
@ -981,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)
{
try
@ -1005,6 +1090,15 @@ public class ConfigHandler
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)
{
var indexId = Utils.GetMd5(Global.CoreMultipleLoadConfigFileName);
@ -1023,14 +1117,21 @@ public class ConfigHandler
var profileItem = await AppHandler.Instance.GetProfileItem(indexId) ?? new();
profileItem.IndexId = indexId;
profileItem.Remarks = multipleLoad switch
if (coreType == ECoreType.Xray)
{
EMultipleLoad.Random => ResUI.menuSetDefaultMultipleServerXrayRandom,
EMultipleLoad.RoundRobin => ResUI.menuSetDefaultMultipleServerXrayRoundRobin,
EMultipleLoad.LeastPing => ResUI.menuSetDefaultMultipleServerXrayLeastPing,
EMultipleLoad.LeastLoad => ResUI.menuSetDefaultMultipleServerXrayLeastLoad,
_ => ResUI.menuSetDefaultMultipleServerXrayRoundRobin,
};
profileItem.Remarks = multipleLoad switch
{
EMultipleLoad.Random => ResUI.menuSetDefaultMultipleServerXrayRandom,
EMultipleLoad.RoundRobin => ResUI.menuSetDefaultMultipleServerXrayRoundRobin,
EMultipleLoad.LeastPing => ResUI.menuSetDefaultMultipleServerXrayLeastPing,
EMultipleLoad.LeastLoad => ResUI.menuSetDefaultMultipleServerXrayLeastLoad,
_ => ResUI.menuSetDefaultMultipleServerXrayRoundRobin,
};
}
else if (coreType == ECoreType.sing_box)
{
profileItem.Remarks = ResUI.menuSetDefaultMultipleServerSingBoxLeastPing;
}
profileItem.Address = Global.CoreMultipleLoadConfigFileName;
profileItem.ConfigType = EConfigType.Custom;
profileItem.CoreType = coreType;
@ -1041,6 +1142,14 @@ public class ConfigHandler
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)
{
ProfileItem? itemSocks = null;
@ -1070,6 +1179,13 @@ public class ConfigHandler
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)
{
var lstModel = await AppHandler.Instance.ProfileItems(subid, "");
@ -1093,12 +1209,14 @@ public class ConfigHandler
#region Batch add servers
/// <summary>
/// 批量添加服务器
/// Add multiple servers from string data (common protocols)
/// Parses the string data into server profiles
/// </summary>
/// <param name="config"></param>
/// <param name="strData"></param>
/// <param name="subid"></param>
/// <returns>成功导入的数量</returns>
/// <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> AddBatchServersCommon(Config config, string strData, string subid, bool isSub)
{
if (strData.IsNullOrEmpty())
@ -1178,6 +1296,15 @@ public class ConfigHandler
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)
{
if (strData.IsNullOrEmpty())
@ -1276,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)
{
if (strData.IsNullOrEmpty())
@ -1308,6 +1444,15 @@ public class ConfigHandler
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)
{
if (strData.IsNullOrEmpty())
@ -1380,11 +1525,12 @@ public class ConfigHandler
#region Sub & Group
/// <summary>
/// add sub
/// Add a subscription item from URL
/// Creates a new subscription with default settings
/// </summary>
/// <param name="config"></param>
/// <param name="url"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="url">Subscription URL</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddSubItem(Config config, string url)
{
//already exists
@ -1416,6 +1562,12 @@ public class ConfigHandler
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)
{
var item = await AppHandler.Instance.GetSubItem(subItem.Id);
@ -1467,11 +1619,12 @@ public class ConfigHandler
}
/// <summary>
/// 移除服务器
/// Remove servers associated with a subscription ID
/// </summary>
/// <param name="config"></param>
/// <param name="subid"></param>
/// <returns></returns>
/// <param name="config">Current configuration</param>
/// <param name="subid">Subscription ID</param>
/// <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)
{
if (subid.IsNullOrEmpty())
@ -1495,6 +1648,12 @@ public class ConfigHandler
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)
{
var item = await AppHandler.Instance.GetSubItem(id);
@ -1508,6 +1667,13 @@ public class ConfigHandler
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)
{
foreach (var item in lstProfile)
@ -1523,6 +1689,12 @@ public class ConfigHandler
#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)
{
if (item.Id.IsNullOrEmpty())
@ -1541,11 +1713,11 @@ public class ConfigHandler
}
/// <summary>
/// AddBatchRoutingRules
/// Add multiple routing rules to a routing item
/// </summary>
/// <param name="config"></param>
/// <param name="strData"></param>
/// <returns></returns>
/// <param name="routingItem">Routing item to add rules to</param>
/// <param name="strData">JSON string containing rules data</param>
/// <returns>0 if successful, -1 if failed</returns>
public static async Task<int> AddBatchRoutingRules(RoutingItem routingItem, string strData)
{
if (strData.IsNullOrEmpty())
@ -1582,12 +1754,14 @@ public class ConfigHandler
}
/// <summary>
/// MoveRoutingRule
/// Move a routing rule within a rules list
/// Supports moving to top, up, down, bottom or specific position
/// </summary>
/// <param name="routingItem"></param>
/// <param name="index"></param>
/// <param name="eMove"></param>
/// <returns></returns>
/// <param name="rules">List of routing rules</param>
/// <param name="index">Index of the rule to move</param>
/// <param name="eMove">Direction to move the rule</param>
/// <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)
{
int count = rules.Count;
@ -1658,6 +1832,12 @@ public class ConfigHandler
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)
{
if (await SQLiteHelper.Instance.TableAsync<RoutingItem>().Where(t => t.Id == routingItem.Id).CountAsync() > 0)
@ -1670,6 +1850,12 @@ public class ConfigHandler
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)
{
var item = await AppHandler.Instance.GetRoutingItem(config.RoutingBasicItem.RoutingIndexId);
@ -1683,6 +1869,12 @@ public class ConfigHandler
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)
{
if (config.ConstItem.RouteRulesTemplateSourceUrl.IsNullOrEmpty())
@ -1697,6 +1889,13 @@ public class ConfigHandler
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)
{
var downloadHandle = new DownloadService();
@ -1745,6 +1944,13 @@ public class ConfigHandler
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)
{
var ver = "V3-";
@ -1798,6 +2004,10 @@ public class ConfigHandler
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)
{
await SQLiteHelper.Instance.DeleteAsync(routingItem);
@ -1807,6 +2017,12 @@ public class ConfigHandler
#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)
{
var items = await AppHandler.Instance.DNSItems();
@ -1830,6 +2046,12 @@ public class ConfigHandler
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)
{
if (item == null)
@ -1852,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)
{
var currentItem = await AppHandler.Instance.GetDNSItem(type);
@ -1883,6 +2112,13 @@ public class ConfigHandler
#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)
{
switch (type)

View file

@ -101,7 +101,7 @@ public class CoreHandler
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
{
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray;
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC) ? ECoreType.sing_box : ECoreType.Xray;
var fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false));
var configPath = Utils.GetBinConfigPath(fileName);
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);

View file

@ -8,10 +8,13 @@ public class BaseFmt
{
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; // 如果不是IPv6地址直接返回原地址
else
{
return address;
}
}
protected static int GetStdTransport(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery)

View file

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

View file

@ -127,6 +127,26 @@ public class Outboundsettings4Ray
public int? userLevel { get; set; }
public FragmentItem4Ray? fragment { get; set; }
public string? secretKey { get; set; }
public List<string>? address { get; set; }
public List<WireguardPeer4Ray>? peers { get; set; }
public bool? noKernelTun { get; set; }
public int? mtu { get; set; }
public List<int>? reserved { get; set; }
public int? workers { get; set; }
}
public class WireguardPeer4Ray
{
public string endpoint { get; set; }
public string publicKey { get; set; }
}
public class VnextItem4Ray

View file

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

View file

@ -88,7 +88,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Please check the server settings first. 的本地化字符串。
/// 查找类似 Please check the Configuration settings first. 的本地化字符串。
/// </summary>
public static string CheckServerSettings {
get {
@ -178,7 +178,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Failed to import custom configuration server 的本地化字符串。
/// 查找类似 Failed to import custom configuration Configuration 的本地化字符串。
/// </summary>
public static string FailedImportedCustomServer {
get {
@ -214,7 +214,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Please enter the correct server port format. 的本地化字符串。
/// 查找类似 Please enter the correct port format. 的本地化字符串。
/// </summary>
public static string FillCorrectServerPort {
get {
@ -241,7 +241,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Please enter the server address. 的本地化字符串。
/// 查找类似 Please enter the address. 的本地化字符串。
/// </summary>
public static string FillServerAddress {
get {
@ -250,7 +250,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Please browse to import server configuration 的本地化字符串。
/// 查找类似 Please browse to import Configuration configuration 的本地化字符串。
/// </summary>
public static string FillServerAddressCustom {
get {
@ -466,7 +466,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Next proxy remarks 的本地化字符串。
/// 查找类似 Next proxy Configuration remarks 的本地化字符串。
/// </summary>
public static string LvNextProfile {
get {
@ -484,7 +484,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Previous proxy remarks 的本地化字符串。
/// 查找类似 Previous proxy Configuration remarks 的本地化字符串。
/// </summary>
public static string LvPrevProfile {
get {
@ -493,7 +493,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Please make sure the remarks exist and are unique 的本地化字符串。
/// 查找类似 Please make sure the Configuration remarks exist and are unique 的本地化字符串。
/// </summary>
public static string LvPrevProfileTip {
get {
@ -673,7 +673,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add a custom configuration server 的本地化字符串。
/// 查找类似 Add a custom configuration Configuration 的本地化字符串。
/// </summary>
public static string menuAddCustomServer {
get {
@ -682,7 +682,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [HTTP] server 的本地化字符串。
/// 查找类似 Add [HTTP] Configuration 的本地化字符串。
/// </summary>
public static string menuAddHttpServer {
get {
@ -691,7 +691,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [Hysteria2] server 的本地化字符串。
/// 查找类似 Add [Hysteria2] Configuration 的本地化字符串。
/// </summary>
public static string menuAddHysteria2Server {
get {
@ -727,7 +727,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [Shadowsocks] server 的本地化字符串。
/// 查找类似 Add [Shadowsocks] Configuration 的本地化字符串。
/// </summary>
public static string menuAddShadowsocksServer {
get {
@ -736,7 +736,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [SOCKS] server 的本地化字符串。
/// 查找类似 Add [SOCKS] Configuration 的本地化字符串。
/// </summary>
public static string menuAddSocksServer {
get {
@ -745,7 +745,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [Trojan] server 的本地化字符串。
/// 查找类似 Add [Trojan] Configuration 的本地化字符串。
/// </summary>
public static string menuAddTrojanServer {
get {
@ -754,7 +754,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [TUIC] server 的本地化字符串。
/// 查找类似 Add [TUIC] Configuration 的本地化字符串。
/// </summary>
public static string menuAddTuicServer {
get {
@ -763,7 +763,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [VLESS] server 的本地化字符串。
/// 查找类似 Add [VLESS] Configuration 的本地化字符串。
/// </summary>
public static string menuAddVlessServer {
get {
@ -772,7 +772,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [VMess] server 的本地化字符串。
/// 查找类似 Add [VMess] Configuration 的本地化字符串。
/// </summary>
public static string menuAddVmessServer {
get {
@ -781,7 +781,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Add [WireGuard] server 的本地化字符串。
/// 查找类似 Add [WireGuard] Configuration 的本地化字符串。
/// </summary>
public static string menuAddWireguardServer {
get {
@ -853,7 +853,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Clone selected server 的本地化字符串。
/// 查找类似 Clone selected Configuration 的本地化字符串。
/// </summary>
public static string menuCopyServer {
get {
@ -871,7 +871,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Edit Server (Ctrl+D) 的本地化字符串。
/// 查找类似 Edit Configuration (Ctrl+D) 的本地化字符串。
/// </summary>
public static string menuEditServer {
get {
@ -898,7 +898,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Export selected server for complete configuration 的本地化字符串。
/// 查找类似 Export selected Configuration for complete configuration 的本地化字符串。
/// </summary>
public static string menuExport2ClientConfig {
get {
@ -907,7 +907,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Export selected server for complete configuration to clipboard 的本地化字符串。
/// 查找类似 Export selected Configuration for complete configuration to clipboard 的本地化字符串。
/// </summary>
public static string menuExport2ClientConfigClipboard {
get {
@ -934,7 +934,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Export server 的本地化字符串。
/// 查找类似 Export Configuration 的本地化字符串。
/// </summary>
public static string menuExportConfig {
get {
@ -1222,7 +1222,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Test servers real delay (Ctrl+R) 的本地化字符串。
/// 查找类似 Test Configurations real delay (Ctrl+R) 的本地化字符串。
/// </summary>
public static string menuRealPingServer {
get {
@ -1312,7 +1312,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Remove duplicate servers 的本地化字符串。
/// 查找类似 Remove duplicate Configurations 的本地化字符串。
/// </summary>
public static string menuRemoveDuplicateServer {
get {
@ -1330,7 +1330,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Remove selected servers (Delete) 的本地化字符串。
/// 查找类似 Remove selected Configurations (Delete) 的本地化字符串。
/// </summary>
public static string menuRemoveServer {
get {
@ -1474,7 +1474,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Servers 的本地化字符串。
/// 查找类似 Configurations 的本地化字符串。
/// </summary>
public static string menuServers {
get {
@ -1483,7 +1483,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Multi-server to custom configuration 的本地化字符串。
/// 查找类似 Multi-Configuration to custom configuration 的本地化字符串。
/// </summary>
public static string menuSetDefaultMultipleServer {
get {
@ -1492,7 +1492,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Multi-server LeastPing by sing-box 的本地化字符串。
/// 查找类似 Multi-Configuration LeastPing by sing-box 的本地化字符串。
/// </summary>
public static string menuSetDefaultMultipleServerSingBoxLeastPing {
get {
@ -1501,7 +1501,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Multi-server LeastLoad by Xray 的本地化字符串。
/// 查找类似 Multi-Configuration LeastLoad by Xray 的本地化字符串。
/// </summary>
public static string menuSetDefaultMultipleServerXrayLeastLoad {
get {
@ -1510,7 +1510,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Multi-server LeastPing by Xray 的本地化字符串。
/// 查找类似 Multi-Configuration LeastPing by Xray 的本地化字符串。
/// </summary>
public static string menuSetDefaultMultipleServerXrayLeastPing {
get {
@ -1519,7 +1519,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Multi-server Random by Xray 的本地化字符串。
/// 查找类似 Multi-Configuration Random by Xray 的本地化字符串。
/// </summary>
public static string menuSetDefaultMultipleServerXrayRandom {
get {
@ -1528,7 +1528,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Multi-server RoundRobin by Xray 的本地化字符串。
/// 查找类似 Multi-Configuration RoundRobin by Xray 的本地化字符串。
/// </summary>
public static string menuSetDefaultMultipleServerXrayRoundRobin {
get {
@ -1537,7 +1537,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Set as active server (Enter) 的本地化字符串。
/// 查找类似 Set as active Configuration (Enter) 的本地化字符串。
/// </summary>
public static string menuSetDefaultServer {
get {
@ -1555,7 +1555,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Share Server (Ctrl+F) 的本地化字符串。
/// 查找类似 Share Configuration (Ctrl+F) 的本地化字符串。
/// </summary>
public static string menuShareServer {
get {
@ -1582,7 +1582,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Test servers download speed (Ctrl+T) 的本地化字符串。
/// 查找类似 Test Configurations download speed (Ctrl+T) 的本地化字符串。
/// </summary>
public static string menuSpeedServer {
get {
@ -1726,7 +1726,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Test servers with tcping (Ctrl+O) 的本地化字符串。
/// 查找类似 Test Configurations with tcping (Ctrl+O) 的本地化字符串。
/// </summary>
public static string menuTcpingServer {
get {
@ -1834,7 +1834,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Server filter, press Enter to execute 的本地化字符串。
/// 查找类似 Configuration filter, press Enter to execute 的本地化字符串。
/// </summary>
public static string MsgServerTitle {
get {
@ -2023,7 +2023,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Please select the server first 的本地化字符串。
/// 查找类似 Please select the Configuration first 的本地化字符串。
/// </summary>
public static string PleaseSelectServer {
get {
@ -2050,7 +2050,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Servers deduplication completed. Old: {0}, New: {1}. 的本地化字符串。
/// 查找类似 Configurations deduplication completed. Old: {0}, New: {1}. 的本地化字符串。
/// </summary>
public static string RemoveDuplicateServerResult {
get {
@ -2077,7 +2077,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Are you sure you want to remove the server? 的本地化字符串。
/// 查找类似 Are you sure you want to remove the Configuration? 的本地化字符串。
/// </summary>
public static string RemoveServer {
get {
@ -2203,7 +2203,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Custom configuration server imported successfully 的本地化字符串。
/// 查找类似 Custom configuration Configuration imported successfully 的本地化字符串。
/// </summary>
public static string SuccessfullyImportedCustomServer {
get {
@ -2212,7 +2212,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 {0} servers have been imported from clipboard 的本地化字符串。
/// 查找类似 {0} Configurations have been imported from clipboard 的本地化字符串。
/// </summary>
public static string SuccessfullyImportedServerViaClipboard {
get {
@ -2581,7 +2581,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Server port range 的本地化字符串。
/// 查找类似 Configuration port range 的本地化字符串。
/// </summary>
public static string TbPorts7 {
get {
@ -3040,7 +3040,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Double-clicking server makes it active 的本地化字符串。
/// 查找类似 Double-clicking Configuration makes it active 的本地化字符串。
/// </summary>
public static string TbSettingsDoubleClick2Activate {
get {
@ -3076,7 +3076,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Enable sorting servers by drag-n-drop (requires restart) 的本地化字符串。
/// 查找类似 Enable sorting Configurations by drag-n-drop (requires restart) 的本地化字符串。
/// </summary>
public static string TbSettingsEnableDragDropSort {
get {
@ -3526,7 +3526,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Tray right-click menu servers display limit 的本地化字符串。
/// 查找类似 Tray right-click menu Configurations display limit 的本地化字符串。
/// </summary>
public static string TbSettingsTrayMenuServersLimit {
get {

View file

@ -121,7 +121,7 @@
<value>Export share link to clipboard successfully</value>
</data>
<data name="CheckServerSettings" xml:space="preserve">
<value>Please check the server settings first.</value>
<value>Please check the Configuration settings first.</value>
</data>
<data name="ConfigurationFormatIncorrect" xml:space="preserve">
<value>Invalid configuration format.</value>
@ -148,13 +148,13 @@
<value>Failed to get the default configuration</value>
</data>
<data name="FailedImportedCustomServer" xml:space="preserve">
<value>Failed to import custom configuration server</value>
<value>Failed to import custom configuration Configuration</value>
</data>
<data name="FailedReadConfiguration" xml:space="preserve">
<value>Failed to read configuration file</value>
</data>
<data name="FillCorrectServerPort" xml:space="preserve">
<value>Please enter the correct server port format.</value>
<value>Please enter the correct port format.</value>
</data>
<data name="FillLocalListeningPort" xml:space="preserve">
<value>Please enter the local listening port.</value>
@ -163,7 +163,7 @@
<value>Please enter the password.</value>
</data>
<data name="FillServerAddress" xml:space="preserve">
<value>Please enter the server address.</value>
<value>Please enter the address.</value>
</data>
<data name="FillUUID" xml:space="preserve">
<value>Please enter the user ID.</value>
@ -271,13 +271,13 @@
<value>Please select a protocol</value>
</data>
<data name="PleaseSelectServer" xml:space="preserve">
<value>Please select the server first</value>
<value>Please select the Configuration first</value>
</data>
<data name="RemoveDuplicateServerResult" xml:space="preserve">
<value>Servers deduplication completed. Old: {0}, New: {1}.</value>
<value>Configurations deduplication completed. Old: {0}, New: {1}.</value>
</data>
<data name="RemoveServer" xml:space="preserve">
<value>Are you sure you want to remove the server?</value>
<value>Are you sure you want to remove the Configuration?</value>
</data>
<data name="SaveClientConfigurationIn" xml:space="preserve">
<value>The client configuration file is saved at: {0}</value>
@ -289,10 +289,10 @@
<value>Configuration successful. {0}</value>
</data>
<data name="SuccessfullyImportedCustomServer" xml:space="preserve">
<value>Custom configuration server imported successfully</value>
<value>Custom configuration Configuration imported successfully</value>
</data>
<data name="SuccessfullyImportedServerViaClipboard" xml:space="preserve">
<value>{0} servers have been imported from clipboard</value>
<value>{0} Configurations have been imported from clipboard</value>
</data>
<data name="SuccessfullyImportedServerViaScan" xml:space="preserve">
<value>Successfully scanned and imported the shared link</value>
@ -394,7 +394,7 @@
<value>All</value>
</data>
<data name="FillServerAddressCustom" xml:space="preserve">
<value>Please browse to import server configuration</value>
<value>Please browse to import Configuration configuration</value>
</data>
<data name="Speedtesting" xml:space="preserve">
<value>Testing...</value>
@ -406,7 +406,7 @@
<value>Local</value>
</data>
<data name="MsgServerTitle" xml:space="preserve">
<value>Server filter, press Enter to execute</value>
<value>Configuration filter, press Enter to execute</value>
</data>
<data name="menuCheckUpdate" xml:space="preserve">
<value>Check Update</value>
@ -436,7 +436,7 @@
<value>Routing Setting</value>
</data>
<data name="menuServers" xml:space="preserve">
<value>Servers</value>
<value>Configurations</value>
</data>
<data name="menuSetting" xml:space="preserve">
<value>Settings</value>
@ -487,55 +487,55 @@
<value>Scan QR code on the screen (Ctrl+S)</value>
</data>
<data name="menuCopyServer" xml:space="preserve">
<value>Clone selected server</value>
<value>Clone selected Configuration</value>
</data>
<data name="menuRemoveDuplicateServer" xml:space="preserve">
<value>Remove duplicate servers</value>
<value>Remove duplicate Configurations</value>
</data>
<data name="menuRemoveServer" xml:space="preserve">
<value>Remove selected servers (Delete)</value>
<value>Remove selected Configurations (Delete)</value>
</data>
<data name="menuSetDefaultServer" xml:space="preserve">
<value>Set as active server (Enter)</value>
<value>Set as active Configuration (Enter)</value>
</data>
<data name="menuClearServerStatistics" xml:space="preserve">
<value>Clear all service statistics</value>
</data>
<data name="menuRealPingServer" xml:space="preserve">
<value>Test servers real delay (Ctrl+R)</value>
<value>Test Configurations real delay (Ctrl+R)</value>
</data>
<data name="menuSortServerResult" xml:space="preserve">
<value>Sort by test result</value>
</data>
<data name="menuSpeedServer" xml:space="preserve">
<value>Test servers download speed (Ctrl+T)</value>
<value>Test Configurations download speed (Ctrl+T)</value>
</data>
<data name="menuTcpingServer" xml:space="preserve">
<value>Test servers with tcping (Ctrl+O)</value>
<value>Test Configurations with tcping (Ctrl+O)</value>
</data>
<data name="menuExport2ClientConfig" xml:space="preserve">
<value>Export selected server for complete configuration</value>
<value>Export selected Configuration for complete configuration</value>
</data>
<data name="menuExport2ShareUrl" xml:space="preserve">
<value>Export Share Link to Clipboard (Ctrl+C)</value>
</data>
<data name="menuAddCustomServer" xml:space="preserve">
<value>Add a custom configuration server</value>
<value>Add a custom configuration Configuration</value>
</data>
<data name="menuAddShadowsocksServer" xml:space="preserve">
<value>Add [Shadowsocks] server</value>
<value>Add [Shadowsocks] Configuration</value>
</data>
<data name="menuAddSocksServer" xml:space="preserve">
<value>Add [SOCKS] server</value>
<value>Add [SOCKS] Configuration</value>
</data>
<data name="menuAddTrojanServer" xml:space="preserve">
<value>Add [Trojan] server</value>
<value>Add [Trojan] Configuration</value>
</data>
<data name="menuAddVlessServer" xml:space="preserve">
<value>Add [VLESS] server</value>
<value>Add [VLESS] Configuration</value>
</data>
<data name="menuAddVmessServer" xml:space="preserve">
<value>Add [VMess] server</value>
<value>Add [VMess] Configuration</value>
</data>
<data name="menuSelectAll" xml:space="preserve">
<value>Select all (Ctrl+A)</value>
@ -760,7 +760,7 @@
<value>Enable Security Protocol TLS v1.3 (subscription/update)</value>
</data>
<data name="TbSettingsTrayMenuServersLimit" xml:space="preserve">
<value>Tray right-click menu servers display limit</value>
<value>Tray right-click menu Configurations display limit</value>
</data>
<data name="TbSettingsUdpEnabled" xml:space="preserve">
<value>Enable UDP</value>
@ -793,7 +793,7 @@
<value>PAC mode</value>
</data>
<data name="menuShareServer" xml:space="preserve">
<value>Share Server (Ctrl+F)</value>
<value>Share Configuration (Ctrl+F)</value>
</data>
<data name="menuRouting" xml:space="preserve">
<value>Routing</value>
@ -940,7 +940,7 @@
<value>Move to group</value>
</data>
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
<value>Enable sorting servers by drag-n-drop (requires restart)</value>
<value>Enable sorting Configurations by drag-n-drop (requires restart)</value>
</data>
<data name="TbAutoRefresh" xml:space="preserve">
<value>Auto refresh</value>
@ -949,10 +949,10 @@
<value>Skip test</value>
</data>
<data name="menuEditServer" xml:space="preserve">
<value>Edit Server (Ctrl+D)</value>
<value>Edit Configuration (Ctrl+D)</value>
</data>
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
<value>Double-clicking server makes it active</value>
<value>Double-clicking Configuration makes it active</value>
</data>
<data name="SpeedtestingCompleted" xml:space="preserve">
<value>Test completed</value>
@ -1060,7 +1060,7 @@
<value>Domain</value>
</data>
<data name="menuAddHysteria2Server" xml:space="preserve">
<value>Add [Hysteria2] server</value>
<value>Add [Hysteria2] Configuration</value>
</data>
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
<value>Hysteria Max bandwidth (Up/Down)</value>
@ -1069,19 +1069,19 @@
<value>Use System Hosts</value>
</data>
<data name="menuAddTuicServer" xml:space="preserve">
<value>Add [TUIC] server</value>
<value>Add [TUIC] Configuration</value>
</data>
<data name="TbHeaderType8" xml:space="preserve">
<value>Congestion control</value>
</data>
<data name="LvPrevProfile" xml:space="preserve">
<value>Previous proxy remarks</value>
<value>Previous proxy Configuration remarks</value>
</data>
<data name="LvNextProfile" xml:space="preserve">
<value>Next proxy remarks</value>
<value>Next proxy Configuration remarks</value>
</data>
<data name="LvPrevProfileTip" xml:space="preserve">
<value>Please make sure the remarks exist and are unique</value>
<value>Please make sure the Configuration remarks exist and are unique</value>
</data>
<data name="TbSettingsEnableExInbound" xml:space="preserve">
<value>Enable additional Inbound</value>
@ -1090,7 +1090,7 @@
<value>Enable IPv6 Address</value>
</data>
<data name="menuAddWireguardServer" xml:space="preserve">
<value>Add [WireGuard] server</value>
<value>Add [WireGuard] Configuration</value>
</data>
<data name="TbPrivateKey" xml:space="preserve">
<value>Private Key</value>
@ -1123,7 +1123,7 @@
<value>*grpc Authority</value>
</data>
<data name="menuAddHttpServer" xml:space="preserve">
<value>Add [HTTP] server</value>
<value>Add [HTTP] Configuration</value>
</data>
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
<value>Use Xray and enable non-Tun mode, which conflicts with the group previous proxy</value>
@ -1237,7 +1237,7 @@
<value>Export Base64-encoded Share Links to Clipboard</value>
</data>
<data name="menuExport2ClientConfigClipboard" xml:space="preserve">
<value>Export selected server for complete configuration to clipboard</value>
<value>Export selected Configuration for complete configuration to clipboard</value>
</data>
<data name="menuShowOrHideMainWindow" xml:space="preserve">
<value>Show or hide the main window</value>
@ -1390,30 +1390,30 @@
<value>Removed {0} invalid test results.</value>
</data>
<data name="TbPorts7" xml:space="preserve">
<value>Server port range</value>
<value>Configuration port range</value>
</data>
<data name="TbPorts7Tips" xml:space="preserve">
<value>Will cover the port, separate with commas (,)</value>
</data>
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
<value>Multi-server to custom configuration</value>
<value>Multi-Configuration to custom configuration</value>
</data>
<data name="menuSetDefaultMultipleServerXrayRandom" xml:space="preserve">
<value>Multi-server Random by Xray</value>
<value>Multi-Configuration Random by Xray</value>
</data>
<data name="menuSetDefaultMultipleServerXrayRoundRobin" xml:space="preserve">
<value>Multi-server RoundRobin by Xray</value>
<value>Multi-Configuration RoundRobin by Xray</value>
</data>
<data name="menuSetDefaultMultipleServerXrayLeastPing" xml:space="preserve">
<value>Multi-server LeastPing by Xray</value>
<value>Multi-Configuration LeastPing by Xray</value>
</data>
<data name="menuSetDefaultMultipleServerXrayLeastLoad" xml:space="preserve">
<value>Multi-server LeastLoad by Xray</value>
<value>Multi-Configuration LeastLoad by Xray</value>
</data>
<data name="menuSetDefaultMultipleServerSingBoxLeastPing" xml:space="preserve">
<value>Multi-server LeastPing by sing-box</value>
<value>Multi-Configuration LeastPing by sing-box</value>
</data>
<data name="menuExportConfig" xml:space="preserve">
<value>Export server</value>
<value>Export Configuration</value>
</data>
</root>

View file

@ -121,7 +121,7 @@
<value>导出分享链接至剪贴板成功</value>
</data>
<data name="CheckServerSettings" xml:space="preserve">
<value>请先检查服务器设置</value>
<value>请先检查配置文件设置</value>
</data>
<data name="ConfigurationFormatIncorrect" xml:space="preserve">
<value>配置格式不正确</value>
@ -148,13 +148,13 @@
<value>获取默认配置失败</value>
</data>
<data name="FailedImportedCustomServer" xml:space="preserve">
<value>导入自定义配置服务器失败</value>
<value>导入自定义配置文件失败</value>
</data>
<data name="FailedReadConfiguration" xml:space="preserve">
<value>读取配置文件失败</value>
</data>
<data name="FillCorrectServerPort" xml:space="preserve">
<value>请填写正确格式的服务器端口</value>
<value>请填写正确格式的端口</value>
</data>
<data name="FillLocalListeningPort" xml:space="preserve">
<value>请填写本地监听端口</value>
@ -163,7 +163,7 @@
<value>请填写密码</value>
</data>
<data name="FillServerAddress" xml:space="preserve">
<value>请填写服务器地址</value>
<value>请填写地址</value>
</data>
<data name="FillUUID" xml:space="preserve">
<value>请填写用户 ID</value>
@ -271,13 +271,13 @@
<value>请选择协议</value>
</data>
<data name="PleaseSelectServer" xml:space="preserve">
<value>请先选择服务器</value>
<value>请先选择配置文件</value>
</data>
<data name="RemoveDuplicateServerResult" xml:space="preserve">
<value>服务器去重完成。原数量: {0},现数量: {1}。</value>
<value>配置文件去重完成。原数量: {0},现数量: {1}。</value>
</data>
<data name="RemoveServer" xml:space="preserve">
<value>是否确定移除服务器</value>
<value>是否确定移除配置文件</value>
</data>
<data name="SaveClientConfigurationIn" xml:space="preserve">
<value>客户端配置文件保存在:{0}</value>
@ -289,10 +289,10 @@
<value>配置成功。 {0}</value>
</data>
<data name="SuccessfullyImportedCustomServer" xml:space="preserve">
<value>成功导入自定义配置服务器</value>
<value>成功导入自定义配置文件</value>
</data>
<data name="SuccessfullyImportedServerViaClipboard" xml:space="preserve">
<value>成功从剪贴板导入 {0} 个服务器</value>
<value>成功从剪贴板导入 {0} 个配置文件</value>
</data>
<data name="SuccessfullyImportedServerViaScan" xml:space="preserve">
<value>扫描导入分享链接成功</value>
@ -388,13 +388,13 @@
<value>注册全局热键 {0} 成功</value>
</data>
<data name="UngroupedServers" xml:space="preserve">
<value>未分组服务器</value>
<value>未分组配置文件</value>
</data>
<data name="AllGroupServers" xml:space="preserve">
<value>所有</value>
</data>
<data name="FillServerAddressCustom" xml:space="preserve">
<value>请浏览导入服务器配置</value>
<value>请浏览导入配置文件配置</value>
</data>
<data name="Speedtesting" xml:space="preserve">
<value>测试中...</value>
@ -406,7 +406,7 @@
<value>本地</value>
</data>
<data name="MsgServerTitle" xml:space="preserve">
<value>服务器过滤器,按回车执行</value>
<value>配置文件过滤器,按回车执行</value>
</data>
<data name="menuCheckUpdate" xml:space="preserve">
<value>检查更新</value>
@ -436,7 +436,7 @@
<value>路由设置</value>
</data>
<data name="menuServers" xml:space="preserve">
<value>服务器</value>
<value>配置文件</value>
</data>
<data name="menuSetting" xml:space="preserve">
<value>设置</value>
@ -487,55 +487,55 @@
<value>扫描屏幕上的二维码 (Ctrl+S)</value>
</data>
<data name="menuCopyServer" xml:space="preserve">
<value>克隆所选服务器</value>
<value>克隆所选配置文件</value>
</data>
<data name="menuRemoveDuplicateServer" xml:space="preserve">
<value>移除重复的服务器</value>
<value>移除重复的配置文件</value>
</data>
<data name="menuRemoveServer" xml:space="preserve">
<value>移除所选服务器 (多选) (Delete)</value>
<value>移除所选配置文件 (多选) (Delete)</value>
</data>
<data name="menuSetDefaultServer" xml:space="preserve">
<value>设为活动服务器 (Enter)</value>
<value>设为活动配置文件 (Enter)</value>
</data>
<data name="menuClearServerStatistics" xml:space="preserve">
<value>清除所有服务统计数据</value>
</data>
<data name="menuRealPingServer" xml:space="preserve">
<value>测试服务器真连接延迟 (多选) (Ctrl+R)</value>
<value>测试配置文件真连接延迟 (多选) (Ctrl+R)</value>
</data>
<data name="menuSortServerResult" xml:space="preserve">
<value>按测试结果排序</value>
</data>
<data name="menuSpeedServer" xml:space="preserve">
<value>测试服务器速度 (多选) (Ctrl+T)</value>
<value>测试配置文件速度 (多选) (Ctrl+T)</value>
</data>
<data name="menuTcpingServer" xml:space="preserve">
<value>测试服务器延迟 Tcping (多选) (Ctrl+O)</value>
<value>测试配置文件延迟 Tcping (多选) (Ctrl+O)</value>
</data>
<data name="menuExport2ClientConfig" xml:space="preserve">
<value>导出所选服务器完整配置</value>
<value>导出所选配置文件完整配置</value>
</data>
<data name="menuExport2ShareUrl" xml:space="preserve">
<value>导出分享链接至剪贴板 (多选) (Ctrl+C)</value>
</data>
<data name="menuAddCustomServer" xml:space="preserve">
<value>添加自定义配置服务器</value>
<value>添加自定义配置文件</value>
</data>
<data name="menuAddShadowsocksServer" xml:space="preserve">
<value>添加 [Shadowsocks] 服务器</value>
<value>添加 [Shadowsocks] 配置文件</value>
</data>
<data name="menuAddSocksServer" xml:space="preserve">
<value>添加 [SOCKS] 服务器</value>
<value>添加 [SOCKS] 配置文件</value>
</data>
<data name="menuAddTrojanServer" xml:space="preserve">
<value>添加 [Trojan] 服务器</value>
<value>添加 [Trojan] 配置文件</value>
</data>
<data name="menuAddVlessServer" xml:space="preserve">
<value>添加 [VLESS] 服务器</value>
<value>添加 [VLESS] 配置文件</value>
</data>
<data name="menuAddVmessServer" xml:space="preserve">
<value>添加 [VMess] 服务器</value>
<value>添加 [VMess] 配置文件</value>
</data>
<data name="menuSelectAll" xml:space="preserve">
<value>全选 (Ctrl+A)</value>
@ -700,7 +700,7 @@
<value>Outbound Freedom domainStrategy</value>
</data>
<data name="TbSettingsEnableAutoAdjustMainLvColWidth" xml:space="preserve">
<value>自动调整服务器列宽在更新订阅后</value>
<value>自动调整配置文件列宽在更新订阅后</value>
</data>
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
<value>检查 Pre-Release 更新 (请谨慎启用)</value>
@ -760,7 +760,7 @@
<value>启用安全协议 TLS v1.3 (订阅/检查更新)</value>
</data>
<data name="TbSettingsTrayMenuServersLimit" xml:space="preserve">
<value>托盘右键菜单服务器展示数量限制</value>
<value>托盘右键菜单配置文件展示数量限制</value>
</data>
<data name="TbSettingsUdpEnabled" xml:space="preserve">
<value>开启 UDP</value>
@ -793,7 +793,7 @@
<value>Pac 模式</value>
</data>
<data name="menuShareServer" xml:space="preserve">
<value>分享服务器 (Ctrl+F)</value>
<value>分享配置文件 (Ctrl+F)</value>
</data>
<data name="menuRouting" xml:space="preserve">
<value>路由</value>
@ -940,7 +940,7 @@
<value>移至订阅分组</value>
</data>
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
<value>启用服务器拖放排序(需重启)</value>
<value>启用配置文件拖放排序(需重启)</value>
</data>
<data name="TbAutoRefresh" xml:space="preserve">
<value>自动刷新</value>
@ -949,10 +949,10 @@
<value>跳过测试</value>
</data>
<data name="menuEditServer" xml:space="preserve">
<value>编辑服务器 (Ctrl+D)</value>
<value>编辑配置文件 (Ctrl+D)</value>
</data>
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
<value>主界面双击设为活动服务器</value>
<value>主界面双击设为活动配置文件</value>
</data>
<data name="SpeedtestingCompleted" xml:space="preserve">
<value>测试完成</value>
@ -1057,7 +1057,7 @@
<value>Domain</value>
</data>
<data name="menuAddHysteria2Server" xml:space="preserve">
<value>添加 [Hysteria2] 服务器</value>
<value>添加 [Hysteria2] 配置文件</value>
</data>
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
<value>Hysteria 最大带宽 (Up/Dw)</value>
@ -1066,19 +1066,19 @@
<value>使用系统 hosts</value>
</data>
<data name="menuAddTuicServer" xml:space="preserve">
<value>添加 [TUIC] 服务器</value>
<value>添加 [TUIC] 配置文件</value>
</data>
<data name="TbHeaderType8" xml:space="preserve">
<value>拥塞控制算法</value>
</data>
<data name="LvPrevProfile" xml:space="preserve">
<value>前置代理别名</value>
<data name="LvPrevProfile" xml:space="preserve">
<value>前置代理配置文件别名</value>
</data>
<data name="LvNextProfile" xml:space="preserve">
<value>落地代理別名</value>
<data name="LvNextProfile" xml:space="preserve">
<value>落地代理配置文件別名</value>
</data>
<data name="LvPrevProfileTip" xml:space="preserve">
<value>请确保别名存在并唯一</value>
<data name="LvPrevProfileTip" xml:space="preserve">
<value>请确保配置文件别名存在并唯一</value>
</data>
<data name="TbSettingsEnableExInbound" xml:space="preserve">
<value>启用额外监听端口</value>
@ -1087,7 +1087,7 @@
<value>启用 IPv6</value>
</data>
<data name="menuAddWireguardServer" xml:space="preserve">
<value>添加 [WireGuard] 服务器</value>
<value>添加 [WireGuard] 配置文件</value>
</data>
<data name="TbPrivateKey" xml:space="preserve">
<value>PrivateKey</value>
@ -1120,7 +1120,7 @@
<value>*grpc Authority</value>
</data>
<data name="menuAddHttpServer" xml:space="preserve">
<value>添加 [HTTP] 服务器</value>
<value>添加 [HTTP] 配置文件</value>
</data>
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
<value>使用 Xray 且非 Tun 模式启用,和分组前置代理冲突</value>
@ -1234,7 +1234,7 @@
<value>导出分享链接至剪贴板 (多选) Base64 编码</value>
</data>
<data name="menuExport2ClientConfigClipboard" xml:space="preserve">
<value>导出所选服务器完整配置至剪贴板</value>
<value>导出所选配置文件完整配置至剪贴板</value>
</data>
<data name="menuShowOrHideMainWindow" xml:space="preserve">
<value>显示或隐藏主界面</value>
@ -1393,24 +1393,24 @@
<value>会覆盖端口,多组时用逗号 (,) 隔开</value>
</data>
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
<value>多服务器产生自定义配置 (多选)</value>
<value>多配置文件产生自定义配置 (多选)</value>
</data>
<data name="menuSetDefaultMultipleServerXrayRandom" xml:space="preserve">
<value>多服务器随机 Xray</value>
<value>多配置文件随机 Xray</value>
</data>
<data name="menuSetDefaultMultipleServerXrayRoundRobin" xml:space="preserve">
<value>多服务器负载均衡 Xray</value>
<value>多配置文件负载均衡  Xray</value>
</data>
<data name="menuSetDefaultMultipleServerXrayLeastPing" xml:space="preserve">
<value>多服务器最低延迟 Xray</value>
<value>多配置文件最低延迟  Xray</value>
</data>
<data name="menuSetDefaultMultipleServerXrayLeastLoad" xml:space="preserve">
<value>多服务器最稳定 Xray</value>
<value>多配置文件最稳定  Xray</value>
</data>
<data name="menuSetDefaultMultipleServerSingBoxLeastPing" xml:space="preserve">
<value>多服务器最低延迟 sing-box</value>
<value>多配置文件最低延迟 sing-box</value>
</data>
<data name="menuExportConfig" xml:space="preserve">
<value>导出服务器</value>
<value>导出配置文件</value>
</data>
</root>

View file

@ -121,7 +121,7 @@
<value>匯出分享链接至剪貼簿成功</value>
</data>
<data name="CheckServerSettings" xml:space="preserve">
<value>請先檢查伺服器設定</value>
<value>請先檢查設定檔設定</value>
</data>
<data name="ConfigurationFormatIncorrect" xml:space="preserve">
<value>設定格式不正確</value>
@ -148,13 +148,13 @@
<value>獲取預設設定失敗</value>
</data>
<data name="FailedImportedCustomServer" xml:space="preserve">
<value>匯入自訂設定伺服器失敗</value>
<value>匯入自訂設定設定檔失敗</value>
</data>
<data name="FailedReadConfiguration" xml:space="preserve">
<value>讀取設定檔失敗</value>
</data>
<data name="FillCorrectServerPort" xml:space="preserve">
<value>請填寫正確格式的伺服器埠</value>
<value>請填寫正確格式的埠</value>
</data>
<data name="FillLocalListeningPort" xml:space="preserve">
<value>請填寫本機偵聽埠</value>
@ -163,7 +163,7 @@
<value>請填寫密碼</value>
</data>
<data name="FillServerAddress" xml:space="preserve">
<value>請填寫伺服器位址</value>
<value>請填寫位址</value>
</data>
<data name="FillUUID" xml:space="preserve">
<value>請填寫使用者 ID</value>
@ -271,13 +271,13 @@
<value>請選擇協定</value>
</data>
<data name="PleaseSelectServer" xml:space="preserve">
<value>請先選擇伺服器</value>
<value>請先選擇設定檔</value>
</data>
<data name="RemoveDuplicateServerResult" xml:space="preserve">
<value>伺服器去重完成。原數量: {0},現數量: {1}。</value>
<value>設定檔去重完成。原數量: {0},現數量: {1}。</value>
</data>
<data name="RemoveServer" xml:space="preserve">
<value>是否確定移除伺服器</value>
<value>是否確定移除設定檔</value>
</data>
<data name="SaveClientConfigurationIn" xml:space="preserve">
<value>用戶端設定檔儲存在:{0}</value>
@ -289,10 +289,10 @@
<value>設定成功。{0}</value>
</data>
<data name="SuccessfullyImportedCustomServer" xml:space="preserve">
<value>成功匯入自訂設定伺服器</value>
<value>成功匯入自訂設定設定檔</value>
</data>
<data name="SuccessfullyImportedServerViaClipboard" xml:space="preserve">
<value>成功從剪貼簿匯入 {0} 個伺服器</value>
<value>成功從剪貼簿匯入 {0} 個設定檔</value>
</data>
<data name="SuccessfullyImportedServerViaScan" xml:space="preserve">
<value>掃描匯入分享链接成功</value>
@ -388,13 +388,13 @@
<value>註冊全域快速鍵 {0} 成功</value>
</data>
<data name="UngroupedServers" xml:space="preserve">
<value>未分組伺服器</value>
<value>未分組設定檔</value>
</data>
<data name="AllGroupServers" xml:space="preserve">
<value>所有</value>
</data>
<data name="FillServerAddressCustom" xml:space="preserve">
<value>請瀏覽匯入伺服器設定</value>
<value>請瀏覽匯入設定檔設定</value>
</data>
<data name="Speedtesting" xml:space="preserve">
<value>測試中...</value>
@ -406,7 +406,7 @@
<value>本機</value>
</data>
<data name="MsgServerTitle" xml:space="preserve">
<value>伺服器過濾,按 Enter 執行</value>
<value>設定檔過濾,按 Enter 執行</value>
</data>
<data name="menuCheckUpdate" xml:space="preserve">
<value>檢查更新</value>
@ -436,7 +436,7 @@
<value>路由設定</value>
</data>
<data name="menuServers" xml:space="preserve">
<value>伺服器</value>
<value>設定檔</value>
</data>
<data name="menuSetting" xml:space="preserve">
<value>設定</value>
@ -487,55 +487,55 @@
<value>掃描螢幕上的二維碼 (Ctrl+S)</value>
</data>
<data name="menuCopyServer" xml:space="preserve">
<value>複製所選伺服器</value>
<value>複製所選設定檔</value>
</data>
<data name="menuRemoveDuplicateServer" xml:space="preserve">
<value>移除重複的伺服器</value>
<value>移除重複的設定檔</value>
</data>
<data name="menuRemoveServer" xml:space="preserve">
<value>移除所選伺服器 (多選) (Delete)</value>
<value>移除所選設定檔 (多選) (Delete)</value>
</data>
<data name="menuSetDefaultServer" xml:space="preserve">
<value>設為活動伺服器 (Enter)</value>
<value>設為活動設定檔 (Enter)</value>
</data>
<data name="menuClearServerStatistics" xml:space="preserve">
<value>清除所有服務統計資料</value>
</data>
<data name="menuRealPingServer" xml:space="preserve">
<value>測試伺服器真連線延遲 (多選) (Ctrl+R)</value>
<value>測試設定檔真連線延遲 (多選) (Ctrl+R)</value>
</data>
<data name="menuSortServerResult" xml:space="preserve">
<value>按測試結果排序</value>
</data>
<data name="menuSpeedServer" xml:space="preserve">
<value>測試伺服器速度 (多選) (Ctrl+T)</value>
<value>測試設定檔速度 (多選) (Ctrl+T)</value>
</data>
<data name="menuTcpingServer" xml:space="preserve">
<value>測試伺服器延遲 Tcping (多選) (Ctrl+O)</value>
<value>測試設定檔延遲 Tcping (多選) (Ctrl+O)</value>
</data>
<data name="menuExport2ClientConfig" xml:space="preserve">
<value>匯出所選伺服器完整設定</value>
<value>匯出所選設定檔完整設定</value>
</data>
<data name="menuExport2ShareUrl" xml:space="preserve">
<value>匯出分享链接至剪貼簿 (多選) (Ctrl+C)</value>
</data>
<data name="menuAddCustomServer" xml:space="preserve">
<value>新增自訂設定伺服器</value>
<value>新增自訂設定設定檔</value>
</data>
<data name="menuAddShadowsocksServer" xml:space="preserve">
<value>新增 [Shadowsocks] 伺服器</value>
<value>新增 [Shadowsocks] 設定檔</value>
</data>
<data name="menuAddSocksServer" xml:space="preserve">
<value>新增 [SOCKS] 伺服器</value>
<value>新增 [SOCKS] 設定檔</value>
</data>
<data name="menuAddTrojanServer" xml:space="preserve">
<value>新增 [Trojan] 伺服器</value>
<value>新增 [Trojan] 設定檔</value>
</data>
<data name="menuAddVlessServer" xml:space="preserve">
<value>新增 [VLESS] 伺服器</value>
<value>新增 [VLESS] 設定檔</value>
</data>
<data name="menuAddVmessServer" xml:space="preserve">
<value>新增 [VMess] 伺服器</value>
<value>新增 [VMess] 設定檔</value>
</data>
<data name="menuSelectAll" xml:space="preserve">
<value>全選 (Ctrl+A)</value>
@ -700,7 +700,7 @@
<value>Outbound Freedom domainStrategy</value>
</data>
<data name="TbSettingsEnableAutoAdjustMainLvColWidth" xml:space="preserve">
<value>在更新訂閱後自動調整伺服器列寬</value>
<value>在更新訂閱後自動調整設定檔列寬</value>
</data>
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
<value>檢查 Pre-Release 更新 (請謹慎啟用)</value>
@ -760,7 +760,7 @@
<value>啟用安全協定 TLS v1.3 (訂閱/檢查更新)</value>
</data>
<data name="TbSettingsTrayMenuServersLimit" xml:space="preserve">
<value>工具列右鍵選單伺服器展示數量限制</value>
<value>工具列右鍵選單設定檔展示數量限制</value>
</data>
<data name="TbSettingsUdpEnabled" xml:space="preserve">
<value>開啟 UDP</value>
@ -793,7 +793,7 @@
<value>PAC 模式</value>
</data>
<data name="menuShareServer" xml:space="preserve">
<value>分享伺服器 (Ctrl+F)</value>
<value>分享設定檔 (Ctrl+F)</value>
</data>
<data name="menuRouting" xml:space="preserve">
<value>路由</value>
@ -940,7 +940,7 @@
<value>移至訂閱分組</value>
</data>
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
<value>啟動伺服器拖放排序 (需重啟)</value>
<value>啟動設定檔拖放排序 (需重啟)</value>
</data>
<data name="TbAutoRefresh" xml:space="preserve">
<value>自動重新整理</value>
@ -949,10 +949,10 @@
<value>跳過測試</value>
</data>
<data name="menuEditServer" xml:space="preserve">
<value>編輯伺服器 (Ctrl+D)</value>
<value>編輯設定檔 (Ctrl+D)</value>
</data>
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
<value>主介面輕按兩下設為活動伺服器</value>
<value>主介面輕按兩下設為活動設定檔</value>
</data>
<data name="SpeedtestingCompleted" xml:space="preserve">
<value>測試完成</value>
@ -1057,7 +1057,7 @@
<value>Domain</value>
</data>
<data name="menuAddHysteria2Server" xml:space="preserve">
<value>添加 [Hysteria2] 伺服器</value>
<value>添加 [Hysteria2] 設定檔</value>
</data>
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
<value>Hysteria 最大頻寬 (Up/Dw)</value>
@ -1066,19 +1066,19 @@
<value>使用系統 hosts</value>
</data>
<data name="menuAddTuicServer" xml:space="preserve">
<value>新增 [TUIC] 伺服器</value>
<value>新增 [TUIC] 設定檔</value>
</data>
<data name="TbHeaderType8" xml:space="preserve">
<value>擁塞控制算法</value>
</data>
<data name="LvPrevProfile" xml:space="preserve">
<value>前置代理別名</value>
<data name="LvPrevProfile" xml:space="preserve">
<value>前置代理設定檔別名</value>
</data>
<data name="LvNextProfile" xml:space="preserve">
<value>落地代理別名</value>
<data name="LvNextProfile" xml:space="preserve">
<value>落地代理設定檔別名</value>
</data>
<data name="LvPrevProfileTip" xml:space="preserve">
<value>請確保別名存在並且唯一</value>
<data name="LvPrevProfileTip" xml:space="preserve">
<value>請確保設定檔別名存在並且唯一</value>
</data>
<data name="TbSettingsEnableExInbound" xml:space="preserve">
<value>啟用額外偵聽連接埠</value>
@ -1087,7 +1087,7 @@
<value>啟用 IPv6</value>
</data>
<data name="menuAddWireguardServer" xml:space="preserve">
<value>添加 [WireGuard] 伺服器</value>
<value>添加 [WireGuard] 設定檔</value>
</data>
<data name="TbPrivateKey" xml:space="preserve">
<value>PrivateKey</value>
@ -1120,7 +1120,7 @@
<value>*grpc Authority</value>
</data>
<data name="menuAddHttpServer" xml:space="preserve">
<value>新增 [HTTP] 伺服器</value>
<value>新增 [HTTP] 設定檔</value>
</data>
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
<value>使用 Xray 且非 Tun 模式啟用,和分組前置代理衝突</value>
@ -1234,7 +1234,7 @@
<value>匯出分享链接至剪貼簿 (多選) Base64 编码</value>
</data>
<data name="menuExport2ClientConfigClipboard" xml:space="preserve">
<value>匯出所選伺服器完整設定至剪貼簿</value>
<value>匯出所選設定檔完整設定至剪貼簿</value>
</data>
<data name="menuShowOrHideMainWindow" xml:space="preserve">
<value>顯示或隱藏主介面</value>
@ -1393,24 +1393,24 @@
<value>會覆蓋端口,多組時用逗號 (,) 隔開</value>
</data>
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
<value>多伺服器產生自訂配置 (多選)</value>
<value>多設定檔產生自訂配置 (多選)</value>
</data>
<data name="menuSetDefaultMultipleServerXrayRandom" xml:space="preserve">
<value>多伺服器隨機 Xray</value>
<value>多設定檔隨機 Xray</value>
</data>
<data name="menuSetDefaultMultipleServerXrayRoundRobin" xml:space="preserve">
<value>多伺服器負載平衡 Xray</value>
<value>多設定檔負載平衡 Xray</value>
</data>
<data name="menuSetDefaultMultipleServerXrayLeastPing" xml:space="preserve">
<value>多伺服器最低延遲 Xray</value>
<value>多設定檔最低延遲 Xray</value>
</data>
<data name="menuSetDefaultMultipleServerXrayLeastLoad" xml:space="preserve">
<value>多伺服器最穩定 Xray</value>
<value>多設定檔最穩定 Xray</value>
</data>
<data name="menuSetDefaultMultipleServerSingBoxLeastPing" xml:space="preserve">
<value>多伺服器最低延遲 sing-box</value>
<value>多設定檔最低延遲 sing-box</value>
</data>
<data name="menuExportConfig" xml:space="preserve">
<value>匯出伺服器</value>
<value>匯出設定檔</value>
</data>
</root>

View file

@ -13,13 +13,6 @@ public class CoreConfigClashService
_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)
{
var ret = new RetResult();

View file

@ -120,7 +120,7 @@ public class CoreConfigV2rayService
{
continue;
}
if (it.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard)
if (it.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC)
{
continue;
}
@ -661,7 +661,7 @@ public class CoreConfigV2rayService
{
usersItem = vnextItem.users.First();
}
//远程服务器用户ID
usersItem.id = node.Id;
usersItem.alterId = node.AlterId;
usersItem.email = Global.UserEMail;
@ -805,6 +805,26 @@ public class CoreConfigV2rayService
outbound.settings.vnext = null;
break;
}
case EConfigType.WireGuard:
{
var peer = new WireguardPeer4Ray
{
publicKey = node.PublicKey,
endpoint = node.Address + ":" + node.Port.ToString()
};
var setting = new Outboundsettings4Ray
{
address = Utils.String2List(node.RequestHost),
secretKey = node.Id,
reserved = Utils.String2List(node.Path)?.Select(int.Parse).ToList(),
mtu = node.ShortId.IsNullOrEmpty() ? Global.TunMtus.First() : node.ShortId.ToInt(),
peers = new List<WireguardPeer4Ray> { peer }
};
outbound.settings = setting;
outbound.settings.vnext = null;
outbound.settings.servers = null;
break;
}
}
outbound.protocol = Global.ProtocolTypes[node.ConfigType];
@ -1123,7 +1143,7 @@ public class CoreConfigV2rayService
obj["servers"] = JsonUtils.SerializeToNode(servers);
}
// 追加至 dns 设置
// Append to dns settings
if (item.UseSystemHosts)
{
var systemHosts = Utils.GetSystemHosts();
@ -1270,8 +1290,7 @@ public class CoreConfigV2rayService
if (prevNode is not null
&& prevNode.ConfigType != EConfigType.Custom
&& prevNode.ConfigType != EConfigType.Hysteria2
&& prevNode.ConfigType != EConfigType.TUIC
&& prevNode.ConfigType != EConfigType.WireGuard)
&& prevNode.ConfigType != EConfigType.TUIC)
{
var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
await GenOutbound(prevNode, prevOutbound);
@ -1289,8 +1308,7 @@ public class CoreConfigV2rayService
if (nextNode is not null
&& nextNode.ConfigType != EConfigType.Custom
&& nextNode.ConfigType != EConfigType.Hysteria2
&& nextNode.ConfigType != EConfigType.TUIC
&& nextNode.ConfigType != EConfigType.WireGuard)
&& nextNode.ConfigType != EConfigType.TUIC)
{
var nextOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
await GenOutbound(nextNode, nextOutbound);

View file

@ -100,6 +100,7 @@ public class OptionSettingViewModel : MyReactiveObject
[Reactive] public string CoreType4 { get; set; }
[Reactive] public string CoreType5 { get; set; }
[Reactive] public string CoreType6 { get; set; }
[Reactive] public string CoreType9 { get; set; }
#endregion CoreType
@ -259,6 +260,10 @@ public class OptionSettingViewModel : MyReactiveObject
case 6:
CoreType6 = type;
break;
case 9:
CoreType9 = type;
break;
}
});
await Task.CompletedTask;
@ -407,6 +412,10 @@ public class OptionSettingViewModel : MyReactiveObject
type = CoreType6;
break;
case 9:
type = CoreType9;
break;
default:
continue;
}

View file

@ -131,7 +131,6 @@ public partial class AddServerWindow : ReactiveWindow<AddServerViewModel>
sepa2.IsVisible = false;
gridTransport.IsVisible = false;
gridTls.IsVisible = false;
cmbCoreType.IsEnabled = false;
break;
}

View file

@ -813,7 +813,7 @@
<Grid
Margin="{StaticResource Margin4}"
ColumnDefinitions="Auto,Auto"
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto">
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<TextBlock
Grid.Row="1"
Grid.Column="0"
@ -891,6 +891,19 @@
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}" />
<TextBlock
Grid.Row="7"
Grid.Column="0"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Text="Wireguard" />
<ComboBox
x:Name="cmbCoreType9"
Grid.Row="7"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin4}" />
</Grid>
</TabItem>
</TabControl>

View file

@ -64,6 +64,7 @@ public partial class OptionSettingWindow : ReactiveWindow<OptionSettingViewModel
cmbCoreType4.Items.Add(it);
cmbCoreType5.Items.Add(it);
cmbCoreType6.Items.Add(it);
cmbCoreType9.Items.Add(it);
});
for (var i = 2; i <= 8; i++)
@ -160,6 +161,7 @@ public partial class OptionSettingWindow : ReactiveWindow<OptionSettingViewModel
this.Bind(ViewModel, vm => vm.CoreType4, v => v.cmbCoreType4.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType5, v => v.cmbCoreType5.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType6, v => v.cmbCoreType6.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType9, v => v.cmbCoreType9.SelectedValue).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
});

View file

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

View file

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

View file

@ -125,7 +125,6 @@ public partial class AddServerWindow
sepa2.Visibility = Visibility.Collapsed;
gridTransport.Visibility = Visibility.Collapsed;
gridTls.Visibility = Visibility.Collapsed;
cmbCoreType.IsEnabled = false;
break;
}

View file

@ -1098,6 +1098,7 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@ -1192,6 +1193,21 @@
Width="200"
Margin="{StaticResource Margin8}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="7"
Grid.Column="0"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="Wireguard" />
<ComboBox
x:Name="cmbCoreType9"
Grid.Row="7"
Grid.Column="1"
Width="200"
Margin="{StaticResource Margin8}"
Style="{StaticResource DefComboBox}" />
</Grid>
</TabItem>
</TabControl>

View file

@ -66,6 +66,7 @@ public partial class OptionSettingWindow
cmbCoreType4.Items.Add(it);
cmbCoreType5.Items.Add(it);
cmbCoreType6.Items.Add(it);
cmbCoreType9.Items.Add(it);
});
for (var i = 2; i <= 8; i++)
@ -178,6 +179,7 @@ public partial class OptionSettingWindow
this.Bind(ViewModel, vm => vm.CoreType4, v => v.cmbCoreType4.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType5, v => v.cmbCoreType5.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType6, v => v.cmbCoreType6.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType9, v => v.cmbCoreType9.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
});