Compare commits

...

232 Commits
7.2.3 ... 7.8.1

Author SHA1 Message Date
2dust
c3fdfcc4bd up 7.8.1 2025-02-08 16:49:59 +08:00
2dust
7ea8fae2da Improve test logic
Retest the failed part of the test and call it recursively.
Remove the number of batches that are automatically divided when testing parameters.
2025-02-08 16:43:40 +08:00
2dust
67ffa810d3 Optimize code and remove Action 2025-02-06 15:28:51 +08:00
2dust
ba2a636dd2 Fixed the system language judgment during the first run
https://github.com/2dust/v2rayN/issues/6638
2025-02-06 14:36:38 +08:00
2dust
d471336994 Adjust App Exit function
https://github.com/2dust/v2rayN/issues/6634
2025-02-05 17:31:13 +08:00
2dust
7e6482fdff Adjust hysteria core run arguments
https://github.com/2dust/v2rayN/issues/6635
2025-02-05 17:14:56 +08:00
2dust
a8eba93ffd up 7.8.0 2025-02-04 14:30:42 +08:00
2dust
4ffe595db6 Code clean 2025-02-04 14:30:28 +08:00
2dust
885587e551 Update Directory.Packages.props 2025-02-04 14:19:56 +08:00
2dust
e986dc189e Fix ProcUtils NoAssociatedProcess issue 2025-02-04 10:30:33 +08:00
2dust
bccab41c8f Update Directory.Build.props 2025-02-04 10:28:49 +08:00
2dust
79a0538ca0 Improve core info 2025-02-03 20:19:20 +08:00
2dust
e6b27d17e4 Add support for overtls custom configuration
https://github.com/ShadowsocksR-Live/overtls
2025-02-03 15:43:26 +08:00
2dust
2a0012824a Add support for brook custom configuration
https://github.com/txthinking/brook
https://github.com/txthinking/brook/issues/1372
2025-02-03 15:06:21 +08:00
2dust
9d92be99ee Improve core running arguments 2025-02-03 14:48:53 +08:00
2dust
6914831d30 Code clean 2025-02-02 17:48:59 +08:00
2dust
19d83be6de Fix Package AppImage script 2025-02-01 19:10:54 +08:00
2dust
ce7303bd0d up 7.7.1 2025-02-01 14:16:54 +08:00
2dust
4c3318ac86 Revert "Update MainWindow.axaml.cs"
This reverts commit 4d95d7d8c0.
2025-02-01 14:11:12 +08:00
2dust
db25fdeee1 Revert "Remove using System.Reflection"
This reverts commit 732c3eee8b.
2025-02-01 13:51:28 +08:00
2dust
732c3eee8b Remove using System.Reflection 2025-02-01 10:34:05 +08:00
2dust
2b0d805b2f Update Directory.Build.props 2025-02-01 10:33:11 +08:00
2dust
4faa94b2a3 Cache when reading embedded resources 2025-01-31 16:02:29 +08:00
2dust
331d11aee2 Update .editorconfig 2025-01-31 15:59:44 +08:00
2dust
4d95d7d8c0 Update MainWindow.axaml.cs
if (Utils.IsOSX() || _config.UiItem.Hide2TrayWhenClose)
2025-01-31 15:59:35 +08:00
dependabot[bot]
fd82623c74 Bump actions/setup-dotnet from 4.2.0 to 4.3.0 (#6604)
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v4.2.0...v4.3.0)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-31 09:17:42 +08:00
2dust
4a32b2c814 Fixed the issue of update the Windows self contained version 2025-01-30 18:06:13 +08:00
2dust
45264005a4 Code clean 2025-01-30 17:10:05 +08:00
2dust
253219dd16 Update .editorconfig 2025-01-30 16:35:48 +08:00
ShiinaRinne
b2feaf3ba9 [macOS] feat: auto run. https://github.com/2dust/v2rayN/issues/6383 (#6597) 2025-01-30 13:24:01 +08:00
2dust
6c5011ad68 Try to remove the tun device when restarting the service in Windows
https://github.com/2dust/v2rayN/pull/6561
2025-01-30 10:46:04 +08:00
ShiinaRinne
c0f8b6b84c [macOS] amend: Child window visibility handling (#6598)
https://github.com/2dust/v2rayN/pull/6596

When the main window is hidden, open child windows are mistakenly hidden as well.
This prevents reopening child windows after the main window is shown again.
2025-01-30 10:12:59 +08:00
ShiinaRinne
f71125d8f3 macOS 一些优化 (#6596)
* [macOS] hide icon in Dock

* [macOS] fix: close button not work

* [macOS] fix: cant directly show window when click `Show or hide the main window` on minimized
2025-01-29 19:26:40 +08:00
2dust
e674a025d8 Adjust Directory.Build.props
https://learn.microsoft.com/zh-cn/dotnet/core/deploying/trimming/trimming-options

https://learn.microsoft.com/zh-cn/dotnet/csharp/language-reference/compiler-options/code-generation
2025-01-29 15:17:30 +08:00
2dust
dadc24876f Change Directory 2025-01-29 14:22:30 +08:00
Anatoliy
98d4801b7e Use Directory.Build.props for centralized configuration management (#6591)
* use Directory.Buld.props

* remove some properties
2025-01-28 20:01:59 +08:00
Anatoliy
0e50bfb6eb create editorconfig (#6592) 2025-01-28 12:16:04 +08:00
2dust
a5aa286535 Add Name to App.axaml 2025-01-25 20:45:56 +08:00
2dust
3caf025c3c Update README.md 2025-01-25 20:19:02 +08:00
2dust
c943c6c60a Update README.md 2025-01-25 20:15:16 +08:00
2dust
8c55c629cd Fix PackageReference 2025-01-24 20:28:04 +08:00
2dust
0c38ebb63f Added Avalonia UI Windows version compilation script 2025-01-24 20:01:36 +08:00
2dust
75df85f598 Release script adjust prerelease = true 2025-01-24 19:48:34 +08:00
2dust
59e99b2316 Downgrade ZXing.Net.Bindings.SkiaSharp to version 0.16.14
In linux report
Unhandled exception. System.TypeInitializationException: The type initializer for 'SkiaSharp.SKFontManager' threw an exception.
 ---> System.TypeInitializationException: The type initializer for 'SkiaSharp.SKObject' threw an exception.
 ---> System.InvalidOperationException: The version of the native libSkiaSharp library (88.1) is incompatible with this version of SkiaSharp. Supported versions of the native libSkiaSharp library are in the range [116.0, 117.0).
   at SkiaSharp.SkiaSharpVersion.CheckNativeLibraryCompatible(Version minSupported, Version current, Boolean throwIfIncompatible)
   at SkiaSharp.SkiaSharpVersion.CheckNativeLibraryCompatible(Boolean throwIfIncompatible)
   at SkiaSharp.SKObject..cctor()
2025-01-24 19:46:28 +08:00
Anatoliy
02f4dcbaf7 use Directory.Packages.props (#6581) 2025-01-24 19:00:21 +08:00
2dust
470dec5588 up PackageReference 2025-01-24 17:24:07 +08:00
2dust
be1e37ddd0 Hide the upgrade core in Windows 7 2025-01-24 14:26:51 +08:00
2dust
fdc32601a9 Update ResUI.Designer.cs 2025-01-24 14:25:56 +08:00
2dust
d3b86858e1 Revert "Use Directory.Packages.props (#6575)"
This reverts commit 9c20d9cb1f.
2025-01-24 14:25:13 +08:00
Anatoliy
9c20d9cb1f Use Directory.Packages.props (#6575) 2025-01-24 09:57:38 +08:00
alphax-hue3682
d2cda16378 Update Persian Translate (#6559) 2025-01-22 10:00:33 +08:00
aucub
2ab00d5b6f Add Package AppImage script (#6556) 2025-01-21 09:27:38 +08:00
OnceUponATimeInAmerica
1b8a58cd07 Update English translation (#6555) 2025-01-21 09:15:48 +08:00
Anatoliy
0c3293045f Remove extra .gitignore file and move .gitattributes to the root folder for consistent storage of .git-related files. (#6545) 2025-01-20 09:28:30 +08:00
2dust
4c4ce7e8d1 Revert "增加macos dmg软件签名 (#6541)"
This reverts commit a0d4a3f2e8.
2025-01-19 18:58:32 +08:00
zjt003
a0d4a3f2e8 增加macos dmg软件签名 (#6541)
* Update package-osx.sh

* Update build-osx.yml
2025-01-19 18:34:39 +08:00
2dust
26abe7e7d7 up 7.7.0 2025-01-19 09:36:43 +08:00
2dust
b9c86ed3a1 Modify the file name in winget release package 2025-01-19 09:35:19 +08:00
2dust
b7cff66a80 Remove the core name in the Windows release version 2025-01-19 09:34:37 +08:00
2dust
61a40d2860 up PackageReference 2025-01-19 09:27:20 +08:00
2dust
80eb569366 The bin folder is added to the package
54fe669d89
2025-01-18 21:10:41 +08:00
2dust
54fe669d89 Copy the bin folder to the storage location (for init) 2025-01-18 16:58:44 +08:00
2dust
0953237e9e Improvements 2025-01-18 16:01:52 +08:00
2dust
cf1a8599eb When updating the bin folder, skip the file if it already exists.
https://github.com/2dust/v2rayN/issues/6515
2025-01-17 10:27:29 +08:00
alphax-hue3682
171132be12 Update Persian Translate (#6513) 2025-01-16 15:56:05 +08:00
2dust
43c95422b7 up 7.6.2 2025-01-15 19:49:14 +08:00
esmaiel777
2662243641 Update dns_singbox_normal (#6511) 2025-01-15 19:47:45 +08:00
esmaiel777
060a35e091 Update tun_singbox_dns (#6510) 2025-01-15 19:47:34 +08:00
2dust
de1132c2df Added option to display real-time speed 2025-01-15 19:45:53 +08:00
2dust
f19edc9370 Improvements and Adjustments
InitCoreInfo()
2025-01-15 17:31:13 +08:00
2dust
f1601c463b Improvements and Adjustments
await Task.CompletedTask;
return await Task.FromResult(0);
2025-01-15 17:26:15 +08:00
2dust
77b15cd530 Add a prompt for not setting a password when open Tun on macos 2025-01-15 11:02:49 +08:00
2dust
a6479fe0d0 Update build-windows.yml 2025-01-14 18:15:45 +08:00
2dust
4ad4e27dc1 Improve reload function 2025-01-14 17:05:13 +08:00
2dust
7370684985 Improve delete expired files 2025-01-14 17:04:43 +08:00
2dust
5ae58e6a98 Improve reload function 2025-01-14 14:49:17 +08:00
2dust
780ccb1932 Improved ProfileItemsEx 2025-01-14 11:48:02 +08:00
2dust
6b4076be10 up 7.6.1 2025-01-12 19:36:19 +08:00
alphax-hue3682
d7a04a15ae Update Persian translate (#6487) 2025-01-12 19:33:57 +08:00
2dust
2ae43f8bdb Revert "Remove rules custom Icon"
This reverts commit d3ebc17a10.
2025-01-12 19:33:23 +08:00
2dust
d3ebc17a10 Remove rules custom Icon 2025-01-12 14:35:59 +08:00
2dust
7a8680711e Improvements and Adjustments 2025-01-12 14:30:49 +08:00
2dust
649e89e7af Added Copy Terminal proxy command to clipboard in tray menu
https://github.com/2dust/v2rayN/issues/6482
2025-01-12 11:07:34 +08:00
2dust
cb94d64395 Bug fix 2025-01-11 19:35:32 +08:00
2dust
2440dc2440 Remove deprecated DefIEProxyExceptions 2025-01-11 19:34:04 +08:00
Little丶Dreams
364a24c580 CloneServerStatItem 时检查indexId和toIndexId是否相同 (#6478) 2025-01-11 14:44:09 +08:00
2dust
8f3e0dbd82 up 7.6.0 2025-01-11 11:48:57 +08:00
alphax-hue3682
596234df26 Update Persian translate (#6465)
* Update ResUI.fa-Ir.resx

e0ae101ff4

* Update ResUI.fa-Ir.resx
2025-01-11 11:30:06 +08:00
2dust
c38aec50dc Delete unused resources 2025-01-11 11:28:35 +08:00
2dust
40915b5f98 Adjust theme options for windows 2025-01-11 11:23:40 +08:00
2dust
a176613119 Bug fix for ProcUtils 2025-01-11 10:44:34 +08:00
2dust
6c6de1ae7f Improvements and Adjustments 2025-01-10 20:12:42 +08:00
2dust
edbd168dcf Add theme options for desktop 2025-01-10 15:53:06 +08:00
2dust
127858d582 Adjust UI for desktop 2025-01-10 14:23:03 +08:00
2dust
baf90cfbdd Sing-box cache file specified path
https://github.com/2dust/v2rayN/issues/6460
2025-01-10 10:00:00 +08:00
2dust
1a5eeb9401 Adjust UI for desktop 2025-01-09 21:03:17 +08:00
2dust
e0ae101ff4 Adjust UI for desktop 2025-01-09 15:14:03 +08:00
Long Yixing
8b4a07dfe8 Modify the macos build script (#6461)
No longer generate AppIcon.icns
2025-01-09 10:21:07 +08:00
2dust
db934e70cb The icon of the system proxy can be customized
https://github.com/2dust/v2rayN/issues/6459
2025-01-08 20:35:33 +08:00
2dust
b770048f05 The exported routing rules are compatible with the import function of v2rayNG 2025-01-08 17:57:23 +08:00
2dust
27c53be209 up 7.5.6 2025-01-08 14:16:30 +08:00
2dust
d93c12b354 Add more options to xray fragment 2025-01-08 13:52:21 +08:00
2dust
98d4a47efb Fix Mux for XUDP
https://github.com/2dust/v2rayN/issues/6446
2025-01-07 20:16:05 +08:00
2dust
8ab04c65b5 Update README.md 2025-01-07 14:33:15 +08:00
2dust
1b2dab1388 Bug fix
https://github.com/2dust/v2rayN/issues/6448
2025-01-07 11:28:46 +08:00
2dust
4f8dae7fa0 Add the mixed option in Stack in Tun mode settings
https://github.com/2dust/v2rayN/issues/6441
2025-01-06 20:46:07 +08:00
Harry Huang
cdc23e32c4 Fix zh-Hans and zh-Hant translation style (#6443)
* Fix zh-Hans i10n translation style

* Fix zh-Hant i10n translation style
2025-01-06 19:05:43 +08:00
2dust
20457e9e63 up 7.5.5 2025-01-05 19:10:57 +08:00
2dust
e63042af84 Bug fix for fontsize 2025-01-05 19:10:12 +08:00
2dust
c35b4d3c1b up 7.5.4 2025-01-05 17:58:55 +08:00
2dust
64a83a5d64 down PackageReference 2025-01-05 17:58:23 +08:00
2dust
01039d0b47 up 7.5.3 2025-01-05 17:31:32 +08:00
2dust
7c1e5a3cba Fixed possible crash issues 2025-01-05 17:12:51 +08:00
2dust
038161527f Buf fix for CurrentFontSize 2025-01-05 17:11:32 +08:00
2dust
b12b7a17e6 Fix possible issues with load balancing 2025-01-05 16:31:32 +08:00
2dust
37cf23d5fe up PackageReference 2025-01-05 15:01:15 +08:00
2dust
ed7fb4f6e3 Code clean 2025-01-05 14:50:31 +08:00
2dust
5d4bd2fee6 Fix possible issues with load balancing
https://github.com/2dust/v2rayN/issues/6429
2025-01-05 14:49:53 +08:00
2dust
aae5906311 Fix GetListNetworkServices 2025-01-05 12:24:14 +08:00
2dust
4a7bafd011 Fix Linux restore backup function
Fixed the issue that the guiNConfig.json file cannot be restored in the backup and restore function
2025-01-05 10:22:18 +08:00
2dust
626ebfe65d Improved ModifyFontSize 2025-01-04 20:42:42 +08:00
2dust
3cc75cd46d up 7.5.2 2025-01-04 19:07:16 +08:00
2dust
f809ee7b20 Adjust the macos package icon
https://github.com/2dust/v2rayN/issues/6404
2025-01-04 19:06:26 +08:00
2dust
1295d8191c Fix DNS
https://github.com/2dust/v2rayN/issues/6416
2025-01-04 17:47:54 +08:00
2dust
bc2adbfa77 Add restart to Linux restore backup function 2025-01-04 17:03:12 +08:00
2dust
9583dff176 Added the function of restarting the main app to AmazTool 2025-01-04 17:01:57 +08:00
2dust
5732b84a7b Refactor KillProcess 2025-01-04 15:06:30 +08:00
2dust
c0d27504ac Refactor ProcessStart RebootAsAdmin 2025-01-03 20:56:51 +08:00
2dust
3db1dd7bbb Add a title to SaveLog 2025-01-03 15:02:31 +08:00
2dust
5392766c5e Improved KillProcess 2025-01-03 15:01:30 +08:00
2dust
730b7dea37 Adjust upgrade waiting time 2025-01-03 09:50:21 +08:00
2dust
02a13ce028 Add logging to KillProcess
https://github.com/2dust/v2rayN/issues/6386
2025-01-02 13:54:17 +08:00
2dust
7884853098 Improved backup and restore
Overwrite the configuration file directly in the main program
2025-01-02 13:36:26 +08:00
2dust
e122ea8146 Optimize VerticalAlignment="Center" 2025-01-02 12:20:43 +08:00
2dust
f500d2b9f4 up 7.5.1 2025-01-01 16:25:53 +08:00
2dust
79e53bf1f5 Improve macos system proxy code 2025-01-01 14:24:23 +08:00
2dust
31de7ec094 Bug fix SetLinuxChmod 2025-01-01 12:27:49 +08:00
2dust
2e4501187c Window title display adjustment
https://github.com/2dust/v2rayN/issues/6389
2025-01-01 10:38:55 +08:00
2dust
4430c9bd74 Remove the last rule from the Whitelist
https://github.com/2dust/v2rayN/issues/6378
2024-12-31 20:37:14 +08:00
2dust
cf8be85ff7 Remove the display of run as an administrator in Linux and macos 2024-12-31 16:30:27 +08:00
2dust
0759be1223 Fix rule required
https://github.com/2dust/v2rayN/issues/6378
2024-12-31 15:32:31 +08:00
2dust
21f8ddcf9f macos adds system proxy for USB
https://github.com/2dust/v2rayN/issues/6381
2024-12-31 14:55:35 +08:00
2dust
37cba5ee34 Fix export rule order issue
https://github.com/2dust/v2rayN/issues/6377
2024-12-31 14:15:09 +08:00
OnceUponATimeInAmerica
ff642fd1ac Add full support for (one-click) Iran regional preset by using Chocolate4U's github repos for iran routing rules (#6384) 2024-12-31 13:51:06 +08:00
2dust
647f1d9c8b up 7.5.0 2024-12-30 19:56:33 +08:00
2dust
d886195ee3 Adjust upgrade waiting time 2024-12-30 19:55:32 +08:00
2dust
e2b8f4f89a If Process.start contains spaces, add quotes 2024-12-30 19:33:39 +08:00
2dust
1dcfe661e9 Modify the build script
When NotStoreConfigHere.txt file exists, the configs not stored in the current folder
2024-12-30 18:16:07 +08:00
2dust
d6dd110781 Adjust open the storage location 2024-12-30 11:10:27 +08:00
2dust
a0f956c885 Add command shortcut keys for macos
https://github.com/2dust/v2rayN/issues/6375
2024-12-30 11:02:09 +08:00
Long Yixing
88bcafed97 Modify the build macos script (#6374) 2024-12-30 09:24:22 +08:00
2dust
6e4f15ab52 Update README.md 2024-12-27 10:12:38 +08:00
Wydy
20cae1ff4d Update pac (#6356) 2024-12-27 09:48:28 +08:00
2dust
dcf621b822 Modify the build script 2024-12-26 17:19:42 +08:00
2dust
eafa20032b Modify the build windows script 2024-12-25 17:06:03 +08:00
2dust
7375e1a490 Modify the build macos script 2024-12-25 16:48:23 +08:00
2dust
199d87ba84 Modify the build linux script and add release package deb 2024-12-25 16:11:02 +08:00
2dust
b43975ebfc Add v2rayN.png for desktop 2024-12-25 16:06:11 +08:00
2dust
fe7314c978 up 7.4.2 2024-12-24 10:55:25 +08:00
2dust
d4eb8e59a6 update build 2024-12-23 17:39:50 +08:00
2dust
8ee00907b7 update build 2024-12-23 17:34:06 +08:00
2dust
25fddc3c71 Code clean for desktop 2024-12-23 14:28:33 +08:00
2dust
c78b733850 Revert "update build macos"
This reverts commit a57c83125e.
2024-12-23 13:59:55 +08:00
2dust
a57c83125e update build macos 2024-12-23 12:12:03 +08:00
2dust
247b59985f update build 2024-12-23 11:31:56 +08:00
2dust
7470b8b6d3 Try to fix
https://github.com/2dust/v2rayN/issues/6073
2024-12-23 10:38:37 +08:00
2dust
776d37b7aa Optimize port display 2024-12-23 10:37:43 +08:00
alphax-hue3682
8f532f8468 Update persian translate (#6325) 2024-12-23 10:00:51 +08:00
2dust
472963fe2d Add a second local listening port
https://github.com/2dust/v2rayN/issues/6321
2024-12-22 20:03:20 +08:00
2dust
6a9b62ab9a Improve Ctrl+V for Windows 2024-12-22 12:02:00 +08:00
2dust
9ac8aa2969 up PackageReference 2024-12-22 12:00:50 +08:00
2dust
838bd2c794 up 7.4.1 2024-12-19 16:18:45 +08:00
2dust
b2bbe432e0 Fix
https://github.com/2dust/v2rayN/issues/6309
2024-12-19 16:07:45 +08:00
2dust
b3d8042452 The lower limit of the font size from 10 to 8 2024-12-19 13:53:40 +08:00
2dust
0c758a7fdc Optimize UI for macos 2024-12-19 13:36:45 +08:00
2dust
85cb1d1c92 Bug fix system proxy for macos 2024-12-19 13:20:12 +08:00
2dust
2cd2e8894d Add system proxy exception function for macos 2024-12-19 11:40:16 +08:00
2dust
abb58379b3 Add IsNonWindows instead of IsLinux or IsOSX 2024-12-19 11:24:52 +08:00
2dust
4f48e8b190 Optimize UI 2024-12-19 10:23:46 +08:00
2dust
2b5cbb5e74 UnauthorizedAccessException to Exception 2024-12-18 15:27:00 +08:00
2dust
23dd140921 up 7.4.0 2024-12-18 14:47:27 +08:00
2dust
8c8d7bda64 StartupPath optional LocalApplicationData for linux 2024-12-18 10:27:58 +08:00
2dust
a6e246948a Linux system proxy adds kde version processing 2024-12-17 11:05:12 +08:00
2dust
c49ba735a0 Optimize code 2024-12-16 21:05:36 +08:00
2dust
1a33c598e8 Disable mux when using xhttp 2024-12-16 21:01:03 +08:00
2dust
a4bbdb49de proxy api.ip.sb
https://github.com/2dust/v2rayN/issues/6280
2024-12-16 19:59:46 +08:00
2dust
cf3846fbfd Update README.md 2024-12-16 19:47:27 +08:00
2dust
d46943eedf Optimize UI 2024-12-16 14:28:22 +08:00
2dust
3bc17bd50a Add host for xray ws
https://github.com/XTLS/Xray-core/pull/4142
2024-12-16 14:22:31 +08:00
2dust
48a159f4c8 Need SkiaSharp V2.88 2024-12-15 16:15:58 +08:00
2dust
3d1bcffdc5 up 7.3.2 2024-12-15 15:14:25 +08:00
2dust
45fa0f94d2 up PackageReference 2024-12-15 15:13:37 +08:00
2dust
ed16b7de4a Fix
https://github.com/2dust/v2rayN/issues/6258
2024-12-15 14:41:48 +08:00
2dust
f2ec03c7ec Bug fix
https://github.com/2dust/v2rayN/issues/6263
2024-12-15 14:41:29 +08:00
2dust
11db87f1e6 Remove unused resources 2024-12-15 14:27:00 +08:00
phoenix6936
a1feaf33e0 Update persian translation (#6245)
* Update persian translation

* Update ResUI.fa-Ir.resx
2024-12-15 11:24:13 +08:00
2dust
53a99e3f79 Remove part System.Reflection 2024-12-08 11:11:06 +08:00
2dust
e7f04f55c2 Remove QueryableExtension 2024-12-08 11:10:15 +08:00
2dust
6653ea12b7 Add Language: Hungarian
https://github.com/2dust/v2rayN/issues/6252
2024-12-07 21:25:53 +08:00
2dust
a28cef5b98 Fixed the issue of save window size when exit
https://github.com/2dust/v2rayN/issues/6251
2024-12-07 21:13:57 +08:00
2dust
78a28fbdb3 up 7.3.1 2024-12-07 16:30:32 +08:00
2dust
bf8bbbdcb0 Code clean 2024-12-07 16:29:58 +08:00
2dust
83ad83b135 Optimize save config files 2024-12-07 14:07:51 +08:00
2dust
dbd4f55981 Add system proxy exception function for linux
https://github.com/2dust/v2rayN/issues/6214
2024-12-06 19:12:32 +08:00
2dust
5f5d7172ee Optimize system proxy exceptions 2024-12-06 16:38:23 +08:00
2dust
fbd4557b44 WebProxy uses socks5 instead of http 2024-12-06 14:01:11 +08:00
phoenix6936
5d55a55754 Update persian translate (#6237)
* Update persian translate

* Update ResUI.fa-Ir.resx
2024-12-06 10:01:11 +08:00
phoenix6936
84032aec33 Update persian translation (#6227)
* Update persian translation

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx

* Update ResUI.fa-Ir.resx
2024-12-06 09:38:56 +08:00
2dust
a372d8902e up 7.3.0 2024-12-05 20:08:23 +08:00
2dust
c38c62e4c3 Add automatic batching during speed test and real ping 2024-12-05 19:48:42 +08:00
2dust
8aceff7480 Enhanced testing function
Separate xray-core and sing-box-core testing
2024-12-05 15:21:16 +08:00
2dust
736c450161 Improve the code 2024-12-05 14:05:12 +08:00
2dust
3b63a3d308 Fix
https://github.com/2dust/v2rayN/issues/6216
2024-12-05 14:04:39 +08:00
2dust
4f56174c8f Bug fix
https://github.com/2dust/v2rayN/issues/6219
2024-12-05 12:16:53 +08:00
2dust
4d2eb324f1 Adjust UI
https://github.com/2dust/v2rayN/issues/6217
2024-12-05 10:39:08 +08:00
2dust
3f2ab8ddcb Try to fix
https://github.com/2dust/v2rayN/issues/6186
2024-12-05 10:12:26 +08:00
2dust
fd8f863c5b Add stream-one for xhttp mode 2024-12-03 18:00:55 +08:00
2dust
246f1d7df0 Update README.md 2024-12-03 17:54:13 +08:00
2dust
ccacda9bf5 Using mixed local listening ports 2024-12-03 15:01:36 +08:00
2dust
5494d63878 Remove v2fly-core UI operation support 2024-12-03 13:58:56 +08:00
2dust
c32b9812a7 up PackageReference 2024-12-02 14:43:07 +08:00
2dust
9eb9898b61 Improve the clash connection 2024-12-02 14:40:09 +08:00
2dust
834e05999f Paste import functionality moved to server list
https://github.com/2dust/v2rayN/issues/6201
2024-12-02 11:01:32 +08:00
2dust
b4c37d9906 Bug fix
https://github.com/2dust/v2rayN/issues/6200
2024-12-02 10:16:07 +08:00
2dust
9326b450d7 Delete .github/workflows/winget-pre-release-publish.yml 2024-12-01 14:39:36 +08:00
2dust
019ee8b1ba Update winget-publish.yml 2024-12-01 14:30:39 +08:00
Merrick Zhang
f043645397 Create winget-publish.yml (#6014)
* Create winget-publish.yml

Publish to winget after release

* Update winget-publish.yml

change to released trigger

* Create winget-pre-release-publish.yml

publish pre-release versions.
2024-12-01 14:29:10 +08:00
2dust
3b173f0b3e Improve code 2024-12-01 11:17:36 +08:00
2dust
f36c06389d Improve the clash connection 2024-12-01 10:18:36 +08:00
2dust
d3a0b44247 Bug fix
https://github.com/2dust/v2rayN/issues/6182
2024-11-30 13:49:26 +08:00
2dust
e4d3a98aa8 Fixed the problem of traffic statistics api url 2024-11-30 10:58:53 +08:00
2dust
f685682214 Code clean 2024-11-29 19:21:09 +08:00
210 changed files with 13247 additions and 4883 deletions

170
.editorconfig Normal file
View File

@@ -0,0 +1,170 @@
root = true
[*]
charset = utf-8
indent_style = space
tab_width = 4
indent_size = 4
end_of_line = crlf
trim_trailing_whitespace = true
insert_final_newline = true
[*.{yml,yaml}]
indent_style = space
indent_size = 2
[*.cs]
dotnet_hide_advanced_members = true
dotnet_member_insertion_location = with_other_members_of_the_same_kind
dotnet_property_generation_behavior = prefer_throwing_properties
dotnet_search_reference_assemblies = true
dotnet_separate_import_directive_groups = false:warning
dotnet_sort_system_directives_first = true:warning
file_header_template = unset
dotnet_style_qualification_for_event = false:warning
dotnet_style_qualification_for_field = false:warning
dotnet_style_qualification_for_method = false:warning
dotnet_style_qualification_for_property = false:warning
dotnet_style_predefined_type_for_locals_parameters_members = true:warning
dotnet_style_predefined_type_for_member_access = true:warning
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
dotnet_style_parentheses_in_other_operators = always_for_clarity:warning
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
dotnet_style_require_accessibility_modifiers = always:warning
dotnet_prefer_system_hash_code = true:warning
dotnet_style_coalesce_expression = true:warning
dotnet_style_collection_initializer = false:warning
dotnet_style_explicit_tuple_names = true:warning
dotnet_style_namespace_match_folder = true:warning
dotnet_style_null_propagation = true:warning
dotnet_style_object_initializer = true:warning
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_auto_properties = true:warning
dotnet_style_prefer_collection_expression = false:warning
dotnet_style_prefer_compound_assignment = true:warning
dotnet_style_prefer_conditional_expression_over_assignment = false:warning
dotnet_style_prefer_conditional_expression_over_return = false:warning
dotnet_style_prefer_foreach_explicit_cast_in_source = always:warning
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
dotnet_style_prefer_inferred_tuple_names = true:warning
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
dotnet_style_prefer_simplified_boolean_expressions = true:warning
dotnet_style_prefer_simplified_interpolation = true:warning
dotnet_style_readonly_field = true:warning
dotnet_code_quality_unused_parameters = all:warning
dotnet_remove_unnecessary_suppression_exclusions = none
dotnet_style_allow_multiple_blank_lines_experimental = false:warning
dotnet_style_allow_statement_immediately_after_block_experimental = true:warning
csharp_style_var_elsewhere = true:warning
csharp_style_var_for_built_in_types = true:warning
csharp_style_var_when_type_is_apparent = true:warning
csharp_style_expression_bodied_accessors = when_on_single_line:warning
csharp_style_expression_bodied_constructors = false:warning
csharp_style_expression_bodied_indexers = when_on_single_line:warning
csharp_style_expression_bodied_lambdas = when_on_single_line:warning
csharp_style_expression_bodied_local_functions = false:warning
csharp_style_expression_bodied_methods = false:warning
csharp_style_expression_bodied_operators = false:warning
csharp_style_expression_bodied_properties = when_on_single_line:warning
csharp_style_pattern_matching_over_as_with_null_check = true:warning
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
csharp_style_prefer_extended_property_pattern = true:warning
csharp_style_prefer_not_pattern = true:warning
csharp_style_prefer_pattern_matching = true:warning
csharp_style_prefer_switch_expression = false:warning
csharp_style_conditional_delegate_call = true:warning
csharp_prefer_static_anonymous_function = true:warning
csharp_prefer_static_local_function = true:warning
csharp_preferred_modifier_order = public,internal,private,protected,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:warning
csharp_style_prefer_readonly_struct = true:warning
csharp_style_prefer_readonly_struct_member = true:warning
csharp_prefer_braces = true:warning
csharp_prefer_simple_using_statement = true:warning
csharp_prefer_system_threading_lock = true:warning
csharp_style_namespace_declarations = file_scoped:warning
csharp_style_prefer_method_group_conversion = true:warning
csharp_style_prefer_primary_constructors = true:warning
csharp_style_prefer_top_level_statements = false:warning
csharp_prefer_simple_default_expression = true:warning
csharp_style_deconstructed_variable_declaration = true:warning
csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
csharp_style_inlined_variable_declaration = true:warning
csharp_style_prefer_index_operator = false:warning
csharp_style_prefer_local_over_anonymous_function = true:warning
csharp_style_prefer_null_check_over_type_check = true:warning
csharp_style_prefer_range_operator = false:warning
csharp_style_prefer_tuple_swap = true:warning
csharp_style_prefer_utf8_string_literals = true:warning
csharp_style_throw_expression = true:warning
csharp_style_unused_value_assignment_preference = discard_variable:warning
csharp_style_unused_value_expression_statement_preference = discard_variable:warning
csharp_using_directive_placement = outside_namespace:warning
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:warning
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:warning
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false:warning
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:warning
csharp_style_allow_embedded_statements_on_same_line_experimental = false:warning
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = no_change
csharp_indent_switch_labels = true
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false:warning
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
dotnet_naming_rule.interface_should_be_pascal.severity = warning
dotnet_naming_rule.interface_should_be_pascal.symbols = interface
dotnet_naming_rule.interface_should_be_pascal.style = pascal
dotnet_naming_rule.types_should_be_pascal.severity = warning
dotnet_naming_rule.types_should_be_pascal.symbols = types
dotnet_naming_rule.types_should_be_pascal.style = pascal
dotnet_naming_rule.non_field_members_should_be_pascal.severity = warning
dotnet_naming_rule.non_field_members_should_be_pascal.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal.style = pascal
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = *
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = *
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = *
dotnet_naming_symbols.non_field_members.required_modifiers =
dotnet_naming_style.pascal.required_prefix =
dotnet_naming_style.pascal.required_suffix =
dotnet_naming_style.pascal.word_separator =
dotnet_naming_style.pascal.capitalization = pascal_case

View File

@@ -1,10 +1,11 @@
# Set update schedule for GitHub Actions
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
# Check for updates to GitHub Actions every daily
interval: "daily"
- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "daily"

99
.github/workflows/build-linux.yml vendored Normal file
View File

@@ -0,0 +1,99 @@
name: release Linux
on:
workflow_dispatch:
inputs:
release_tag:
required: false
type: string
push:
branches:
- master
env:
OutputArch: "linux-64"
OutputArchArm: "linux-arm64"
OutputPath64: "${{ github.workspace }}/v2rayN/Release/linux-64"
OutputPathArm64: "${{ github.workspace }}/v2rayN/Release/linux-arm64"
jobs:
build:
strategy:
matrix:
configuration: [Release]
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4.2.2
- name: Setup
uses: actions/setup-dotnet@v4.3.0
with:
dotnet-version: '8.0.x'
- name: Build
run: |
cd v2rayN
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPath64
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-arm64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPathArm64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -o $OutputPath64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-arm64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -o $OutputPathArm64
- name: Upload build artifacts
uses: actions/upload-artifact@v4.6.0
with:
name: v2rayN-linux
path: |
${{ github.workspace }}/v2rayN/Release/linux*
# release debian package
- name: Package debian
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-debian.sh
./package-debian.sh $OutputArch $OutputPath64 ${{ github.event.inputs.release_tag }}
./package-debian.sh $OutputArchArm $OutputPathArm64 ${{ github.event.inputs.release_tag }}
- name: Upload deb to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.deb
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true
- name: Package AppImage
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-appimage.sh
./package-appimage.sh $OutputArch $OutputPath64 ${{ github.event.inputs.release_tag }}
./package-appimage.sh $OutputArchArm $OutputPathArm64 ${{ github.event.inputs.release_tag }}
- name: Upload AppImage to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.AppImage
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true
# release zip archive
- name: Package release zip archive
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-release-zip.sh
./package-release-zip.sh $OutputArch $OutputPath64
./package-release-zip.sh $OutputArchArm $OutputPathArm64
- name: Upload zip archive to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.zip
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true

View File

@@ -1,10 +1,20 @@
name: release macos
name: release macOS
on:
workflow_dispatch:
inputs:
release_tag:
required: false
type: string
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
branches:
- master
env:
OutputArch: "macos-64"
OutputArchArm: "macos-arm64"
OutputPath64: "${{ github.workspace }}/v2rayN/Release/macos-64"
OutputPathArm64: "${{ github.workspace }}/v2rayN/Release/macos-arm64"
jobs:
build:
@@ -12,21 +22,63 @@ jobs:
matrix:
configuration: [Release]
runs-on: macos-latest
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v4.2.2
- name: Setup
uses: actions/setup-dotnet@v4.3.0
with:
dotnet-version: '8.0.x'
- name: Build
run: cd v2rayN &&
./build-osx.sh
run: |
cd v2rayN
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPath64
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-arm64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -o $OutputPathArm64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -o $OutputPath64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-arm64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -o $OutputPathArm64
- name: Upload build artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v4.6.0
with:
name: v2rayN-osx
name: v2rayN-macos
path: |
./v2rayN/v2rayN-osx.zip
${{ github.workspace }}/v2rayN/Release/macos*
# release osx package
- name: Package osx
if: github.event.inputs.release_tag != ''
run: |
brew install create-dmg
chmod 755 package-osx.sh
./package-osx.sh $OutputArch $OutputPath64 ${{ github.event.inputs.release_tag }}
./package-osx.sh $OutputArchArm $OutputPathArm64 ${{ github.event.inputs.release_tag }}
- name: Upload dmg to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.dmg
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true
# release zip archive
- name: Package release zip archive
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-release-zip.sh
./package-release-zip.sh $OutputArch $OutputPath64
./package-release-zip.sh $OutputArchArm $OutputPathArm64
- name: Upload zip archive to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.zip
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true

View File

@@ -0,0 +1,50 @@
name: release Windows desktop (Avalonia UI)
on:
workflow_dispatch:
inputs:
release_tag:
required: false
type: string
push:
branches:
- master
env:
OutputArch: "windows-64"
OutputArchArm: "windows-arm64"
OutputPath64: "${{ github.workspace }}/v2rayN/Release/windows-64"
OutputPathArm64: "${{ github.workspace }}/v2rayN/Release/windows-arm64"
jobs:
build:
strategy:
matrix:
configuration: [Release]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4.2.2
- name: Setup
uses: actions/setup-dotnet@v4.3.0
with:
dotnet-version: '8.0.x'
- name: Build
run: |
cd v2rayN
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r win-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPath64
dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r win-arm64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPathArm64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -p:EnableWindowsTargeting=true -o $OutputPath64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -p:EnableWindowsTargeting=true -o $OutputPathArm64
- name: Upload build artifacts
uses: actions/upload-artifact@v4.6.0
with:
name: v2rayN-windows-desktop
path: |
${{ github.workspace }}/v2rayN/Release/windows*

71
.github/workflows/build-windows.yml vendored Normal file
View File

@@ -0,0 +1,71 @@
name: release Windows
on:
workflow_dispatch:
inputs:
release_tag:
required: false
type: string
push:
branches:
- master
env:
OutputArch: "windows-64"
OutputArchArm: "windows-arm64"
OutputPath64: "${{ github.workspace }}/v2rayN/Release/windows-64"
OutputPathArm64: "${{ github.workspace }}/v2rayN/Release/windows-arm64"
OutputPath64Sc: "${{ github.workspace }}/v2rayN/Release/windows-64-SelfContained"
jobs:
build:
strategy:
matrix:
configuration: [Release]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4.2.2
- name: Setup
uses: actions/setup-dotnet@v4.3.0
with:
dotnet-version: '8.0.x'
- name: Build
run: |
cd v2rayN
dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-x64 --self-contained=false -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPath64
dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-arm64 --self-contained=false -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPathArm64
dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPath64Sc
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained=false -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPath64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 --self-contained=false -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:EnableWindowsTargeting=true -o $OutputPathArm64
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained=true -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:PublishTrimmed=true -p:EnableWindowsTargeting=true -o $OutputPath64Sc
- name: Upload build artifacts
uses: actions/upload-artifact@v4.6.0
with:
name: v2rayN-windows
path: |
${{ github.workspace }}/v2rayN/Release/windows*
# release zip archive
- name: Package release zip archive
if: github.event.inputs.release_tag != ''
run: |
chmod 755 package-release-zip.sh
./package-release-zip.sh $OutputArch $OutputPath64
./package-release-zip.sh $OutputArchArm $OutputPathArm64
./package-release-zip.sh "windows-64-SelfContained" $OutputPath64Sc
- name: Upload zip archive to release
uses: svenstaro/upload-release-action@v2
if: github.event.inputs.release_tag != ''
with:
file: ${{ github.workspace }}/v2rayN*.zip
tag: ${{ github.event.inputs.release_tag }}
file_glob: true
prerelease: true

View File

@@ -1,60 +0,0 @@
name: release
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
strategy:
matrix:
configuration: [Release]
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
# - name: 删除工作流运行
# uses: Mattraks/delete-workflow-runs@v2
# with:
# token: ${{ github.token }}
# repository: ${{ github.repository }}
# retain_days: 0
# keep_minimum_runs: 1
- name: Build
run: cd v2rayN &&
./build.ps1
# - name: Package
# shell: pwsh
# run: |
# 7z a -mx9 ..\v2rayN.7z $env:Wap_Project_Directory
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: v2rayN
path: |
./v2rayN/v2rayN.zip
# - name: Release
# uses: softprops/action-gh-release@v1
# env:
# GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
# with:
# prerelease: ${{ contains(github.ref, '-') }}
# draft: false
# files: |
# .\v2rayN\v2rayN.zip
# body: |
# [![](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/netch_channel) [![](https://img.shields.io/badge/Telegram-Group-green)](https://t.me/netch_group)
# ## Changelogs
# * This is an automated deployment of GitHub Actions, the change log should be updated manually soon
# ## 更新日志
# * 这是 GitHub Actions 自动化部署,更新日志应该很快会手动更新

31
.github/workflows/winget-publish.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: WinGet submission on release
# based off of https://github.com/nushell/nushell/blob/main/.github/workflows/winget-submission.yml
# inspired by https://github.com/microsoft/PowerToys/blob/main/.github/workflows/package-submissions.yml
# Modified by @MerrickZ https://github.com/anpho
on:
workflow_dispatch:
release:
types: [released]
jobs:
winget:
name: Publish winget package
runs-on: windows-latest
steps:
- name: Submit v2ray package to Windows Package Manager Community Repository
run: |
$wingetPackage = "2dust.v2rayN"
$gitToken = "${{ secrets.PT_WINGET }}"
$github = Invoke-RestMethod -uri "https://api.github.com/repos/2dust/v2rayN/releases"
$targetRelease = $github | Where-Object -Property prerelease -match 'False' | Select -First 1
$installerUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'v2rayN-windows-64\.zip*' | Select -ExpandProperty browser_download_url
$ver = $targetRelease.tag_name
# getting latest wingetcreate file
iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
.\wingetcreate.exe update $wingetPackage -s -v $ver -u "$installerUrl|x64" -t $gitToken

415
.gitignore vendored
View File

@@ -1,19 +1,400 @@
################################################################################
# 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。
################################################################################
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
/v2rayN/.vs/
/v2rayN/v2rayN/bin/Debug/app.publish
/v2rayN/v2rayN/bin/Debug
/v2rayN/v2rayN/bin/Release
/v2rayN/v2rayN/obj/
/v2rayN/.vs/v2rayN/DesignTimeBuild
/v2rayN/packages
.vs/ProjectSettings.json
.vs/slnx.sqlite
.vs/VSWorkspaceState.json
/v2rayN/v2rayUpgrade/bin/Debug
/v2rayN/v2rayUpgrade/bin/Release
/v2rayN/v2rayUpgrade/obj/
# User-specific files
*.rsuser
*.suo
*.user
/.vs/v2rayN
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
# but not Directory.Build.rsp, as it configures directory-level build defaults
!Directory.Build.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml

View File

@@ -1,5 +1,5 @@
# v2rayN
A GUI client for Windows and Linux, support [Xray core](https://github.com/XTLS/Xray-core) and [others](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
A GUI client for Windows, Linux and macOS, support [Xray](https://github.com/XTLS/Xray-core) and [sing-box](https://github.com/SagerNet/sing-box/releases) and [others](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/2dust/v2rayN)](https://github.com/2dust/v2rayN/commits/master)
@@ -9,21 +9,8 @@ A GUI client for Windows and Linux, support [Xray core](https://github.com/XTLS/
## How to use
Check [Release files introduction](https://github.com/2dust/v2rayN/wiki/Release-files-introduction) and select the version you need to download
### Windows
- Run `v2rayN.exe`
### Linux
- `chmod +x v2rayN` Run `./v2rayN`
```
Debian 9+
Ubuntu 16.04+
Fedora 30+
```
## Requirements
- [Microsoft .NET 8.0 Desktop Runtime ](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
- [Supported cores](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)
Read the [Wiki](https://github.com/2dust/v2rayN/wiki) for details.
## Telegram Channel
[github_2dust](https://t.me/github_2dust)

71
package-appimage.sh Normal file
View File

@@ -0,0 +1,71 @@
#!/bin/bash
Arch="$1"
OutputPath="$2"
Version="$3"
FileName="v2rayN-${Arch}.zip"
wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName"
7z x $FileName -aoa
cp -rf v2rayN-${Arch}/* $OutputPath
PackagePath="v2rayN-Package-${Arch}"
mkdir -p "${PackagePath}/AppDir/opt"
cp -rf $OutputPath "${PackagePath}/AppDir/opt/v2rayN"
echo "When this file exists, app will not store configs under this folder" >"${PackagePath}/AppDir/opt/v2rayN/NotStoreConfigHere.txt"
if [ $Arch = "linux-64" ]; then
Arch2="x86_64"
Arch3="amd64"
else
Arch2="aarch64"
Arch3="arm64"
fi
echo $Arch2
# basic
cat >"${PackagePath}/AppDir/AppRun" <<-EOF
#!/bin/sh
HERE="\$(dirname "\$(readlink -f "\${0}")")"
export PATH="\${HERE}"/opt/v2rayN/:"\${PATH}"
export LD_LIBRARY_PATH="\${HERE}"/opt/v2rayN/:"\${LD_LIBRARY_PATH}"
exec "\${HERE}/opt/v2rayN/v2rayN" \$@
EOF
cat >"${PackagePath}/AppDir/v2rayN.desktop" <<-EOF
[Desktop Entry]
Name=v2rayN
Comment=A GUI client for Windows and Linux, support Xray core and sing-box-core and others
Exec=v2rayN
Icon=v2rayN
Terminal=false
Type=Application
Categories=Network;
EOF
sudo cp "${PackagePath}/AppDir/opt/v2rayN/v2rayN.png" "${PackagePath}/AppDir/v2rayN.png"
sudo dpkg --add-architecture ${Arch3}
mkdir deb_folder
cd deb_folder
apt download libicu74:${Arch3}
apt download libfontconfig1:${Arch3} || true
apt download libfontconfig:${Arch3} || true
mkdir ../output_folder
for deb in *.deb; do
dpkg-deb -x "$deb" ../output_folder/
done
cd ..
find output_folder -type f -name "*.so*" -exec cp {} ${PackagePath}/AppDir/opt/v2rayN/ \;
find output_folder -type l -name "*.so*" -exec cp {} ${PackagePath}/AppDir/opt/v2rayN/ \;
rm -rf deb_folder output_folder
sudo chmod 0755 "${PackagePath}/AppDir/opt/v2rayN/v2rayN"
sudo chmod 0755 "${PackagePath}/AppDir/AppRun"
# desktop && PATH
wget "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod a+x appimagetool-x86_64.AppImage
sudo apt install -y libfuse2
sudo ./appimagetool-x86_64.AppImage "${PackagePath}/AppDir"
sudo mv "v2rayN-${Arch2}.AppImage" "v2rayN-${Arch}.AppImage"

58
package-debian.sh Normal file
View File

@@ -0,0 +1,58 @@
#!/bin/bash
Arch="$1"
OutputPath="$2"
Version="$3"
FileName="v2rayN-${Arch}.zip"
wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName"
7z x $FileName
cp -rf v2rayN-${Arch}/* $OutputPath
PackagePath="v2rayN-Package-${Arch}"
mkdir -p "${PackagePath}/DEBIAN"
mkdir -p "${PackagePath}/opt"
cp -rf $OutputPath "${PackagePath}/opt/v2rayN"
echo "When this file exists, app will not store configs under this folder" > "${PackagePath}/opt/v2rayN/NotStoreConfigHere.txt"
if [ $Arch = "linux-64" ]; then
Arch2="amd64"
else
Arch2="arm64"
fi
echo $Arch2
# basic
cat >"${PackagePath}/DEBIAN/control" <<-EOF
Package: v2rayN
Version: $Version
Architecture: $Arch2
Maintainer: https://github.com/2dust/v2rayN
Description: A GUI client for Windows and Linux, support Xray core and sing-box-core and others
EOF
cat >"${PackagePath}/DEBIAN/postinst" <<-EOF
if [ ! -s /usr/share/applications/v2rayN.desktop ]; then
cat >/usr/share/applications/v2rayN.desktop<<-END
[Desktop Entry]
Name=v2rayN
Comment=A GUI client for Windows and Linux, support Xray core and sing-box-core and others
Exec=/opt/v2rayN/v2rayN
Icon=/opt/v2rayN/v2rayN.png
Terminal=false
Type=Application
Categories=Network;Application;
END
fi
update-desktop-database
EOF
sudo chmod 0755 "${PackagePath}/DEBIAN/postinst"
sudo chmod 0755 "${PackagePath}/opt/v2rayN/v2rayN"
sudo chmod 0755 "${PackagePath}/opt/v2rayN/AmazTool"
# desktop && PATH
sudo dpkg-deb -Zxz --build $PackagePath
sudo mv "${PackagePath}.deb" "v2rayN-${Arch}.deb"

58
package-osx.sh Executable file
View File

@@ -0,0 +1,58 @@
#!/bin/bash
Arch="$1"
OutputPath="$2"
Version="$3"
FileName="v2rayN-${Arch}.zip"
wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName"
7z x $FileName
cp -rf v2rayN-${Arch}/* $OutputPath
PackagePath="v2rayN-Package-${Arch}"
mkdir -p "$PackagePath/v2rayN.app/Contents/Resources"
cp -rf "$OutputPath" "$PackagePath/v2rayN.app/Contents/MacOS"
cp -f "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.icns" "$PackagePath/v2rayN.app/Contents/Resources/AppIcon.icns"
echo "When this file exists, app will not store configs under this folder" > "$PackagePath/v2rayN.app/Contents/MacOS/NotStoreConfigHere.txt"
chmod +x "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN"
cat >"$PackagePath/v2rayN.app/Contents/Info.plist" <<-EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>v2rayN</string>
<key>CFBundleExecutable</key>
<string>v2rayN</string>
<key>CFBundleIconFile</key>
<string>AppIcon</string>
<key>CFBundleIconName</key>
<string>AppIcon</string>
<key>CFBundleIdentifier</key>
<string>2dust.v2rayN</string>
<key>CFBundleName</key>
<string>v2rayN</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${Version}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>
EOF
create-dmg \
--volname "v2rayN Installer" \
--window-size 700 420 \
--icon-size 100 \
--icon "v2rayN.app" 160 185 \
--hide-extension "v2rayN.app" \
--app-drop-link 500 185 \
"v2rayN-${Arch}.dmg" \
"$PackagePath/v2rayN.app"

15
package-release-zip.sh Normal file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
Arch="$1"
OutputPath="$2"
OutputArch="v2rayN-${Arch}"
FileName="v2rayN-${Arch}.zip"
wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName"
ZipPath64="./$OutputArch"
mkdir $ZipPath64
cp -rf $OutputPath "$ZipPath64/$OutputArch"
7z a -tZip $FileName "$ZipPath64/$OutputArch" -mx1

363
v2rayN/.gitignore vendored
View File

@@ -1,363 +0,0 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

View File

@@ -1,27 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Copyright>Copyright © 2017-2024 (GPLv3)</Copyright>
<FileVersion>1.3.0</FileVersion>
</PropertyGroup>
<ItemGroup>
<Compile Update="Resx\Resource.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resource.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resx\Resource.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Update="Resx\Resource.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
</EmbeddedResource>
<Compile Update="Resx\Resource.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resource.resx</DependentUpon>
</Compile>
</ItemGroup>
</Project>

View File

@@ -15,8 +15,15 @@
return;
}
var fileName = Uri.UnescapeDataString(string.Join(" ", args));
UpgradeApp.Upgrade(fileName);
var argData = Uri.UnescapeDataString(string.Join(" ", args));
if (argData.Equals("rebootas"))
{
Thread.Sleep(1000);
Utils.StartV2RayN();
return;
}
UpgradeApp.Upgrade(argData);
}
}
}

View File

@@ -1,4 +1,4 @@
using System.Diagnostics;
using System.Diagnostics;
using System.IO.Compression;
using System.Text;
@@ -10,7 +10,7 @@ namespace AmazTool
{
Console.WriteLine($"{Resx.Resource.StartUnzipping}\n{fileName}");
Waiting(9);
Utils.Waiting(5);
if (!File.Exists(fileName))
{
@@ -21,11 +21,11 @@ namespace AmazTool
Console.WriteLine(Resx.Resource.TryTerminateProcess);
try
{
var existing = Process.GetProcessesByName(V2rayN);
var existing = Process.GetProcessesByName(Utils.V2rayN);
foreach (var pp in existing)
{
var path = pp.MainModule?.FileName ?? "";
if (path.StartsWith(GetPath(V2rayN)))
if (path.StartsWith(Utils.GetPath(Utils.V2rayN)))
{
pp?.Kill();
pp?.WaitForExit(1000);
@@ -42,12 +42,12 @@ namespace AmazTool
StringBuilder sb = new();
try
{
string thisAppOldFile = $"{GetExePath()}.tmp";
var thisAppOldFile = $"{Utils.GetExePath()}.tmp";
File.Delete(thisAppOldFile);
string splitKey = "/";
var splitKey = "/";
using ZipArchive archive = ZipFile.OpenRead(fileName);
foreach (ZipArchiveEntry entry in archive.Entries)
using var archive = ZipFile.OpenRead(fileName);
foreach (var entry in archive.Entries)
{
try
{
@@ -59,16 +59,22 @@ namespace AmazTool
Console.WriteLine(entry.FullName);
var lst = entry.FullName.Split(splitKey);
if (lst.Length == 1) continue;
string fullName = string.Join(splitKey, lst[1..lst.Length]);
if (lst.Length == 1)
continue;
var fullName = string.Join(splitKey, lst[1..lst.Length]);
if (string.Equals(GetExePath(), GetPath(fullName), StringComparison.OrdinalIgnoreCase))
if (string.Equals(Utils.GetExePath(), Utils.GetPath(fullName), StringComparison.OrdinalIgnoreCase))
{
File.Move(GetExePath(), thisAppOldFile);
File.Move(Utils.GetExePath(), thisAppOldFile);
}
string entryOutputPath = GetPath(fullName);
var entryOutputPath = Utils.GetPath(fullName);
Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!);
//In the bin folder, if the file already exists, it will be skipped
if (fullName.StartsWith("bin") && File.Exists(entryOutputPath))
{
continue;
}
entry.ExtractToFile(entryOutputPath, true);
Console.WriteLine(entryOutputPath);
@@ -91,48 +97,9 @@ namespace AmazTool
}
Console.WriteLine(Resx.Resource.Restartv2rayN);
Waiting(9);
Process process = new()
{
StartInfo = new()
{
UseShellExecute = true,
FileName = V2rayN,
WorkingDirectory = StartupPath()
}
};
process.Start();
}
Utils.Waiting(2);
private static string GetExePath()
{
return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
Utils.StartV2RayN();
}
private static string StartupPath()
{
return AppDomain.CurrentDomain.BaseDirectory;
}
private static string GetPath(string fileName)
{
string startupPath = StartupPath();
if (string.IsNullOrEmpty(fileName))
{
return startupPath;
}
return Path.Combine(startupPath, fileName);
}
private static void Waiting(int second)
{
for (var i = second; i > 0; i--)
{
Console.WriteLine(i);
Thread.Sleep(1000);
}
}
private static string V2rayN => "v2rayN";
}
}
}

52
v2rayN/AmazTool/Utils.cs Normal file
View File

@@ -0,0 +1,52 @@
using System.Diagnostics;
namespace AmazTool
{
internal class Utils
{
public static string GetExePath()
{
return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
}
public static string StartupPath()
{
return AppDomain.CurrentDomain.BaseDirectory;
}
public static string GetPath(string fileName)
{
string startupPath = StartupPath();
if (string.IsNullOrEmpty(fileName))
{
return startupPath;
}
return Path.Combine(startupPath, fileName);
}
public static string V2rayN => "v2rayN";
public static void StartV2RayN()
{
Process process = new()
{
StartInfo = new()
{
UseShellExecute = true,
FileName = V2rayN,
WorkingDirectory = StartupPath()
}
};
process.Start();
}
public static void Waiting(int second)
{
for (var i = second; i > 0; i--)
{
Console.WriteLine(i);
Thread.Sleep(1000);
}
}
}
}

View File

@@ -0,0 +1,33 @@
<Project>
<PropertyGroup>
<Version>7.8.1</Version>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
<NoWarn>CA1031;CS1591;NU1507;CA1416</NoWarn>
<Nullable>annotations</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Authors>2dust</Authors>
<PackageLicenseExpression>GPL-3.0</PackageLicenseExpression>
<Copyright>Copyright © 2017-$([System.DateTime]::UtcNow.Year) $(Authors)</Copyright>
<InvariantGlobalization>false</InvariantGlobalization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugType>embedded</DebugType>
<EventSourceSupport>false</EventSourceSupport>
<StackTraceSupport>false</StackTraceSupport>
<MetricsSupport>false</MetricsSupport>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
<UseSystemResourceKeys>true</UseSystemResourceKeys>
<PublishSingleFile>true</PublishSingleFile>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,30 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.2.3" />
<PackageVersion Include="Avalonia.Desktop" Version="11.2.3" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.2.3" />
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.2.3" />
<PackageVersion Include="CliWrap" Version="3.7.1" />
<PackageVersion Include="Downloader" Version="3.3.3" />
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.2.0" />
<PackageVersion Include="MaterialDesignThemes" Version="5.2.1" />
<PackageVersion Include="MessageBox.Avalonia" Version="3.2.0" />
<PackageVersion Include="QRCoder" Version="1.6.0" />
<PackageVersion Include="ReactiveUI" Version="20.1.63" />
<PackageVersion Include="ReactiveUI.Fody" Version="19.5.41" />
<PackageVersion Include="ReactiveUI.WPF" Version="20.1.63" />
<PackageVersion Include="Semi.Avalonia" Version="11.2.1.4" />
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.2.1.4" />
<PackageVersion Include="Splat.NLog" Version="15.3.1" />
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
<PackageVersion Include="TaskScheduler" Version="2.11.0" />
<PackageVersion Include="WebDav.Client" Version="2.8.0" />
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
<PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
</ItemGroup>
</Project>

View File

@@ -1,5 +1,5 @@
using Downloader;
using System.Net;
using Downloader;
namespace ServiceLib.Common
{
@@ -181,4 +181,4 @@ namespace ServiceLib.Common
downloadOpt = null;
}
}
}
}

View File

@@ -0,0 +1,61 @@
using System.Collections.Concurrent;
using System.Reflection;
namespace ServiceLib.Common;
public static class EmbedUtils
{
private static readonly string _tag = "EmbedUtils";
private static readonly ConcurrentDictionary<string, string> _dicEmbedCache = new();
/// <summary>
/// Get embedded text resources
/// </summary>
/// <param name="res"></param>
/// <returns></returns>
public static string GetEmbedText(string res)
{
if (_dicEmbedCache.TryGetValue(res, out var value))
{
return value;
}
var result = string.Empty;
try
{
var assembly = Assembly.GetExecutingAssembly();
using var stream = assembly.GetManifestResourceStream(res);
ArgumentNullException.ThrowIfNull(stream);
using StreamReader reader = new(stream);
result = reader.ReadToEnd();
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
_dicEmbedCache.TryAdd(res, result);
return result;
}
/// <summary>
/// Get local storage resources
/// </summary>
/// <returns></returns>
public static string? LoadResource(string? res)
{
try
{
if (File.Exists(res))
{
return File.ReadAllText(res);
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return null;
}
}

View File

@@ -6,6 +6,8 @@ namespace ServiceLib.Common
{
public static class FileManager
{
private static readonly string _tag = "FileManager";
public static bool ByteArrayToFile(string fileName, byte[] content)
{
try
@@ -15,7 +17,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return false;
}
@@ -30,7 +32,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}
@@ -46,7 +48,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}
@@ -60,7 +62,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}
@@ -79,7 +81,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
throw;
}
}
@@ -105,13 +107,13 @@ namespace ServiceLib.Common
}
catch (IOException ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
return false;
}
return true;
@@ -130,7 +132,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
return null;
}
}
@@ -148,13 +150,13 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
return false;
}
return true;
}
public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive, string? ignoredName)
public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive, bool overwrite, string? ignoredName = null)
{
// Get information about the source directory
var dir = new DirectoryInfo(sourceDir);
@@ -181,7 +183,11 @@ namespace ServiceLib.Common
continue;
}
var targetFilePath = Path.Combine(destinationDir, file.Name);
file.CopyTo(targetFilePath, true);
if (!overwrite && File.Exists(targetFilePath))
{
continue;
}
file.CopyTo(targetFilePath, overwrite);
}
// If recursive and copying subdirectories, recursively call this method
@@ -190,9 +196,30 @@ namespace ServiceLib.Common
foreach (var subDir in dirs)
{
var newDestinationDir = Path.Combine(destinationDir, subDir.Name);
CopyDirectory(subDir.FullName, newDestinationDir, true, ignoredName);
CopyDirectory(subDir.FullName, newDestinationDir, true, overwrite, ignoredName);
}
}
}
public static void DeleteExpiredFiles(string sourceDir, DateTime dtLine)
{
try
{
var files = Directory.GetFiles(sourceDir, "*.*");
foreach (var filePath in files)
{
var file = new FileInfo(filePath);
if (file.CreationTime >= dtLine)
{
continue;
}
file.Delete();
}
}
catch
{
// ignored
}
}
}
}

View File

@@ -10,7 +10,7 @@ namespace ServiceLib.Common
{
private static readonly Lazy<HttpClientHelper> _instance = new(() =>
{
HttpClientHandler handler = new() { UseCookies = false };
SocketsHttpHandler handler = new() { UseCookies = false };
HttpClientHelper helper = new(new HttpClient(handler));
return helper;
});
@@ -38,13 +38,15 @@ namespace ServiceLib.Common
public async Task<string?> GetAsync(string url)
{
if (Utils.IsNullOrEmpty(url)) return null;
if (Utils.IsNullOrEmpty(url))
return null;
return await httpClient.GetStringAsync(url);
}
public async Task<string?> GetAsync(HttpClient client, string url, CancellationToken token = default)
{
if (Utils.IsNullOrEmpty(url)) return null;
if (Utils.IsNullOrEmpty(url))
return null;
return await client.GetStringAsync(url, token);
}
@@ -75,11 +77,13 @@ namespace ServiceLib.Common
{
ArgumentNullException.ThrowIfNull(url);
ArgumentNullException.ThrowIfNull(fileName);
if (File.Exists(fileName)) File.Delete(fileName);
if (File.Exists(fileName))
File.Delete(fileName);
using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
if (!response.IsSuccessStatusCode) throw new Exception(response.StatusCode.ToString());
if (!response.IsSuccessStatusCode)
throw new Exception(response.StatusCode.ToString());
var total = response.Content.Headers.ContentLength ?? -1L;
var canReportProgress = total != -1 && progress != null;
@@ -97,7 +101,8 @@ namespace ServiceLib.Common
var read = await stream.ReadAsync(buffer, token);
totalRead += read;
if (read == 0) break;
if (read == 0)
break;
await file.WriteAsync(buffer.AsMemory(0, read), token);
if (canReportProgress)
@@ -183,4 +188,4 @@ namespace ServiceLib.Common
} while (isMoreToRead);
}
}
}
}

View File

@@ -1,4 +1,4 @@
using System.Diagnostics;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ServiceLib.Common
@@ -75,7 +75,8 @@ namespace ServiceLib.Common
private void Dispose(bool disposing)
{
if (disposed) return;
if (disposed)
return;
disposed = true;
if (disposing)
@@ -173,4 +174,4 @@ namespace ServiceLib.Common
}
#endregion Helper classes
}
}

View File

@@ -6,6 +6,8 @@ namespace ServiceLib.Common
{
public class JsonUtils
{
private static readonly string _tag = "JsonUtils";
/// <summary>
/// DeepCopy
/// </summary>
@@ -70,8 +72,9 @@ namespace ServiceLib.Common
/// </summary>
/// <param name="obj"></param>
/// <param name="indented"></param>
/// <param name="nullValue"></param>
/// <returns></returns>
public static string Serialize(object? obj, bool indented = true)
public static string Serialize(object? obj, bool indented = true, bool nullValue = false)
{
var result = string.Empty;
try
@@ -82,14 +85,38 @@ namespace ServiceLib.Common
}
var options = new JsonSerializerOptions
{
WriteIndented = indented ? true : false,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
WriteIndented = indented,
DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull
};
result = JsonSerializer.Serialize(obj, options);
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return result;
}
/// <summary>
/// Serialize Object to Json string
/// </summary>
/// <param name="obj"></param>
/// <param name="options"></param>
/// <returns></returns>
public static string Serialize(object? obj, JsonSerializerOptions options)
{
var result = string.Empty;
try
{
if (obj == null)
{
return result;
}
result = JsonSerializer.Serialize(obj, options);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return result;
}
@@ -100,38 +127,5 @@ namespace ServiceLib.Common
/// <param name="obj"></param>
/// <returns></returns>
public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj);
/// <summary>
/// Save as json file
/// </summary>
/// <param name="obj"></param>
/// <param name="filePath"></param>
/// <param name="nullValue"></param>
/// <returns></returns>
public static int ToFile(object? obj, string? filePath, bool nullValue = true)
{
if (filePath is null)
{
return -1;
}
try
{
using var file = File.Create(filePath);
var options = new JsonSerializerOptions
{
WriteIndented = true,
DefaultIgnoreCondition = nullValue ? JsonIgnoreCondition.Never : JsonIgnoreCondition.WhenWritingNull
};
JsonSerializer.Serialize(file, obj, options);
return 0;
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
return -1;
}
}
}
}

View File

@@ -1,4 +1,4 @@
using NLog;
using NLog;
using NLog.Config;
using NLog.Targets;
@@ -25,46 +25,18 @@ namespace ServiceLib.Common
}
}
public static void ClearLogs()
{
Task.Run(() =>
{
try
{
var now = DateTime.Now.AddMonths(-1);
var dir = Utils.GetLogPath();
var files = Directory.GetFiles(dir, "*.txt");
foreach (var filePath in files)
{
var file = new FileInfo(filePath);
if (file.CreationTime >= now) continue;
try
{
file.Delete();
}
catch
{
// ignored
}
}
}
catch
{
// ignored
}
});
}
public static void SaveLog(string strContent)
{
if (!LogManager.IsLoggingEnabled()) return;
if (!LogManager.IsLoggingEnabled())
return;
LogManager.GetLogger("Log1").Info(strContent);
}
public static void SaveLog(string strTitle, Exception ex)
{
if (!LogManager.IsLoggingEnabled()) return;
if (!LogManager.IsLoggingEnabled())
return;
var logger = LogManager.GetLogger("Log2");
logger.Debug($"{strTitle},{ex.Message}");
@@ -75,4 +47,4 @@ namespace ServiceLib.Common
}
}
}
}
}

View File

@@ -0,0 +1,150 @@
using System.Diagnostics;
namespace ServiceLib.Common;
public static class ProcUtils
{
private static readonly string _tag = "ProcUtils";
public static void ProcessStart(string? fileName, string arguments = "")
{
ProcessStart(fileName, arguments, null);
}
public static int? ProcessStart(string? fileName, string arguments, string? dir)
{
if (fileName.IsNullOrEmpty())
{
return null;
}
try
{
if (fileName.Contains(' '))
fileName = fileName.AppendQuotes();
if (arguments.Contains(' '))
arguments = arguments.AppendQuotes();
Process proc = new()
{
StartInfo = new ProcessStartInfo
{
UseShellExecute = true,
FileName = fileName,
Arguments = arguments,
WorkingDirectory = dir ?? string.Empty
}
};
proc.Start();
return dir is null ? null : proc.Id;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
return null;
}
public static void RebootAsAdmin(bool blAdmin = true)
{
try
{
ProcessStartInfo startInfo = new()
{
UseShellExecute = true,
Arguments = Global.RebootAs,
WorkingDirectory = Utils.StartupPath(),
FileName = Utils.GetExePath().AppendQuotes(),
Verb = blAdmin ? "runas" : null,
};
Process.Start(startInfo);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public static async Task ProcessKill(int pid)
{
try
{
await ProcessKill(Process.GetProcessById(pid), false);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
public static async Task ProcessKill(Process? proc, bool review)
{
if (proc is null)
{
return;
}
GetProcessKeyInfo(proc, review, out var procId, out var fileName, out var processName);
try
{ proc?.Kill(true); }
catch (Exception ex) { Logging.SaveLog(_tag, ex); }
try
{ proc?.Kill(); }
catch (Exception ex) { Logging.SaveLog(_tag, ex); }
try
{ proc?.Close(); }
catch (Exception ex) { Logging.SaveLog(_tag, ex); }
try
{ proc?.Dispose(); }
catch (Exception ex) { Logging.SaveLog(_tag, ex); }
await Task.Delay(300);
await ProcessKillByKeyInfo(review, procId, fileName, processName);
}
private static void GetProcessKeyInfo(Process? proc, bool review, out int? procId, out string? fileName, out string? processName)
{
procId = null;
fileName = null;
processName = null;
if (!review)
return;
try
{
procId = proc?.Id;
fileName = proc?.MainModule?.FileName;
processName = proc?.ProcessName;
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
private static async Task ProcessKillByKeyInfo(bool review, int? procId, string? fileName, string? processName)
{
if (review && procId != null && fileName != null)
{
try
{
var lstProc = Process.GetProcessesByName(processName);
foreach (var proc2 in lstProc)
{
if (proc2.Id == procId)
{
Logging.SaveLog($"{_tag}, KillProcess not completing the job, procId");
await ProcessKill(proc2, false);
}
if (proc2.MainModule != null && proc2.MainModule?.FileName == fileName)
{
Logging.SaveLog($"{_tag}, KillProcess not completing the job, fileName");
}
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
}
}

View File

@@ -1,50 +0,0 @@
using System.Linq.Expressions;
using System.Reflection;
namespace ServiceLib.Common
{
public static class QueryableExtension
{
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> query, string propertyName)
{
return _OrderBy<T>(query, propertyName, false);
}
public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> query, string propertyName)
{
return _OrderBy<T>(query, propertyName, true);
}
private static IOrderedQueryable<T> _OrderBy<T>(IQueryable<T> query, string propertyName, bool isDesc)
{
var methodname = (isDesc) ? "OrderByDescendingInternal" : "OrderByInternal";
var memberProp = typeof(T).GetProperty(propertyName);
var method = typeof(QueryableExtension).GetMethod(methodname)
.MakeGenericMethod(typeof(T), memberProp.PropertyType);
return (IOrderedQueryable<T>)method.Invoke(null, new object[] { query, memberProp });
}
public static IOrderedQueryable<T> OrderByInternal<T, TProp>(IQueryable<T> query, PropertyInfo memberProperty)
{//public
return query.OrderBy(_GetLambda<T, TProp>(memberProperty));
}
public static IOrderedQueryable<T> OrderByDescendingInternal<T, TProp>(IQueryable<T> query, PropertyInfo memberProperty)
{//public
return query.OrderByDescending(_GetLambda<T, TProp>(memberProperty));
}
private static Expression<Func<T, TProp>> _GetLambda<T, TProp>(PropertyInfo memberProperty)
{
if (memberProperty.PropertyType != typeof(TProp)) throw new Exception();
var thisArg = Expression.Parameter(typeof(T));
var lambda = Expression.Lambda<Func<T, TProp>>(Expression.Property(thisArg, memberProperty), thisArg);
return lambda;
}
}
}

View File

@@ -31,8 +31,8 @@
var parts = this.version.Split('.');
if (parts.Length == 2)
{
this.major = int.Parse(parts[0]);
this.minor = int.Parse(parts[1]);
this.major = int.Parse(parts.First());
this.minor = int.Parse(parts.Last());
this.patch = 0;
}
else if (parts.Length is 3 or 4)

View File

@@ -1,5 +1,5 @@
using SQLite;
using System.Collections;
using SQLite;
namespace ServiceLib.Common
{
@@ -73,5 +73,19 @@ namespace ServiceLib.Common
{
return _dbAsync.Table<T>();
}
public async Task DisposeDbConnectionAsync()
{
await Task.Factory.StartNew(() =>
{
_db?.Close();
_db?.Dispose();
_db = null;
_dbAsync?.GetConnection()?.Close();
_dbAsync?.GetConnection()?.Dispose();
_dbAsync = null;
});
}
}
}
}

View File

@@ -1,4 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.CodeAnalysis;
namespace ServiceLib.Common
{
@@ -21,8 +21,9 @@ namespace ServiceLib.Common
public static bool BeginWithAny(this string s, IEnumerable<char> chars)
{
if (s.IsNullOrEmpty()) return false;
return chars.Contains(s[0]);
if (s.IsNullOrEmpty())
return false;
return chars.Contains(s.First());
}
private static bool IsWhiteSpace(this string value)
@@ -34,7 +35,8 @@ namespace ServiceLib.Common
{
while (reader.ReadLine() is { } line)
{
if (line.IsWhiteSpace()) continue;
if (line.IsWhiteSpace())
continue;
yield return line;
}
}
@@ -61,7 +63,7 @@ namespace ServiceLib.Common
return string.Empty;
}
return char.ToUpper(value[0]) + value[1..];
return char.ToUpper(value.First()) + value[1..];
}
public static string AppendQuotes(this string value)
@@ -69,4 +71,4 @@ namespace ServiceLib.Common
return string.IsNullOrEmpty(value) ? string.Empty : $"\"{value}\"";
}
}
}
}

View File

@@ -1,5 +1,3 @@
using CliWrap;
using CliWrap.Buffered;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Net;
@@ -10,60 +8,14 @@ using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
using CliWrap;
using CliWrap.Buffered;
namespace ServiceLib.Common
{
public class Utils
{
#region
/// <summary>
/// 获取嵌入文本资源
/// </summary>
/// <param name="res"></param>
/// <returns></returns>
public static string GetEmbedText(string res)
{
var result = string.Empty;
try
{
var assembly = Assembly.GetExecutingAssembly();
using var stream = assembly.GetManifestResourceStream(res);
ArgumentNullException.ThrowIfNull(stream);
using StreamReader reader = new(stream);
result = reader.ReadToEnd();
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
return result;
}
/// <summary>
/// 取得存储资源
/// </summary>
/// <returns></returns>
public static string? LoadResource(string? res)
{
try
{
if (File.Exists(res))
{
return File.ReadAllText(res);
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
return null;
}
#endregion
private static readonly string _tag = "Utils";
#region
@@ -92,7 +44,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return string.Empty;
@@ -117,7 +69,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return null;
@@ -139,7 +91,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return null;
@@ -159,7 +111,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog("Base64Encode", ex);
Logging.SaveLog(_tag, ex);
}
return string.Empty;
@@ -174,7 +126,8 @@ namespace ServiceLib.Common
{
try
{
if (plainText.IsNullOrEmpty()) return "";
if (plainText.IsNullOrEmpty())
return "";
plainText = plainText.Trim()
.Replace(Environment.NewLine, "")
.Replace("\n", "")
@@ -193,7 +146,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog("Base64Decode", ex);
Logging.SaveLog(_tag, ex);
}
return string.Empty;
@@ -313,8 +266,8 @@ namespace ServiceLib.Common
continue;
}
var key = Uri.UnescapeDataString(keyValue[0]);
var val = Uri.UnescapeDataString(keyValue[1]);
var key = Uri.UnescapeDataString(keyValue.First());
var val = Uri.UnescapeDataString(keyValue.Last());
if (result[key] is null)
{
@@ -370,7 +323,8 @@ namespace ServiceLib.Common
public static bool IsBase64String(string? plainText)
{
if (plainText.IsNullOrEmpty()) return false;
if (plainText.IsNullOrEmpty())
return false;
var buffer = new Span<byte>(new byte[plainText.Length]);
return Convert.TryFromBase64String(plainText, buffer, out var _);
}
@@ -460,9 +414,12 @@ namespace ServiceLib.Common
if (IPAddress.TryParse(ip, out var address))
{
var ipBytes = address.GetAddressBytes();
if (ipBytes[0] == 10) return true;
if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) return true;
if (ipBytes[0] == 192 && ipBytes[1] == 168) return true;
if (ipBytes[0] == 10)
return true;
if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31)
return true;
if (ipBytes[0] == 192 && ipBytes[1] == 168)
return true;
}
return false;
@@ -483,7 +440,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return false;
@@ -515,10 +472,10 @@ namespace ServiceLib.Common
#region
public static bool UpgradeAppExists(out string fileName)
public static bool UpgradeAppExists(out string upgradeFileName)
{
fileName = Path.Combine(Utils.StartupPath(), GetExeName("AmazTool"));
return File.Exists(fileName);
upgradeFileName = Path.Combine(GetBaseDirectory(), GetExeName("AmazTool"));
return File.Exists(upgradeFileName);
}
/// <summary>
@@ -529,19 +486,13 @@ namespace ServiceLib.Common
{
try
{
if (blFull)
{
return
$"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture} - {File.GetLastWriteTime(GetExePath()):yyyy/MM/dd}";
}
else
{
return $"{Global.AppName}/{GetVersionInfo()}";
}
return blFull
? $"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture}"
: $"{Global.AppName}/{GetVersionInfo()}";
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return Global.AppName;
@@ -555,11 +506,16 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
return "0.0";
}
}
public static string GetRuntimeInfo()
{
return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion}";
}
/// <summary>
/// 取得GUID
/// </summary>
@@ -579,7 +535,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return string.Empty;
@@ -590,23 +546,6 @@ namespace ServiceLib.Common
return Guid.TryParse(strSrc, out _);
}
public static void ProcessStart(string? fileName, string arguments = "")
{
try
{
if (fileName.IsNullOrEmpty())
{
return;
}
Process.Start(new ProcessStartInfo(fileName, arguments) { UseShellExecute = true });
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
}
public static Dictionary<string, string> GetSystemHosts()
{
var systemHosts = new Dictionary<string, string>();
@@ -620,16 +559,18 @@ namespace ServiceLib.Common
foreach (var host in hostsList)
{
if (host.StartsWith("#")) continue;
if (host.StartsWith("#"))
continue;
var hostItem = host.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
if (hostItem.Length < 2) continue;
systemHosts.Add(hostItem[1], hostItem[0]);
if (hostItem.Length != 2)
continue;
systemHosts.Add(hostItem.Last(), hostItem.First());
}
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return systemHosts;
@@ -677,6 +618,33 @@ namespace ServiceLib.Common
#region TempPath
public static bool HasWritePermission()
{
try
{
//When this file exists, it is equivalent to having no permission to read and write
if (File.Exists(Path.Combine(GetBaseDirectory(), "NotStoreConfigHere.txt")))
{
return false;
}
var tempPath = Path.Combine(GetBaseDirectory(), "guiTemps");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
var fileName = Path.Combine(tempPath, GetGuid());
File.Create(fileName).Close();
File.Delete(fileName);
}
catch (Exception)
{
return false;
}
return true;
}
public static string GetPath(string fileName)
{
var startupPath = StartupPath();
@@ -688,6 +656,11 @@ namespace ServiceLib.Common
return Path.Combine(startupPath, fileName);
}
public static string GetBaseDirectory(string fileName = "")
{
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
}
public static string GetExePath()
{
return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;
@@ -695,7 +668,12 @@ namespace ServiceLib.Common
public static string StartupPath()
{
return AppDomain.CurrentDomain.BaseDirectory;
if (Environment.GetEnvironmentVariable(Global.LocalAppData) == "1")
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "v2rayN");
}
return GetBaseDirectory();
}
public static string GetTempPath(string filename = "")
@@ -818,6 +796,8 @@ namespace ServiceLib.Common
public static bool IsOSX() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
public static bool IsNonWindows() => !RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
public static string GetExeName(string name)
{
return IsWindows() ? $"{name}.exe" : name;
@@ -829,18 +809,19 @@ namespace ServiceLib.Common
{
return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
}
else
{
var id = GetLinuxUserId().Result ?? "1000";
if (int.TryParse(id, out var userId))
{
return userId == 0;
}
else
{
return false;
}
}
return false;
//else
//{
// var id = GetLinuxUserId().Result ?? "1000";
// if (int.TryParse(id, out var userId))
// {
// return userId == 0;
// }
// else
// {
// return false;
// }
//}
}
private static async Task<string?> GetLinuxUserId()
@@ -851,7 +832,11 @@ namespace ServiceLib.Common
public static async Task<string?> SetLinuxChmod(string? fileName)
{
if (fileName.IsNullOrEmpty()) return null;
if (fileName.IsNullOrEmpty())
return null;
if (fileName.Contains(' '))
fileName = fileName.AppendQuotes();
//File.SetUnixFileMode(fileName, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
var arg = new List<string>() { "-c", $"chmod +x {fileName}" };
return await GetCliWrapOutput("/bin/bash", arg);
}
@@ -870,6 +855,12 @@ namespace ServiceLib.Common
: Environment.GetEnvironmentVariable("HOME");
}
public static async Task<string?> GetListNetworkServices()
{
var arg = new List<string>() { "-c", $"networksetup -listallnetworkservices" };
return await GetCliWrapOutput("/bin/bash", arg);
}
#endregion Platform
}
}
}

View File

@@ -1,9 +1,13 @@
using Microsoft.Win32;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Win32;
namespace ServiceLib.Common
{
internal static class WindowsUtils
{
private static readonly string _tag = "WindowsUtils";
public static string? RegReadValue(string path, string name, string def)
{
RegistryKey? regKey = null;
@@ -15,7 +19,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
finally
{
@@ -41,12 +45,30 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
finally
{
regKey?.Close();
}
}
public static async Task RemoveTunDevice()
{
try
{
var sum = MD5.HashData(Encoding.UTF8.GetBytes("wintunsingbox_tun"));
var guid = new Guid(sum);
var pnpUtilPath = @"C:\Windows\System32\pnputil.exe";
var arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """;
// Try to remove the device
await Utils.GetCliWrapOutput(pnpUtilPath, arg);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
}
}
}

View File

@@ -6,6 +6,8 @@ namespace ServiceLib.Common
{
public class YamlUtils
{
private static readonly string _tag = "YamlUtils";
#region YAML
/// <summary>
@@ -26,7 +28,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog("FromYaml", ex);
Logging.SaveLog(_tag, ex);
return deserializer.Deserialize<T>("");
}
}
@@ -53,7 +55,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return result;
}
@@ -71,7 +73,7 @@ namespace ServiceLib.Common
}
catch (Exception ex)
{
Logging.SaveLog("PreprocessYaml", ex);
Logging.SaveLog(_tag, ex);
return null;
}
}

View File

@@ -1,19 +1,19 @@
namespace ServiceLib.Enums
namespace ServiceLib.Enums
{
public enum ECoreType
{
v2fly = 1,
Xray = 2,
v2fly_v5 = 4,
mihomo = 13,
hysteria = 21,
naiveproxy = 22,
tuic = 23,
sing_box = 24,
juicity = 25,
hysteria2 = 26,
brook = 27,
overtls = 28,
v2rayN = 99
}
}
}

View File

@@ -3,12 +3,12 @@
public enum EInboundProtocol
{
socks = 0,
http,
socks2,
http2,
socks3,
pac,
api,
api2,
mixed,
speedtest = 21
}
}

View File

@@ -6,6 +6,7 @@
SendMsgView,
SendSnackMsg,
RefreshProfiles,
StopSpeedtest
StopSpeedtest,
AppExit
}
}

View File

@@ -4,5 +4,6 @@
{
Default = 0,
Russia = 1,
Iran = 2,
}
}

View File

@@ -0,0 +1,13 @@
namespace ServiceLib.Enums
{
public enum ETheme
{
FollowSystem,
Dark,
Light,
Aquatic,
Desert,
Dusk,
NightSky
}
}

View File

@@ -1,4 +1,4 @@
namespace ServiceLib
namespace ServiceLib
{
public class Global
{
@@ -7,18 +7,8 @@
public const string AppName = "v2rayN";
public const string GithubUrl = "https://github.com";
public const string GithubApiUrl = "https://api.github.com/repos";
public const string V2flyCoreUrl = "https://github.com/v2fly/v2ray-core/releases";
public const string XrayCoreUrl = "https://github.com/XTLS/Xray-core/releases";
public const string NUrl = @"https://github.com/2dust/v2rayN/releases";
public const string MihomoCoreUrl = "https://github.com/MetaCubeX/mihomo/releases";
public const string HysteriaCoreUrl = "https://github.com/apernet/hysteria/releases";
public const string NaiveproxyCoreUrl = "https://github.com/klzgrad/naiveproxy/releases";
public const string TuicCoreUrl = "https://github.com/EAimTY/tuic/releases";
public const string SingboxCoreUrl = "https://github.com/SagerNet/sing-box/releases";
public const string GeoUrl = "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/{0}.dat";
public const string SpeedPingTestUrl = @"https://www.google.com/generate_204";
public const string JuicityCoreUrl = "https://github.com/juicity/juicity/releases";
public const string CustomRoutingListUrl = @"https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/";
public const string SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs";
public const string IPAPIUrl = "https://api.ip.sb/geoip";
@@ -63,81 +53,99 @@
public const string HttpProtocol = "http://";
public const string HttpsProtocol = "https://";
public const string SocksProtocol = "socks://";
public const string Socks5Protocol = "socks5://";
public const string UserEMail = "t@t.tt";
public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
public const string AutoRunName = "v2rayNAutoRun";
public const string CustomIconName = "v2rayN.ico";
public const string IEProxyExceptions = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*";
public const string SystemProxyExceptionsWindows = "localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*";
public const string SystemProxyExceptionsLinux = "localhost,127.0.0.0/8,::1";
public const string RoutingRuleComma = "<COMMA>";
public const string GrpcGunMode = "gun";
public const string GrpcMultiMode = "multi";
public const int MaxPort = 65536;
public const string DelayUnit = "";
public const string SpeedUnit = "";
public const int MinFontSize = 10;
public const int MinFontSize = 8;
public const string RebootAs = "rebootas";
public const string AvaAssets = "avares://v2rayN/Assets/";
public const string LocalAppData = "V2RAYN_LOCAL_APPLICATION_DATA";
public const string V2RayLocalAsset = "V2RAY_LOCATION_ASSET";
public const string XrayLocalAsset = "XRAY_LOCATION_ASSET";
public const int SpeedTestPageSize = 1000;
public static readonly List<string> IEProxyProtocols = new() {
"{ip}:{http_port}",
"socks={ip}:{socks_port}",
"http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}",
"http=http://{ip}:{http_port};https=http://{ip}:{http_port}",
""
};
public static readonly List<string> IEProxyProtocols =
[
"{ip}:{http_port}",
"socks={ip}:{socks_port}",
"http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}",
"http=http://{ip}:{http_port};https=http://{ip}:{http_port}",
""
];
public static readonly List<string> SubConvertUrls = new List<string> {
@"https://sub.xeton.dev/sub?url={0}",
@"https://api.dler.io/sub?url={0}",
@"http://127.0.0.1:25500/sub?url={0}",
""
};
public static readonly List<string> SubConvertUrls =
[
@"https://sub.xeton.dev/sub?url={0}",
@"https://api.dler.io/sub?url={0}",
@"http://127.0.0.1:25500/sub?url={0}",
""
];
public static readonly List<string> SubConvertConfig = new List<string> {
@"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini"
};
public static readonly List<string> SubConvertConfig =
[@"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini"];
public static readonly List<string> SubConvertTargets = new List<string> {
"",
"mixed",
"v2ray",
"clash",
"ss",
};
public static readonly List<string> SubConvertTargets =
[
"",
"mixed",
"v2ray",
"clash",
"ss"
];
public static readonly List<string> SpeedTestUrls = new() {
public static readonly List<string> SpeedTestUrls =
[
@"https://speed.cloudflare.com/__down?bytes=100000000",
@"https://speed.cloudflare.com/__down?bytes=50000000",
@"https://speed.cloudflare.com/__down?bytes=10000000",
@"https://cachefly.cachefly.net/50mb.test",
};
@"https://cachefly.cachefly.net/50mb.test"
];
public static readonly List<string> SpeedPingTestUrls = new() {
public static readonly List<string> SpeedPingTestUrls =
[
@"https://www.google.com/generate_204",
@"https://www.gstatic.com/generate_204",
@"https://www.apple.com/library/test/success.html",
@"http://www.msftconnecttest.com/connecttest.txt",
};
@"http://www.msftconnecttest.com/connecttest.txt"
];
public static readonly List<string> GeoFilesSources = new() {
public static readonly List<string> GeoFilesSources =
[
"",
@"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"
];
public static readonly List<string> SingboxRulesetSources = new() {
public static readonly List<string> SingboxRulesetSources =
[
"",
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-rules-dat@release/sing-box/rule-set-{0}/{1}.srs",
};
@"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-sing-box-rules@rule-set/{1}.srs"
];
public static readonly List<string> RoutingRulesSources = new() {
public static readonly List<string> RoutingRulesSources =
[
"",
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/template.json",
};
@"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/template.json"
];
public static readonly List<string> DNSTemplateSources = new() {
public static readonly List<string> DNSTemplateSources =
[
"",
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/",
};
@"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/"
];
public static readonly Dictionary<string, string> UserAgentTexts = new()
{
@@ -152,67 +160,355 @@
public static readonly Dictionary<EConfigType, string> ProtocolShares = new()
{
{EConfigType.VMess,"vmess://"},
{EConfigType.Shadowsocks,"ss://"},
{EConfigType.SOCKS,"socks://"},
{EConfigType.VLESS,"vless://"},
{EConfigType.Trojan,"trojan://"},
{EConfigType.Hysteria2,"hysteria2://"},
{EConfigType.TUIC,"tuic://"},
{EConfigType.WireGuard,"wireguard://"}
{ EConfigType.VMess, "vmess://" },
{ EConfigType.Shadowsocks, "ss://" },
{ EConfigType.SOCKS, "socks://" },
{ EConfigType.VLESS, "vless://" },
{ EConfigType.Trojan, "trojan://" },
{ EConfigType.Hysteria2, "hysteria2://" },
{ EConfigType.TUIC, "tuic://" },
{ EConfigType.WireGuard, "wireguard://" }
};
public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()
{
{EConfigType.VMess,"vmess"},
{EConfigType.Shadowsocks,"shadowsocks"},
{EConfigType.SOCKS,"socks"},
{EConfigType.HTTP,"http"},
{EConfigType.VLESS,"vless"},
{EConfigType.Trojan,"trojan"},
{EConfigType.Hysteria2,"hysteria2"},
{EConfigType.TUIC,"tuic"},
{EConfigType.WireGuard,"wireguard"}
{ EConfigType.VMess, "vmess" },
{ EConfigType.Shadowsocks, "shadowsocks" },
{ EConfigType.SOCKS, "socks" },
{ EConfigType.HTTP, "http" },
{ EConfigType.VLESS, "vless" },
{ EConfigType.Trojan, "trojan" },
{ EConfigType.Hysteria2, "hysteria2" },
{ EConfigType.TUIC, "tuic" },
{ EConfigType.WireGuard, "wireguard" }
};
public static readonly List<string> VmessSecurities = new() { "aes-128-gcm", "chacha20-poly1305", "auto", "none", "zero" };
public static readonly List<string> SsSecurities = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "none", "plain" };
public static readonly List<string> SsSecuritiesInXray = new() { "aes-256-gcm", "aes-128-gcm", "chacha20-poly1305", "chacha20-ietf-poly1305", "xchacha20-poly1305", "xchacha20-ietf-poly1305", "none", "plain", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" };
public static readonly List<string> SsSecuritiesInSingbox = new() { "aes-256-gcm", "aes-192-gcm", "aes-128-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", "none", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "rc4-md5", "chacha20-ietf", "xchacha20" };
public static readonly List<string> Flows = new() { "", "xtls-rprx-vision", "xtls-rprx-vision-udp443" };
public static readonly List<string> Networks = new() { "tcp", "kcp", "ws", "httpupgrade", "xhttp", "h2", "quic", "grpc" };
public static readonly List<string> KcpHeaderTypes = new() { "srtp", "utp", "wechat-video", "dtls", "wireguard" };
public static readonly List<string> CoreTypes = new() { "v2fly", "Xray", "sing_box" };
public static readonly List<string> CoreTypes4VLESS = new() { "Xray", "sing_box" };
public static readonly List<string> DomainStrategies = new() { "AsIs", "IPIfNonMatch", "IPOnDemand" };
public static readonly List<string> DomainStrategies4Singbox = new() { "ipv4_only", "ipv6_only", "prefer_ipv4", "prefer_ipv6", "" };
public static readonly List<string> DomainMatchers = new() { "linear", "mph", "" };
public static readonly List<string> Fingerprints = new() { "chrome", "firefox", "safari", "ios", "android", "edge", "360", "qq", "random", "randomized", "" };
public static readonly List<string> UserAgent = new() { "chrome", "firefox", "safari", "edge", "none" };
public static readonly List<string> XhttpMode = new() { "auto", "packet-up", "stream-up" };
public static readonly List<string> VmessSecurities =
[
"aes-128-gcm",
"chacha20-poly1305",
"auto",
"none",
"zero"
];
public static readonly List<string> AllowInsecure = new() { "true", "false", "" };
public static readonly List<string> DomainStrategy4Freedoms = new() { "AsIs", "UseIP", "UseIPv4", "UseIPv6", "" };
public static readonly List<string> SingboxDomainStrategy4Out = new() { "ipv4_only", "prefer_ipv4", "prefer_ipv6", "ipv6_only", "" };
public static readonly List<string> DomainDNSAddress = ["223.5.5.5", "223.6.6.6", "localhost"];
public static readonly List<string> SingboxDomainDNSAddress = ["223.5.5.5", "223.6.6.6", "dhcp://auto"];
public static readonly List<string> Languages = new() { "zh-Hans", "zh-Hant", "en", "fa-Ir", "ru" };
public static readonly List<string> Alpns = new() { "h3", "h2", "http/1.1", "h3,h2", "h2,http/1.1", "h3,h2,http/1.1", "" };
public static readonly List<string> LogLevels = new() { "debug", "info", "warning", "error", "none" };
public static readonly List<string> InboundTags = new() { "socks", "http", "socks2", "http2" };
public static readonly List<string> RuleProtocols = new() { "http", "tls", "bittorrent" };
public static readonly List<string> RuleNetworks = new() { "", "tcp", "udp", "tcp,udp" };
public static readonly List<string> destOverrideProtocols = ["http", "tls", "quic", "fakedns", "fakedns+others"];
public static readonly List<string> TunMtus = new() { "1280", "1408", "1500", "9000" };
public static readonly List<string> TunStacks = new() { "gvisor", "system" };
public static readonly List<string> PresetMsgFilters = new() { "proxy", "direct", "block", "" };
public static readonly List<string> SingboxMuxs = new() { "h2mux", "smux", "yamux", "" };
public static readonly List<string> TuicCongestionControls = new() { "cubic", "new_reno", "bbr" };
public static readonly List<string> SsSecurities =
[
"aes-256-gcm",
"aes-128-gcm",
"chacha20-poly1305",
"chacha20-ietf-poly1305",
"none",
"plain"
];
public static readonly List<string> allowSelectType = new() { "selector", "urltest", "loadbalance", "fallback" };
public static readonly List<string> notAllowTestType = new() { "selector", "urltest", "direct", "reject", "compatible", "pass", "loadbalance", "fallback" };
public static readonly List<string> proxyVehicleType = new() { "file", "http" };
public static readonly List<string> SsSecuritiesInXray =
[
"aes-256-gcm",
"aes-128-gcm",
"chacha20-poly1305",
"chacha20-ietf-poly1305",
"xchacha20-poly1305",
"xchacha20-ietf-poly1305",
"none",
"plain",
"2022-blake3-aes-128-gcm",
"2022-blake3-aes-256-gcm",
"2022-blake3-chacha20-poly1305"
];
public static readonly List<string> SsSecuritiesInSingbox =
[
"aes-256-gcm",
"aes-192-gcm",
"aes-128-gcm",
"chacha20-ietf-poly1305",
"xchacha20-ietf-poly1305",
"none",
"2022-blake3-aes-128-gcm",
"2022-blake3-aes-256-gcm",
"2022-blake3-chacha20-poly1305",
"aes-128-ctr",
"aes-192-ctr",
"aes-256-ctr",
"aes-128-cfb",
"aes-192-cfb",
"aes-256-cfb",
"rc4-md5",
"chacha20-ietf",
"xchacha20"
];
public static readonly List<string> Flows =
[
"",
"xtls-rprx-vision",
"xtls-rprx-vision-udp443"
];
public static readonly List<string> Networks =
[
"tcp",
"kcp",
"ws",
"httpupgrade",
"xhttp",
"h2",
"quic",
"grpc"
];
public static readonly List<string> KcpHeaderTypes =
[
"srtp",
"utp",
"wechat-video",
"dtls",
"wireguard"
];
public static readonly List<string> CoreTypes =
[
"Xray",
"sing_box"
];
public static readonly List<string> DomainStrategies =
[
"AsIs",
"IPIfNonMatch",
"IPOnDemand"
];
public static readonly List<string> DomainStrategies4Singbox =
[
"ipv4_only",
"ipv6_only",
"prefer_ipv4",
"prefer_ipv6",
""
];
public static readonly List<string> DomainMatchers =
[
"linear",
"mph",
""
];
public static readonly List<string> Fingerprints =
[
"chrome",
"firefox",
"safari",
"ios",
"android",
"edge",
"360",
"qq",
"random",
"randomized",
""
];
public static readonly List<string> UserAgent =
[
"chrome",
"firefox",
"safari",
"edge",
"none"
];
public static readonly List<string> XhttpMode =
[
"auto",
"packet-up",
"stream-up",
"stream-one"
];
public static readonly List<string> AllowInsecure =
[
"true",
"false",
""
];
public static readonly List<string> DomainStrategy4Freedoms =
[
"AsIs",
"UseIP",
"UseIPv4",
"UseIPv6",
""
];
public static readonly List<string> SingboxDomainStrategy4Out =
[
"ipv4_only",
"prefer_ipv4",
"prefer_ipv6",
"ipv6_only",
""
];
public static readonly List<string> DomainDNSAddress =
[
"223.5.5.5",
"223.6.6.6",
"localhost"
];
public static readonly List<string> SingboxDomainDNSAddress =
[
"223.5.5.5",
"223.6.6.6",
"dhcp://auto"
];
public static readonly List<string> Languages =
[
"zh-Hans",
"zh-Hant",
"en",
"fa-Ir",
"ru",
"hu"
];
public static readonly List<string> Alpns =
[
"h3",
"h2",
"http/1.1",
"h3,h2",
"h2,http/1.1",
"h3,h2,http/1.1",
""
];
public static readonly List<string> LogLevels =
[
"debug",
"info",
"warning",
"error",
"none"
];
public static readonly List<string> InboundTags =
[
"socks",
"socks2",
"socks3"
];
public static readonly List<string> RuleProtocols =
[
"http",
"tls",
"bittorrent"
];
public static readonly List<string> RuleNetworks =
[
"",
"tcp",
"udp",
"tcp,udp"
];
public static readonly List<string> destOverrideProtocols =
[
"http",
"tls",
"quic",
"fakedns",
"fakedns+others"
];
public static readonly List<string> TunMtus =
[
"1280",
"1408",
"1500",
"9000"
];
public static readonly List<string> TunStacks =
[
"gvisor",
"system",
"mixed"
];
public static readonly List<string> PresetMsgFilters =
[
"proxy",
"direct",
"block",
""
];
public static readonly List<string> SingboxMuxs =
[
"h2mux",
"smux",
"yamux",
""
];
public static readonly List<string> TuicCongestionControls =
[
"cubic",
"new_reno",
"bbr"
];
public static readonly List<string> allowSelectType =
[
"selector",
"urltest",
"loadbalance",
"fallback"
];
public static readonly List<string> notAllowTestType =
[
"selector",
"urltest",
"direct",
"reject",
"compatible",
"pass",
"loadbalance",
"fallback"
];
public static readonly List<string> proxyVehicleType =
[
"file",
"http"
];
public static readonly Dictionary<ECoreType, string> CoreUrls = new()
{
{ ECoreType.v2fly, "v2fly/v2ray-core" },
{ ECoreType.v2fly_v5, "v2fly/v2ray-core" },
{ ECoreType.Xray, "XTLS/Xray-core" },
{ ECoreType.sing_box, "SagerNet/sing-box" },
{ ECoreType.mihomo, "MetaCubeX/mihomo" },
{ ECoreType.hysteria, "apernet/hysteria" },
{ ECoreType.hysteria2, "apernet/hysteria" },
{ ECoreType.naiveproxy, "klzgrad/naiveproxy" },
{ ECoreType.tuic, "EAimTY/tuic" },
{ ECoreType.juicity, "juicity/juicity" },
{ ECoreType.brook, "txthinking/brook" },
{ ECoreType.overtls, "ShadowsocksR-Live/overtls" },
{ ECoreType.v2rayN, "2dust/v2rayN" },
};
#endregion const
}
}
}

View File

@@ -27,7 +27,7 @@
get
{
_statePort2 ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api2));
return _statePort2.Value;
return _statePort2.Value + (_config.TunModeItem.EnableTun ? 1 : 0);
}
}
@@ -46,11 +46,18 @@
public bool InitApp()
{
_config = ConfigHandler.LoadConfig();
if (_config == null)
if (Utils.HasWritePermission() == false)
{
Environment.SetEnvironmentVariable(Global.LocalAppData, "1", EnvironmentVariableTarget.Process);
}
Logging.Setup();
var config = ConfigHandler.LoadConfig();
if (config == null)
{
return false;
}
_config = config;
Thread.CurrentThread.CurrentUICulture = new(_config.UiItem.CurrentLanguage);
//Under Win10
@@ -70,15 +77,30 @@
public bool InitComponents()
{
Logging.Setup();
Logging.SaveLog($"v2rayN start up | {Utils.GetRuntimeInfo()}");
Logging.LoggingEnabled(_config.GuiItem.EnableLog);
Logging.SaveLog($"v2rayN start up | {Utils.GetVersion()} | {Utils.GetExePath()}");
Logging.SaveLog($"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
Logging.ClearLogs();
ClearExpiredFiles();
return true;
}
public bool Reset()
{
_statePort = null;
_statePort2 = null;
return true;
}
private void ClearExpiredFiles()
{
Task.Run(() =>
{
FileManager.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1));
FileManager.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1));
});
}
#endregion Init
#region Config
@@ -94,7 +116,13 @@
if (Utils.IsWindows())
{
_processJob ??= new();
_processJob?.AddProcess(processHandle);
try
{
_processJob?.AddProcess(processHandle);
}
catch
{
}
}
}
@@ -107,7 +135,7 @@
return await SQLiteHelper.Instance.TableAsync<SubItem>().OrderBy(t => t.Sort).ToListAsync();
}
public async Task<SubItem?> GetSubItem(string subid)
public async Task<SubItem?> GetSubItem(string? subid)
{
return await SQLiteHelper.Instance.TableAsync<SubItem>().FirstOrDefaultAsync(t => t.Id == subid);
}
@@ -152,45 +180,6 @@
return await SQLiteHelper.Instance.QueryAsync<ProfileItemModel>(sql);
}
public async Task<List<ProfileItemModel>?> ProfileItemsEx(string subid, string filter)
{
var lstModel = await ProfileItems(_config.SubIndexId, filter);
await ConfigHandler.SetDefaultServer(_config, lstModel);
var lstServerStat = (_config.GuiItem.EnableStatistics ? StatisticsHandler.Instance.ServerStat : null) ?? [];
var lstProfileExs = await ProfileExHandler.Instance.GetProfileExs();
lstModel = (from t in lstModel
join t2 in lstServerStat on t.IndexId equals t2.IndexId into t2b
from t22 in t2b.DefaultIfEmpty()
join t3 in lstProfileExs on t.IndexId equals t3.IndexId into t3b
from t33 in t3b.DefaultIfEmpty()
select new ProfileItemModel
{
IndexId = t.IndexId,
ConfigType = t.ConfigType,
Remarks = t.Remarks,
Address = t.Address,
Port = t.Port,
Security = t.Security,
Network = t.Network,
StreamSecurity = t.StreamSecurity,
Subid = t.Subid,
SubRemarks = t.SubRemarks,
IsActive = t.IndexId == _config.IndexId,
Sort = t33 == null ? 0 : t33.Sort,
Delay = t33 == null ? 0 : t33.Delay,
DelayVal = t33?.Delay != 0 ? $"{t33?.Delay} {Global.DelayUnit}" : string.Empty,
SpeedVal = t33?.Speed != 0 ? $"{t33?.Speed} {Global.SpeedUnit}" : string.Empty,
TodayDown = t22 == null ? "" : Utils.HumanFy(t22.TodayDown),
TodayUp = t22 == null ? "" : Utils.HumanFy(t22.TodayUp),
TotalDown = t22 == null ? "" : Utils.HumanFy(t22.TotalDown),
TotalUp = t22 == null ? "" : Utils.HumanFy(t22.TotalUp)
}).OrderBy(t => t.Sort).ToList();
return lstModel;
}
public async Task<ProfileItem?> GetProfileItem(string indexId)
{
if (Utils.IsNullOrEmpty(indexId))
@@ -257,16 +246,8 @@
return (ECoreType)profileItem.CoreType;
}
if (_config.CoreTypeItem == null)
{
return ECoreType.Xray;
}
var item = _config.CoreTypeItem.FirstOrDefault(it => it.ConfigType == eConfigType);
if (item == null)
{
return ECoreType.Xray;
}
return item.CoreType;
var item = _config.CoreTypeItem?.FirstOrDefault(it => it.ConfigType == eConfigType);
return item?.CoreType ?? ECoreType.Xray;
}
#endregion Core Type

View File

@@ -1,10 +1,12 @@
using System.Security.Principal;
using System.Security.Principal;
using System.Text.RegularExpressions;
namespace ServiceLib.Handler
{
public static class AutoStartupHandler
{
private static readonly string _tag = "AutoStartupHandler";
public static async Task<bool> UpdateTask(Config config)
{
if (Utils.IsWindows())
@@ -25,9 +27,14 @@ namespace ServiceLib.Handler
await SetTaskLinux();
}
}
else if(Utils.IsOSX())
else if (Utils.IsOSX())
{
//TODO
await ClearTaskOSX();
if (config.GuiItem.AutoRun)
{
await SetTaskOSX();
}
}
return true;
@@ -43,6 +50,8 @@ namespace ServiceLib.Handler
{
AutoStartTaskService(autoRunName, "", "");
}
await Task.CompletedTask;
}
private static async Task SetTaskWindows()
@@ -62,8 +71,9 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
await Task.CompletedTask;
}
/// <summary>
@@ -123,15 +133,16 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
await Task.CompletedTask;
}
private static async Task SetTaskLinux()
{
try
{
var linuxConfig = Utils.GetEmbedText(Global.LinuxAutostartConfig);
var linuxConfig = EmbedUtils.GetEmbedText(Global.LinuxAutostartConfig);
if (linuxConfig.IsNotEmpty())
{
linuxConfig = linuxConfig.Replace("$ExecPath$", Utils.GetExePath());
@@ -143,7 +154,7 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}
@@ -155,5 +166,77 @@ namespace ServiceLib.Handler
}
#endregion Linux
#region macOS
private static async Task ClearTaskOSX()
{
try
{
var launchAgentPath = GetLaunchAgentPathMacOS();
if (File.Exists(launchAgentPath))
{
var args = new[] { "-c", $"launchctl unload -w \"{launchAgentPath}\"" };
await Utils.GetCliWrapOutput("/bin/bash", args);
File.Delete(launchAgentPath);
}
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
private static async Task SetTaskOSX()
{
try
{
var plistContent = GenerateLaunchAgentPlist();
var launchAgentPath = GetLaunchAgentPathMacOS();
await File.WriteAllTextAsync(launchAgentPath, plistContent);
var args = new[] { "-c", $"launchctl load -w \"{launchAgentPath}\"" };
await Utils.GetCliWrapOutput("/bin/bash", args);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
private static string GetLaunchAgentPathMacOS()
{
var homePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
var launchAgentPath = Path.Combine(homePath, "Library", "LaunchAgents", $"{Global.AppName}-LaunchAgent.plist");
Directory.CreateDirectory(Path.GetDirectoryName(launchAgentPath));
return launchAgentPath;
}
private static string GenerateLaunchAgentPlist()
{
var exePath = Utils.GetExePath();
var appName = Path.GetFileNameWithoutExtension(exePath);
return $@"<?xml version=""1.0"" encoding=""UTF-8""?>
<!DOCTYPE plist PUBLIC ""-//Apple//DTD PLIST 1.0//EN"" ""http://www.apple.com/DTDs/PropertyList-1.0.dtd"">
<plist version=""1.0"">
<dict>
<key>Label</key>
<string>{Global.AppName}-LaunchAgent</string>
<key>ProgramArguments</key>
<array>
<string>/bin/sh</string>
<string>-c</string>
<string>if ! pgrep -x ""{appName}"" > /dev/null; then ""{exePath}""; fi</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<false/>
</dict>
</plist>";
}
#endregion macOS
}
}
}

View File

@@ -9,6 +9,7 @@ namespace ServiceLib.Handler
private Dictionary<string, ProxiesItem>? _proxies;
public Dictionary<string, object> ProfileContent { get; set; }
private static readonly string _tag = "ClashApiHandler";
public async Task<Tuple<ClashProxies, ClashProviders>?> GetClashProxiesAsync(Config config)
{
@@ -109,7 +110,7 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog("GetClashProxyGroups", ex);
Logging.SaveLog(_tag, ex);
return null;
}
}
@@ -125,7 +126,7 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}
@@ -153,7 +154,7 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}
@@ -169,7 +170,7 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return null;
@@ -184,7 +185,7 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}

View File

@@ -9,7 +9,7 @@ namespace ServiceLib.Handler
public class ConfigHandler
{
private static readonly string _configRes = Global.ConfigFileName;
private static readonly object _objLock = new();
private static readonly string _tag = "ConfigHandler";
#region ConfigHandler
@@ -21,7 +21,7 @@ namespace ServiceLib.Handler
public static Config? LoadConfig()
{
Config? config = null;
var result = Utils.LoadResource(Utils.GetConfigPath(_configRes));
var result = EmbedUtils.LoadResource(Utils.GetConfigPath(_configRes));
if (Utils.IsNotEmpty(result))
{
config = JsonUtils.Deserialize<Config>(result);
@@ -62,15 +62,14 @@ namespace ServiceLib.Handler
{
if (config.Inbound.Count > 0)
{
config.Inbound[0].Protocol = EInboundProtocol.socks.ToString();
config.Inbound.First().Protocol = EInboundProtocol.socks.ToString();
}
}
config.RoutingBasicItem ??= new();
if (Utils.IsNullOrEmpty(config.RoutingBasicItem.DomainStrategy))
{
config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies[0];//"IPIfNonMatch";
config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies.First();
}
config.KcpItem ??= new KcpItem
@@ -95,10 +94,7 @@ namespace ServiceLib.Handler
EnableTun = false,
Mtu = 9000,
};
config.GuiItem ??= new()
{
EnableStatistics = false,
};
config.GuiItem ??= new();
config.MsgUIItem ??= new();
config.UiItem ??= new UIItem()
@@ -109,21 +105,12 @@ namespace ServiceLib.Handler
if (Utils.IsNullOrEmpty(config.UiItem.CurrentLanguage))
{
if (Thread.CurrentThread.CurrentCulture.Name.Equals("zh-cn", StringComparison.CurrentCultureIgnoreCase))
{
config.UiItem.CurrentLanguage = Global.Languages[0];
}
else
{
config.UiItem.CurrentLanguage = Global.Languages[2];
}
config.UiItem.CurrentLanguage = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName.Equals("zh", StringComparison.CurrentCultureIgnoreCase)
? Global.Languages.First()
: Global.Languages[2];
}
config.ConstItem ??= new ConstItem();
if (Utils.IsNullOrEmpty(config.ConstItem.DefIEProxyExceptions))
{
config.ConstItem.DefIEProxyExceptions = Global.IEProxyExceptions;
}
config.SpeedTestItem ??= new();
if (config.SpeedTestItem.SpeedTestTimeout < 10)
@@ -132,7 +119,7 @@ namespace ServiceLib.Handler
}
if (Utils.IsNullOrEmpty(config.SpeedTestItem.SpeedTestUrl))
{
config.SpeedTestItem.SpeedTestUrl = Global.SpeedTestUrls[0];
config.SpeedTestItem.SpeedTestUrl = Global.SpeedTestUrls.First();
}
if (Utils.IsNullOrEmpty(config.SpeedTestItem.SpeedPingTestUrl))
{
@@ -148,7 +135,7 @@ namespace ServiceLib.Handler
config.Mux4SboxItem ??= new()
{
Protocol = Global.SingboxMuxs[0],
Protocol = Global.SingboxMuxs.First(),
MaxConnections = 8
};
@@ -161,6 +148,17 @@ namespace ServiceLib.Handler
config.SystemProxyItem ??= new();
config.WebDavItem ??= new();
config.CheckUpdateItem ??= new();
config.Fragment4RayItem ??= new()
{
Packets = "tlshello",
Length = "100-200",
Interval = "10-20"
};
if (config.SystemProxyItem.SystemProxyExceptions.IsNullOrEmpty())
{
config.SystemProxyItem.SystemProxyExceptions = Utils.IsWindows() ? Global.SystemProxyExceptionsWindows : Global.SystemProxyExceptionsLinux;
}
return config;
}
@@ -172,30 +170,26 @@ namespace ServiceLib.Handler
/// <returns></returns>
public static async Task<int> SaveConfig(Config config)
{
lock (_objLock)
try
{
try
{
//save temp file
var resPath = Utils.GetConfigPath(_configRes);
var tempPath = $"{resPath}_temp";
if (JsonUtils.ToFile(config, tempPath) != 0)
{
return -1;
}
//save temp file
var resPath = Utils.GetConfigPath(_configRes);
var tempPath = $"{resPath}_temp";
if (File.Exists(resPath))
{
File.Delete(resPath);
}
//rename
File.Move(tempPath, resPath);
}
catch (Exception ex)
var content = JsonUtils.Serialize(config, true, true);
if (content.IsNullOrEmpty())
{
Logging.SaveLog("ToJsonFile", ex);
return -1;
}
await File.WriteAllTextAsync(tempPath, content);
//rename
File.Move(tempPath, resPath, true);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
return -1;
}
return 0;
@@ -429,7 +423,7 @@ namespace ServiceLib.Handler
{
return 0;
}
sort = ProfileExHandler.Instance.GetSort(lstProfile[0].IndexId) - 1;
sort = ProfileExHandler.Instance.GetSort(lstProfile.First().IndexId) - 1;
break;
}
@@ -470,7 +464,7 @@ namespace ServiceLib.Handler
}
ProfileExHandler.Instance.SetSort(lstProfile[index].IndexId, sort);
return 0;
return await Task.FromResult(0);
}
/// <summary>
@@ -500,7 +494,7 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
return -1;
}
@@ -766,69 +760,66 @@ namespace ServiceLib.Handler
}).ToList();
Enum.TryParse(colName, true, out EServerColName name);
var propertyName = string.Empty;
switch (name)
{
case EServerColName.ConfigType:
case EServerColName.Remarks:
case EServerColName.Address:
case EServerColName.Port:
case EServerColName.Network:
case EServerColName.StreamSecurity:
propertyName = name.ToString();
break;
case EServerColName.DelayVal:
propertyName = "Delay";
break;
case EServerColName.SpeedVal:
propertyName = "Speed";
break;
case EServerColName.SubRemarks:
propertyName = "Subid";
break;
default:
return -1;
}
var items = lstProfile.AsQueryable();
if (asc)
{
lstProfile = items.OrderBy(propertyName).ToList();
lstProfile = name switch
{
EServerColName.ConfigType => lstProfile.OrderBy(t => t.ConfigType).ToList(),
EServerColName.Remarks => lstProfile.OrderBy(t => t.Remarks).ToList(),
EServerColName.Address => lstProfile.OrderBy(t => t.Address).ToList(),
EServerColName.Port => lstProfile.OrderBy(t => t.Port).ToList(),
EServerColName.Network => lstProfile.OrderBy(t => t.Network).ToList(),
EServerColName.StreamSecurity => lstProfile.OrderBy(t => t.StreamSecurity).ToList(),
EServerColName.DelayVal => lstProfile.OrderBy(t => t.Delay).ToList(),
EServerColName.SpeedVal => lstProfile.OrderBy(t => t.Speed).ToList(),
EServerColName.SubRemarks => lstProfile.OrderBy(t => t.Subid).ToList(),
_ => lstProfile
};
}
else
{
lstProfile = items.OrderByDescending(propertyName).ToList();
lstProfile = name switch
{
EServerColName.ConfigType => lstProfile.OrderByDescending(t => t.ConfigType).ToList(),
EServerColName.Remarks => lstProfile.OrderByDescending(t => t.Remarks).ToList(),
EServerColName.Address => lstProfile.OrderByDescending(t => t.Address).ToList(),
EServerColName.Port => lstProfile.OrderByDescending(t => t.Port).ToList(),
EServerColName.Network => lstProfile.OrderByDescending(t => t.Network).ToList(),
EServerColName.StreamSecurity => lstProfile.OrderByDescending(t => t.StreamSecurity).ToList(),
EServerColName.DelayVal => lstProfile.OrderByDescending(t => t.Delay).ToList(),
EServerColName.SpeedVal => lstProfile.OrderByDescending(t => t.Speed).ToList(),
EServerColName.SubRemarks => lstProfile.OrderByDescending(t => t.Subid).ToList(),
_ => lstProfile
};
}
for (int i = 0; i < lstProfile.Count; i++)
for (var i = 0; i < lstProfile.Count; i++)
{
ProfileExHandler.Instance.SetSort(lstProfile[i].IndexId, (i + 1) * 10);
}
if (name == EServerColName.DelayVal)
switch (name)
{
var maxSort = lstProfile.Max(t => t.Sort) + 10;
foreach (var item in lstProfile)
{
if (item.Delay <= 0)
case EServerColName.DelayVal:
{
ProfileExHandler.Instance.SetSort(item.IndexId, maxSort);
var maxSort = lstProfile.Max(t => t.Sort) + 10;
foreach (var item in lstProfile.Where(item => item.Delay <= 0))
{
ProfileExHandler.Instance.SetSort(item.IndexId, maxSort);
}
break;
}
}
}
if (name == EServerColName.SpeedVal)
{
var maxSort = lstProfile.Max(t => t.Sort) + 10;
foreach (var item in lstProfile)
{
if (item.Speed <= 0)
case EServerColName.SpeedVal:
{
ProfileExHandler.Instance.SetSort(item.IndexId, maxSort);
var maxSort = lstProfile.Max(t => t.Sort) + 10;
foreach (var item in lstProfile.Where(item => item.Speed <= 0))
{
ProfileExHandler.Instance.SetSort(item.IndexId, maxSort);
}
break;
}
}
}
return 0;
@@ -877,7 +868,8 @@ namespace ServiceLib.Handler
List<ProfileItem> lstKeep = new();
List<ProfileItem> lstRemove = new();
if (!config.GuiItem.KeepOlderDedupl) lstProfile.Reverse();
if (!config.GuiItem.KeepOlderDedupl)
lstProfile.Reverse();
foreach (ProfileItem item in lstProfile)
{
@@ -990,7 +982,7 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog("Remove Item", ex);
Logging.SaveLog(_tag, ex);
}
return 0;
@@ -1029,12 +1021,11 @@ namespace ServiceLib.Handler
public static async Task<ProfileItem?> GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType)
{
ProfileItem? itemSocks = null;
var preCoreType = ECoreType.sing_box;
if (node.ConfigType != EConfigType.Custom && coreType != ECoreType.sing_box && config.TunModeItem.EnableTun)
{
itemSocks = new ProfileItem()
{
CoreType = preCoreType,
CoreType = ECoreType.sing_box,
ConfigType = EConfigType.SOCKS,
Address = Global.Loopback,
Sni = node.Address, //Tun2SocksAddress
@@ -1043,7 +1034,7 @@ namespace ServiceLib.Handler
}
else if ((node.ConfigType == EConfigType.Custom && node.PreSocksPort > 0))
{
preCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
var preCoreType = config.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;
itemSocks = new ProfileItem()
{
CoreType = preCoreType,
@@ -1052,7 +1043,7 @@ namespace ServiceLib.Handler
Port = node.PreSocksPort.Value,
};
}
await Task.CompletedTask;
return itemSocks;
}
@@ -1368,7 +1359,8 @@ namespace ServiceLib.Handler
};
var uri = Utils.TryUri(url);
if (uri == null) return -1;
if (uri == null)
return -1;
//Do not allow http protocol
if (url.StartsWith(Global.HttpProtocol) && !Utils.IsPrivateNetwork(uri.IdnHost))
{
@@ -1622,7 +1614,7 @@ namespace ServiceLib.Handler
break;
}
}
return 0;
return await Task.FromResult(0);
}
public static async Task<int> SetDefaultRouting(Config config, RoutingItem routingItem)
@@ -1738,7 +1730,7 @@ namespace ServiceLib.Handler
Url = string.Empty,
Sort = maxSort + 1,
};
await AddBatchRoutingRules(item2, Utils.GetEmbedText(Global.CustomRoutingFileName + "white"));
await AddBatchRoutingRules(item2, EmbedUtils.GetEmbedText(Global.CustomRoutingFileName + "white"));
//Blacklist
var item3 = new RoutingItem()
@@ -1747,7 +1739,7 @@ namespace ServiceLib.Handler
Url = string.Empty,
Sort = maxSort + 2,
};
await AddBatchRoutingRules(item3, Utils.GetEmbedText(Global.CustomRoutingFileName + "black"));
await AddBatchRoutingRules(item3, EmbedUtils.GetEmbedText(Global.CustomRoutingFileName + "black"));
//Global
var item1 = new RoutingItem()
@@ -1756,7 +1748,7 @@ namespace ServiceLib.Handler
Url = string.Empty,
Sort = maxSort + 3,
};
await AddBatchRoutingRules(item1, Utils.GetEmbedText(Global.CustomRoutingFileName + "global"));
await AddBatchRoutingRules(item1, EmbedUtils.GetEmbedText(Global.CustomRoutingFileName + "global"));
if (!blImportAdvancedRules)
{
@@ -1872,6 +1864,16 @@ namespace ServiceLib.Handler
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json"));
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json"));
return true;
case EPresetType.Iran:
config.ConstItem.GeoSourceUrl = Global.GeoFilesSources[2];
config.ConstItem.SrsSourceUrl = Global.SingboxRulesetSources[2];
config.ConstItem.RouteRulesTemplateSourceUrl = Global.RoutingRulesSources[2];
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[2] + "v2ray.json"));
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[2] + "sing_box.json"));
return true;
}
@@ -1880,4 +1882,4 @@ namespace ServiceLib.Handler
#endregion Regional Presets
}
}
}

View File

@@ -5,6 +5,8 @@
/// </summary>
public class CoreConfigHandler
{
private static readonly string _tag = "CoreConfigHandler";
public static async Task<RetResult> GenerateClientConfig(ProfileItem node, string? fileName)
{
var config = AppHandler.Instance.Config;
@@ -78,11 +80,11 @@
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
ret.Success = true;
return ret;
return await Task.FromResult(ret);
}
catch (Exception ex)
{
Logging.SaveLog("GenerateClientCustomConfig", ex);
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}

View File

@@ -1,4 +1,4 @@
using System.Diagnostics;
using System.Diagnostics;
using System.Text;
namespace ServiceLib.Handler
@@ -15,25 +15,37 @@ namespace ServiceLib.Handler
private Process? _processPre;
private int _linuxSudoPid = -1;
private Action<bool, string>? _updateFunc;
private const string _tag = "CoreHandler";
public async Task Init(Config config, Action<bool, string> updateFunc)
{
_config = config;
_updateFunc = updateFunc;
Environment.SetEnvironmentVariable("V2RAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("XRAY_LOCATION_ASSET", Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable(Global.V2RayLocalAsset, Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable(Global.XrayLocalAsset, Utils.GetBinPath(""), EnvironmentVariableTarget.Process);
if (Utils.IsLinux() || Utils.IsOSX())
//Copy the bin folder to the storage location (for init)
if (Environment.GetEnvironmentVariable(Global.LocalAppData) == "1")
{
var fromPath = Utils.GetBaseDirectory("bin");
var toPath = Utils.GetBinPath("");
if (fromPath != toPath)
{
FileManager.CopyDirectory(fromPath, toPath, true, false);
}
}
if (Utils.IsNonWindows())
{
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo();
foreach (var it in coreInfo)
{
if (it.CoreType == ECoreType.v2rayN)
{
if (Utils.UpgradeAppExists(out var fileName))
if (Utils.UpgradeAppExists(out var upgradeFileName))
{
await Utils.SetLinuxChmod(fileName);
await Utils.SetLinuxChmod(upgradeFileName);
}
continue;
}
@@ -54,7 +66,7 @@ namespace ServiceLib.Handler
{
if (node == null)
{
ShowMsg(false, ResUI.CheckServerSettings);
UpdateFunc(false, ResUI.CheckServerSettings);
return;
}
@@ -62,17 +74,28 @@ namespace ServiceLib.Handler
var result = await CoreConfigHandler.GenerateClientConfig(node, fileName);
if (result.Success != true)
{
ShowMsg(true, result.Msg);
UpdateFunc(true, result.Msg);
return;
}
ShowMsg(true, $"{node.GetSummary()}");
ShowMsg(false, $"{Environment.OSVersion} - {(Environment.Is64BitOperatingSystem ? 64 : 32)}");
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
UpdateFunc(false, $"{node.GetSummary()}");
UpdateFunc(false, $"{Utils.GetRuntimeInfo()}");
UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
await CoreStop();
await Task.Delay(100);
if (Utils.IsWindows() && _config.TunModeItem.EnableTun)
{
await Task.Delay(100);
await WindowsUtils.RemoveTunDevice();
}
await CoreStart(node);
await CoreStartPreService(node);
if (_process != null)
{
UpdateFunc(true, $"{node.GetSummary()}");
}
}
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
@@ -80,15 +103,23 @@ namespace ServiceLib.Handler
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard) ? ECoreType.sing_box : ECoreType.Xray;
var configPath = Utils.GetConfigPath(Global.CoreSpeedtestConfigFileName);
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
ShowMsg(false, result.Msg);
UpdateFunc(false, result.Msg);
if (result.Success != true)
{
return -1;
}
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
ShowMsg(false, configPath);
return await CoreStartSpeedtest(configPath, coreType);
UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
UpdateFunc(false, configPath);
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
var proc = await RunProcess(coreInfo, Global.CoreSpeedtestConfigFileName, true, false);
if (proc is null)
{
return -1;
}
return proc.Id;
}
public async Task CoreStop()
@@ -97,15 +128,13 @@ namespace ServiceLib.Handler
{
if (_process != null)
{
await KillProcess(_process);
_process.Dispose();
await ProcUtils.ProcessKill(_process, true);
_process = null;
}
if (_processPre != null)
{
await KillProcess(_processPre);
_processPre.Dispose();
await ProcUtils.ProcessKill(_processPre, true);
_processPre = null;
}
@@ -117,46 +146,12 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
}
public async Task CoreStopPid(int pid)
{
try
{
var _p = Process.GetProcessById(pid);
await KillProcess(_p);
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}
#region Private
private string CoreFindExe(CoreInfo coreInfo)
{
var fileName = string.Empty;
foreach (var name in coreInfo.CoreExes)
{
var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());
if (File.Exists(vName))
{
fileName = vName;
break;
}
}
if (Utils.IsNullOrEmpty(fileName))
{
var msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.CoreType.ToString()), string.Join(", ", coreInfo.CoreExes.ToArray()), coreInfo.Url);
Logging.SaveLog(msg);
ShowMsg(false, msg);
}
return fileName;
}
private async Task CoreStart(ProfileItem node)
{
var coreType = _config.RunningCoreType = AppHandler.Instance.GetCoreType(node, node.ConfigType);
@@ -179,7 +174,7 @@ namespace ServiceLib.Handler
var itemSocks = await ConfigHandler.GetPreSocksItem(_config, node, coreType);
if (itemSocks != null)
{
var preCoreType = _config.RunningCoreType = itemSocks.CoreType ?? ECoreType.sing_box;
var preCoreType = itemSocks.CoreType ?? ECoreType.sing_box;
var fileName = Utils.GetConfigPath(Global.CorePreConfigFileName);
var result = await CoreConfigHandler.GenerateClientConfig(itemSocks, fileName);
if (result.Success)
@@ -196,28 +191,7 @@ namespace ServiceLib.Handler
}
}
private async Task<int> CoreStartSpeedtest(string configPath, ECoreType coreType)
{
try
{
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(coreType);
var proc = await RunProcess(coreInfo, Global.CoreSpeedtestConfigFileName, true, false);
if (proc is null)
{
return -1;
}
return proc.Id;
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
ShowMsg(false, ex.Message);
return -1;
}
}
private void ShowMsg(bool notify, string msg)
private void UpdateFunc(bool notify, string msg)
{
_updateFunc?.Invoke(notify, msg);
}
@@ -226,7 +200,7 @@ namespace ServiceLib.Handler
{
return _config.TunModeItem.EnableTun
&& eCoreType == ECoreType.sing_box
&& (Utils.IsLinux() || Utils.IsOSX())
&& (Utils.IsNonWindows())
//&& _config.TunModeItem.LinuxSudoPwd.IsNotEmpty()
;
}
@@ -235,11 +209,12 @@ namespace ServiceLib.Handler
#region Process
private async Task<Process?> RunProcess(CoreInfo coreInfo, string configPath, bool displayLog, bool mayNeedSudo)
private async Task<Process?> RunProcess(CoreInfo? coreInfo, string configPath, bool displayLog, bool mayNeedSudo)
{
var fileName = CoreFindExe(coreInfo);
var fileName = CoreInfoHandler.Instance.GetCoreExecFile(coreInfo, out var msg);
if (Utils.IsNullOrEmpty(fileName))
{
UpdateFunc(false, msg);
return null;
}
@@ -250,7 +225,7 @@ namespace ServiceLib.Handler
StartInfo = new()
{
FileName = fileName,
Arguments = string.Format(coreInfo.Arguments, configPath),
Arguments = string.Format(coreInfo.Arguments, coreInfo.AbsolutePath ? Utils.GetConfigPath(configPath) : configPath),
WorkingDirectory = Utils.GetConfigPath(),
UseShellExecute = false,
RedirectStandardOutput = displayLog,
@@ -267,24 +242,19 @@ namespace ServiceLib.Handler
await RunProcessAsLinuxSudo(proc, fileName, coreInfo, configPath);
}
var startUpErrorMessage = new StringBuilder();
var startUpSuccessful = false;
if (displayLog)
{
proc.OutputDataReceived += (sender, e) =>
{
if (Utils.IsNullOrEmpty(e.Data)) return;
ShowMsg(false, e.Data + Environment.NewLine);
if (Utils.IsNullOrEmpty(e.Data))
return;
UpdateFunc(false, e.Data + Environment.NewLine);
};
proc.ErrorDataReceived += (sender, e) =>
{
if (Utils.IsNullOrEmpty(e.Data)) return;
ShowMsg(false, e.Data + Environment.NewLine);
if (!startUpSuccessful)
{
startUpErrorMessage.Append(e.Data + Environment.NewLine);
}
if (Utils.IsNullOrEmpty(e.Data))
return;
UpdateFunc(false, e.Data + Environment.NewLine);
};
}
proc.Start();
@@ -297,7 +267,8 @@ namespace ServiceLib.Handler
await Task.Delay(10);
await proc.StandardInput.WriteLineAsync(pwd);
}
if (isNeedSudo) _linuxSudoPid = proc.Id;
if (isNeedSudo)
_linuxSudoPid = proc.Id;
if (displayLog)
{
@@ -305,55 +276,22 @@ namespace ServiceLib.Handler
proc.BeginErrorReadLine();
}
if (proc.WaitForExit(1000))
{
proc.CancelErrorRead();
throw new Exception(displayLog ? startUpErrorMessage.ToString() : "启动进程失败并退出 (Failed to start the process and exited)");
}
else
{
startUpSuccessful = true;
}
await Task.Delay(500);
AppHandler.Instance.AddProcess(proc.Handle);
if (proc is null or { HasExited: true })
{
throw new Exception(ResUI.FailedToRunCore);
}
return proc;
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
ShowMsg(true, ex.Message);
Logging.SaveLog(_tag, ex);
UpdateFunc(mayNeedSudo, ex.Message);
return null;
}
}
private async Task KillProcess(Process? proc)
{
if (proc is null)
{
return;
}
try
{
proc?.Kill(true);
}
catch (Exception)
{
// ignored
}
await Task.Delay(100);
if (proc?.HasExited == false)
{
try
{
proc?.Kill();
}
catch (Exception)
{
// ignored
}
}
}
#endregion Process
#region Linux
@@ -408,13 +346,13 @@ namespace ServiceLib.Handler
var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(10));
await proc.WaitForExitAsync(timeout.Token);
await Task.Delay(1000);
await Task.Delay(3000);
}
private async Task<string> CreateLinuxShellFile(string cmdLine, string fileName)
{
//Shell scripts
var shFilePath = Utils.GetBinPath(fileName);
var shFilePath = Utils.GetBinPath(AppHandler.Instance.IsAdministrator ? "root_" + fileName : fileName);
File.Delete(shFilePath);
var sb = new StringBuilder();
sb.AppendLine("#!/bin/sh");
@@ -440,4 +378,4 @@ namespace ServiceLib.Handler
#endregion Linux
}
}
}

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Handler
namespace ServiceLib.Handler
{
public sealed class CoreInfoHandler
{
@@ -29,151 +29,190 @@
return _coreInfo ?? [];
}
private void InitCoreInfo()
public string GetCoreExecFile(CoreInfo? coreInfo, out string msg)
{
_coreInfo = [];
_coreInfo.Add(new CoreInfo
var fileName = string.Empty;
msg = string.Empty;
foreach (var name in coreInfo?.CoreExes)
{
CoreType = ECoreType.v2rayN,
Url = Global.NUrl,
ReleaseApiUrl = Global.NUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.NUrl + "/download/{0}/v2rayN-windows-64.zip",
DownloadUrlWinArm64 = Global.NUrl + "/download/{0}/v2rayN-windows-arm64.zip",
DownloadUrlLinux64 = Global.NUrl + "/download/{0}/v2rayN-linux-64.zip",
DownloadUrlLinuxArm64 = Global.NUrl + "/download/{0}/v2rayN-linux-arm64.zip",
DownloadUrlOSX64 = Global.NUrl + "/download/{0}/v2rayN-macos-64.zip",
DownloadUrlOSXArm64 = Global.NUrl + "/download/{0}/v2rayN-macos-arm64.zip",
});
_coreInfo.Add(new CoreInfo
var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());
if (File.Exists(vName))
{
fileName = vName;
break;
}
}
if (fileName.IsNullOrEmpty())
{
CoreType = ECoreType.v2fly,
CoreExes = new List<string> { "wv2ray", "v2ray" },
Arguments = "",
Url = Global.V2flyCoreUrl,
ReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
Match = "V2Ray",
VersionArg = "-version",
RedirectInfo = true,
});
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.v2fly_v5,
CoreExes = new List<string> { "v2ray" },
Arguments = "run -c config.json -format jsonv5",
Url = Global.V2flyCoreUrl,
ReleaseApiUrl = Global.V2flyCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
Match = "V2Ray",
VersionArg = "version",
RedirectInfo = true,
});
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.Xray,
CoreExes = new List<string> { "xray", "wxray" },
Arguments = "run -c {0}",
Url = Global.XrayCoreUrl,
ReleaseApiUrl = Global.XrayCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-64.zip",
DownloadUrlWinArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-windows-arm64-v8a.zip",
DownloadUrlLinux64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-64.zip",
DownloadUrlLinuxArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-linux-arm64-v8a.zip",
DownloadUrlOSX64 = Global.XrayCoreUrl + "/download/{0}/Xray-macos-64.zip",
DownloadUrlOSXArm64 = Global.XrayCoreUrl + "/download/{0}/Xray-macos-arm64-v8a.zip",
Match = "Xray",
VersionArg = "-version",
RedirectInfo = true,
});
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.mihomo,
CoreExes = new List<string> { "mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-linux-amd64", "mihomo", "clash" },
Arguments = "-f config.json" + PortableMode(),
Url = Global.MihomoCoreUrl,
ReleaseApiUrl = Global.MihomoCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-amd64-compatible-{0}.zip",
DownloadUrlWinArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-windows-arm64-{0}.zip",
DownloadUrlLinux64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz",
DownloadUrlLinuxArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-linux-arm64-{0}.gz",
DownloadUrlOSX64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-darwin-amd64-compatible-{0}.gz",
DownloadUrlOSXArm64 = Global.MihomoCoreUrl + "/download/{0}/mihomo-darwin-arm64-{0}.gz",
Match = "Mihomo",
VersionArg = "-v",
RedirectInfo = true,
});
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.hysteria,
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria" },
Arguments = "",
Url = Global.HysteriaCoreUrl,
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
RedirectInfo = true,
});
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.naiveproxy,
CoreExes = new List<string> { "naiveproxy", "naive" },
Arguments = "config.json",
Url = Global.NaiveproxyCoreUrl,
RedirectInfo = false,
});
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.tuic,
CoreExes = new List<string> { "tuic-client", "tuic" },
Arguments = "-c config.json",
Url = Global.TuicCoreUrl,
RedirectInfo = true,
});
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.sing_box,
CoreExes = new List<string> { "sing-box-client", "sing-box" },
Arguments = "run -c {0} --disable-color",
Url = Global.SingboxCoreUrl,
RedirectInfo = true,
ReleaseApiUrl = Global.SingboxCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-amd64.zip",
DownloadUrlWinArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-windows-arm64.zip",
DownloadUrlLinux64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz",
DownloadUrlLinuxArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz",
DownloadUrlOSX64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-darwin-amd64.tar.gz",
DownloadUrlOSXArm64 = Global.SingboxCoreUrl + "/download/{0}/sing-box-{1}-darwin-arm64.tar.gz",
Match = "sing-box",
VersionArg = "version",
});
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.juicity,
CoreExes = new List<string> { "juicity-client", "juicity" },
Arguments = "run -c config.json",
Url = Global.JuicityCoreUrl
});
_coreInfo.Add(new CoreInfo
{
CoreType = ECoreType.hysteria2,
CoreExes = new List<string> { "hysteria-windows-amd64", "hysteria-linux-amd64", "hysteria" },
Arguments = "",
Url = Global.HysteriaCoreUrl,
ReleaseApiUrl = Global.HysteriaCoreUrl.Replace(Global.GithubUrl, Global.GithubApiUrl),
RedirectInfo = true,
});
msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo?.CoreType.ToString()), coreInfo?.CoreExes?.LastOrDefault(), coreInfo?.Url);
Logging.SaveLog(msg);
}
return fileName;
}
private string PortableMode()
private void InitCoreInfo()
{
var urlN = GetCoreUrl(ECoreType.v2rayN);
var urlXray = GetCoreUrl(ECoreType.Xray);
var urlMihomo = GetCoreUrl(ECoreType.mihomo);
var urlSingbox = GetCoreUrl(ECoreType.sing_box);
_coreInfo =
[
new CoreInfo
{
CoreType = ECoreType.v2rayN,
Url = GetCoreUrl(ECoreType.v2rayN),
ReleaseApiUrl = urlN.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = urlN + "/download/{0}/v2rayN-windows-64.zip",
DownloadUrlWinArm64 = urlN + "/download/{0}/v2rayN-windows-arm64.zip",
DownloadUrlLinux64 = urlN + "/download/{0}/v2rayN-linux-64.zip",
DownloadUrlLinuxArm64 = urlN + "/download/{0}/v2rayN-linux-arm64.zip",
DownloadUrlOSX64 = urlN + "/download/{0}/v2rayN-macos-64.zip",
DownloadUrlOSXArm64 = urlN + "/download/{0}/v2rayN-macos-arm64.zip",
},
new CoreInfo
{
CoreType = ECoreType.v2fly,
CoreExes = ["wv2ray", "v2ray"],
Arguments = "{0}",
Url = GetCoreUrl(ECoreType.v2fly),
Match = "V2Ray",
VersionArg = "-version",
},
new CoreInfo
{
CoreType = ECoreType.v2fly_v5,
CoreExes = ["v2ray"],
Arguments = "run -c {0} -format jsonv5",
Url = GetCoreUrl(ECoreType.v2fly_v5),
Match = "V2Ray",
VersionArg = "version",
},
new CoreInfo
{
CoreType = ECoreType.Xray,
CoreExes = ["wxray","xray"],
Arguments = "run -c {0}",
Url = GetCoreUrl(ECoreType.Xray),
ReleaseApiUrl = urlXray.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = urlXray + "/download/{0}/Xray-windows-64.zip",
DownloadUrlWinArm64 = urlXray + "/download/{0}/Xray-windows-arm64-v8a.zip",
DownloadUrlLinux64 = urlXray + "/download/{0}/Xray-linux-64.zip",
DownloadUrlLinuxArm64 = urlXray + "/download/{0}/Xray-linux-arm64-v8a.zip",
DownloadUrlOSX64 = urlXray + "/download/{0}/Xray-macos-64.zip",
DownloadUrlOSXArm64 = urlXray + "/download/{0}/Xray-macos-arm64-v8a.zip",
Match = "Xray",
VersionArg = "-version",
},
new CoreInfo
{
CoreType = ECoreType.mihomo,
CoreExes = ["mihomo-windows-amd64-compatible", "mihomo-windows-amd64", "mihomo-linux-amd64", "clash", "mihomo"],
Arguments = "-f {0}" + PortableMode(),
Url = GetCoreUrl(ECoreType.mihomo),
ReleaseApiUrl = urlMihomo.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = urlMihomo + "/download/{0}/mihomo-windows-amd64-compatible-{0}.zip",
DownloadUrlWinArm64 = urlMihomo + "/download/{0}/mihomo-windows-arm64-{0}.zip",
DownloadUrlLinux64 = urlMihomo + "/download/{0}/mihomo-linux-amd64-compatible-{0}.gz",
DownloadUrlLinuxArm64 = urlMihomo + "/download/{0}/mihomo-linux-arm64-{0}.gz",
DownloadUrlOSX64 = urlMihomo + "/download/{0}/mihomo-darwin-amd64-compatible-{0}.gz",
DownloadUrlOSXArm64 = urlMihomo + "/download/{0}/mihomo-darwin-arm64-{0}.gz",
Match = "Mihomo",
VersionArg = "-v",
},
new CoreInfo
{
CoreType = ECoreType.hysteria,
CoreExes = ["hysteria"],
Arguments = "",
Url = GetCoreUrl(ECoreType.hysteria),
},
new CoreInfo
{
CoreType = ECoreType.naiveproxy,
CoreExes = [ "naive", "naiveproxy"],
Arguments = "{0}",
Url = GetCoreUrl(ECoreType.naiveproxy),
},
new CoreInfo
{
CoreType = ECoreType.tuic,
CoreExes = ["tuic-client", "tuic"],
Arguments = "-c {0}",
Url = GetCoreUrl(ECoreType.tuic),
},
new CoreInfo
{
CoreType = ECoreType.sing_box,
CoreExes = ["sing-box-client", "sing-box"],
Arguments = "run -c {0} --disable-color",
Url = GetCoreUrl(ECoreType.sing_box),
ReleaseApiUrl = urlSingbox.Replace(Global.GithubUrl, Global.GithubApiUrl),
DownloadUrlWin64 = urlSingbox + "/download/{0}/sing-box-{1}-windows-amd64.zip",
DownloadUrlWinArm64 = urlSingbox + "/download/{0}/sing-box-{1}-windows-arm64.zip",
DownloadUrlLinux64 = urlSingbox + "/download/{0}/sing-box-{1}-linux-amd64.tar.gz",
DownloadUrlLinuxArm64 = urlSingbox + "/download/{0}/sing-box-{1}-linux-arm64.tar.gz",
DownloadUrlOSX64 = urlSingbox + "/download/{0}/sing-box-{1}-darwin-amd64.tar.gz",
DownloadUrlOSXArm64 = urlSingbox + "/download/{0}/sing-box-{1}-darwin-arm64.tar.gz",
Match = "sing-box",
VersionArg = "version",
},
new CoreInfo
{
CoreType = ECoreType.juicity,
CoreExes = ["juicity-client", "juicity"],
Arguments = "run -c {0}",
Url = GetCoreUrl(ECoreType.juicity)
},
new CoreInfo
{
CoreType = ECoreType.hysteria2,
CoreExes = ["hysteria-windows-amd64", "hysteria-linux-amd64", "hysteria"],
Arguments = "",
Url = GetCoreUrl(ECoreType.hysteria2),
},
new CoreInfo
{
CoreType = ECoreType.brook,
CoreExes = ["brook_windows_amd64", "brook_linux_amd64", "brook"],
Arguments = " {0}",
Url = GetCoreUrl(ECoreType.brook),
AbsolutePath = true,
},
new CoreInfo
{
CoreType = ECoreType.overtls,
CoreExes = [ "overtls-bin", "overtls"],
Arguments = "-r client -c {0}",
Url = GetCoreUrl(ECoreType.overtls),
AbsolutePath = false,
}
];
}
private static string PortableMode()
{
return $" -d {Utils.GetBinPath("").AppendQuotes()}";
}
private static string GetCoreUrl(ECoreType eCoreType)
{
return $"{Global.GithubUrl}/{Global.CoreUrls[eCoreType]}/releases";
}
}
}
}

View File

@@ -1,4 +1,4 @@
using System.Collections.Specialized;
using System.Collections.Specialized;
namespace ServiceLib.Handler.Fmt
{
@@ -214,7 +214,8 @@ namespace ServiceLib.Handler.Fmt
{
foreach (var item in s)
{
if (str.Contains(item, StringComparison.OrdinalIgnoreCase)) return true;
if (str.Contains(item, StringComparison.OrdinalIgnoreCase))
return true;
}
return false;
}
@@ -236,4 +237,4 @@ namespace ServiceLib.Handler.Fmt
return $"{Global.ProtocolShares[eConfigType]}{url}{query}{remark}";
}
}
}
}

View File

@@ -2,6 +2,8 @@
{
public class FmtHandler
{
private static readonly string _tag = "FmtHandler";
public static string? GetShareUri(ProfileItem item)
{
try
@@ -23,7 +25,7 @@
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
return "";
}
}
@@ -81,7 +83,7 @@
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
msg = ResUI.Incorrectconfiguration;
return null;
}

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Handler.Fmt
namespace ServiceLib.Handler.Fmt
{
public class Hysteria2Fmt : BaseFmt
{
@@ -11,7 +11,8 @@
};
var url = Utils.TryUri(str);
if (url == null) return null;
if (url == null)
return null;
item.Address = url.IdnHost;
item.Port = url.Port;
@@ -28,7 +29,8 @@
public static string? ToUri(ProfileItem? item)
{
if (item == null) return null;
if (item == null)
return null;
string url = string.Empty;
string remark = string.Empty;
@@ -91,4 +93,4 @@
return null;
}
}
}
}

View File

@@ -1,4 +1,4 @@
using System.Text.RegularExpressions;
using System.Text.RegularExpressions;
namespace ServiceLib.Handler.Fmt
{
@@ -26,7 +26,8 @@ namespace ServiceLib.Handler.Fmt
public static string? ToUri(ProfileItem? item)
{
if (item == null) return null;
if (item == null)
return null;
string url = string.Empty;
string remark = string.Empty;
@@ -82,7 +83,8 @@ namespace ServiceLib.Handler.Fmt
private static ProfileItem? ResolveSip002(string result)
{
var parsedUrl = Utils.TryUri(result);
if (parsedUrl == null) return null;
if (parsedUrl == null)
return null;
ProfileItem item = new()
{
@@ -99,8 +101,8 @@ namespace ServiceLib.Handler.Fmt
{
return null;
}
item.Security = userInfoParts[0];
item.Id = Utils.UrlDecode(userInfoParts[1]);
item.Security = userInfoParts.First();
item.Id = Utils.UrlDecode(userInfoParts.Last());
}
else
{
@@ -111,8 +113,8 @@ namespace ServiceLib.Handler.Fmt
{
return null;
}
item.Security = userInfoParts[0];
item.Id = userInfoParts[1];
item.Security = userInfoParts.First();
item.Id = userInfoParts.Last();
}
var queryParameters = Utils.ParseQueryString(parsedUrl.Query);
@@ -169,4 +171,4 @@ namespace ServiceLib.Handler.Fmt
return null;
}
}
}
}

View File

@@ -1,13 +1,12 @@
namespace ServiceLib.Handler.Fmt
namespace ServiceLib.Handler.Fmt
{
public class SocksFmt : BaseFmt
{
public static ProfileItem? Resolve(string str, out string msg)
{
msg = ResUI.ConfigurationFormatIncorrect;
ProfileItem? item;
item = ResolveSocksNew(str) ?? ResolveSocks(str);
var item = ResolveSocksNew(str) ?? ResolveSocks(str);
if (item == null)
{
return null;
@@ -24,20 +23,15 @@
public static string? ToUri(ProfileItem? item)
{
if (item == null) return null;
string url = string.Empty;
if (item == null)
return null;
var url = string.Empty;
string remark = string.Empty;
var remark = string.Empty;
if (Utils.IsNotEmpty(item.Remarks))
{
remark = "#" + Utils.UrlEncode(item.Remarks);
}
//url = string.Format("{0}:{1}@{2}:{3}",
// item.security,
// item.id,
// item.address,
// item.port);
//url = Utile.Base64Encode(url);
//new
var pw = Utils.Base64Encode($"{item.Security}:{item.Id}");
return ToUri(EConfigType.SOCKS, item.Address, item.Port, pw, null, remark);
@@ -51,7 +45,7 @@
};
result = result[Global.ProtocolShares[EConfigType.SOCKS].Length..];
//remark
int indexRemark = result.IndexOf("#");
var indexRemark = result.IndexOf("#");
if (indexRemark > 0)
{
try
@@ -62,7 +56,7 @@
result = result[..indexRemark];
}
//part decode
int indexS = result.IndexOf("@");
var indexS = result.IndexOf("@");
if (indexS > 0)
{
}
@@ -71,21 +65,20 @@
result = Utils.Base64Decode(result);
}
string[] arr1 = result.Split('@');
var arr1 = result.Split('@');
if (arr1.Length != 2)
{
return null;
}
string[] arr21 = arr1[0].Split(':');
//string[] arr22 = arr1[1].Split(':');
int indexPort = arr1[1].LastIndexOf(":");
var arr21 = arr1.First().Split(':');
var indexPort = arr1.Last().LastIndexOf(":");
if (arr21.Length != 2 || indexPort < 0)
{
return null;
}
item.Address = arr1[1][..indexPort];
item.Port = Utils.ToInt(arr1[1][(indexPort + 1)..]);
item.Security = arr21[0];
item.Security = arr21.First();
item.Id = arr21[1];
return item;
@@ -94,7 +87,8 @@
private static ProfileItem? ResolveSocksNew(string result)
{
var parsedUrl = Utils.TryUri(result);
if (parsedUrl == null) return null;
if (parsedUrl == null)
return null;
ProfileItem item = new()
{
@@ -106,14 +100,14 @@
// parse base64 UserInfo
var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
var userInfo = Utils.Base64Decode(rawUserInfo);
var userInfoParts = userInfo.Split(new[] { ':' }, 2);
var userInfoParts = userInfo.Split([':'], 2);
if (userInfoParts.Length == 2)
{
item.Security = userInfoParts[0];
item.Security = userInfoParts.First();
item.Id = userInfoParts[1];
}
return item;
}
}
}
}

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Handler.Fmt
namespace ServiceLib.Handler.Fmt
{
public class TrojanFmt : BaseFmt
{
@@ -12,7 +12,8 @@
};
var url = Utils.TryUri(str);
if (url == null) return null;
if (url == null)
return null;
item.Address = url.IdnHost;
item.Port = url.Port;
@@ -27,7 +28,8 @@
public static string? ToUri(ProfileItem? item)
{
if (item == null) return null;
if (item == null)
return null;
string url = string.Empty;
string remark = string.Empty;
@@ -41,4 +43,4 @@
return ToUri(EConfigType.Trojan, item.Address, item.Port, item.Id, dicQuery, remark);
}
}
}
}

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Handler.Fmt
namespace ServiceLib.Handler.Fmt
{
public class TuicFmt : BaseFmt
{
@@ -12,7 +12,8 @@
};
var url = Utils.TryUri(str);
if (url == null) return null;
if (url == null)
return null;
item.Address = url.IdnHost;
item.Port = url.Port;
@@ -21,8 +22,8 @@
var userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);
if (userInfoParts.Length == 2)
{
item.Id = userInfoParts[0];
item.Security = userInfoParts[1];
item.Id = userInfoParts.First();
item.Security = userInfoParts.Last();
}
var query = Utils.ParseQueryString(url.Query);
@@ -34,7 +35,8 @@
public static string? ToUri(ProfileItem? item)
{
if (item == null) return null;
if (item == null)
return null;
string url = string.Empty;
string remark = string.Empty;
@@ -56,4 +58,4 @@
return ToUri(EConfigType.TUIC, item.Address, item.Port, $"{item.Id}:{item.Security}", dicQuery, remark);
}
}
}
}

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Handler.Fmt
namespace ServiceLib.Handler.Fmt
{
public class VLESSFmt : BaseFmt
{
@@ -13,7 +13,8 @@
};
var url = Utils.TryUri(str);
if (url == null) return null;
if (url == null)
return null;
item.Address = url.IdnHost;
item.Port = url.Port;
@@ -30,7 +31,8 @@
public static string? ToUri(ProfileItem? item)
{
if (item == null) return null;
if (item == null)
return null;
string url = string.Empty;
string remark = string.Empty;
@@ -52,4 +54,4 @@
return ToUri(EConfigType.VLESS, item.Address, item.Port, item.Id, dicQuery, remark);
}
}
}
}

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Handler.Fmt
namespace ServiceLib.Handler.Fmt
{
public class VmessFmt : BaseFmt
{
@@ -19,7 +19,8 @@
public static string? ToUri(ProfileItem? item)
{
if (item == null) return null;
if (item == null)
return null;
string url = string.Empty;
VmessQRCode vmessQRCode = new()
@@ -106,7 +107,8 @@
};
var url = Utils.TryUri(str);
if (url == null) return null;
if (url == null)
return null;
item.Address = url.IdnHost;
item.Port = url.Port;
@@ -119,4 +121,4 @@
return item;
}
}
}
}

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Handler.Fmt
namespace ServiceLib.Handler.Fmt
{
public class WireguardFmt : BaseFmt
{
@@ -12,7 +12,8 @@
};
var url = Utils.TryUri(str);
if (url == null) return null;
if (url == null)
return null;
item.Address = url.IdnHost;
item.Port = url.Port;
@@ -31,7 +32,8 @@
public static string? ToUri(ProfileItem? item)
{
if (item == null) return null;
if (item == null)
return null;
string url = string.Empty;
string remark = string.Empty;
@@ -60,4 +62,4 @@
return ToUri(EConfigType.WireGuard, item.Address, item.Port, item.Id, dicQuery, remark);
}
}
}
}

View File

@@ -1,4 +1,4 @@
using System.Net.Sockets;
using System.Net.Sockets;
using System.Text;
namespace ServiceLib.Handler
@@ -35,7 +35,7 @@ namespace ServiceLib.Handler
var path = Path.Combine(_configPath, "pac.txt");
if (!File.Exists(path))
{
var pac = Utils.GetEmbedText(Global.PacFileName);
var pac = EmbedUtils.GetEmbedText(Global.PacFileName);
await File.AppendAllTextAsync(path, pac);
}
@@ -89,7 +89,8 @@ namespace ServiceLib.Handler
public static void Stop()
{
if (_tcpListener == null) return;
if (_tcpListener == null)
return;
try
{
_isRunning = false;
@@ -102,4 +103,4 @@ namespace ServiceLib.Handler
}
}
}
}
}

View File

@@ -10,6 +10,7 @@ namespace ServiceLib.Handler
private ConcurrentBag<ProfileExItem> _lstProfileEx = [];
private Queue<string> _queIndexIds = new();
public static ProfileExHandler Instance => _instance.Value;
private static readonly string _tag = "ProfileExHandler";
public ProfileExHandler()
{
@@ -19,7 +20,7 @@ namespace ServiceLib.Handler
public async Task Init()
{
await InitData();
Task.Run(async () =>
_ = Task.Run(async () =>
{
while (true)
{
@@ -31,7 +32,7 @@ namespace ServiceLib.Handler
public async Task<ConcurrentBag<ProfileExItem>> GetProfileExs()
{
return _lstProfileEx;
return await Task.FromResult(_lstProfileEx);
}
private async Task InitData()
@@ -87,7 +88,7 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog("ProfileExHandler", ex);
Logging.SaveLog(_tag, ex);
}
}
}
@@ -119,7 +120,7 @@ namespace ServiceLib.Handler
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}

View File

@@ -12,22 +12,20 @@
private StatisticsXrayService? _statisticsXray;
private StatisticsSingboxService? _statisticsSingbox;
private static readonly string _tag = "StatisticsHandler";
public List<ServerStatItem> ServerStat => _lstServerStat;
public async Task Init(Config config, Action<ServerSpeedItem> updateFunc)
{
_config = config;
_updateFunc = updateFunc;
if (!config.GuiItem.EnableStatistics)
if (config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)
{
return;
await InitData();
_statisticsXray = new StatisticsXrayService(config, UpdateServerStatHandler);
_statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler);
}
await InitData();
_statisticsXray = new StatisticsXrayService(config, UpdateServerStatHandler);
_statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler);
}
public void Close()
@@ -39,7 +37,7 @@
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}
@@ -61,7 +59,7 @@
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}
@@ -72,6 +70,11 @@
return;
}
if (indexId == toIndexId)
{
return;
}
var stat = _lstServerStat.FirstOrDefault(t => t.IndexId == indexId);
if (stat == null)
{
@@ -96,7 +99,7 @@
private void UpdateServerStatHandler(ServerSpeedItem server)
{
UpdateServerStat(server);
_ = UpdateServerStat(server);
}
private async Task UpdateServerStat(ServerSpeedItem server)

View File

@@ -2,9 +2,9 @@
{
public class ProxySettingLinux
{
public static async Task SetProxy(string host, int port)
public static async Task SetProxy(string host, int port, string exceptions)
{
var lstCmd = GetSetCmds(host, port);
var lstCmd = GetSetCmds(host, port, exceptions);
await ExecCmd(lstCmd);
}
@@ -29,25 +29,39 @@
}
}
private static List<CmdItem> GetSetCmds(string host, int port)
private static List<CmdItem> GetSetCmds(string host, int port, string exceptions)
{
var isKde = IsKde(out var configDir);
List<string> lstType = ["", "http", "https", "socks", "ftp"];
List<CmdItem> lstCmd = [];
//GNOME
foreach (var type in lstType)
{
lstCmd.AddRange(GetSetCmd4Gnome(type, host, port));
}
if (exceptions.IsNotEmpty())
{
lstCmd.AddRange(GetSetCmd4Gnome("exceptions", exceptions, 0));
}
if (isKde)
{
foreach (var type in lstType)
{
lstCmd.AddRange(GetSetCmd4Kde(type, host, port, configDir));
}
}
else
{
foreach (var type in lstType)
if (exceptions.IsNotEmpty())
{
lstCmd.AddRange(GetSetCmd4Gnome(type, host, port));
lstCmd.AddRange(GetSetCmd4Kde("exceptions", exceptions, 0, configDir));
}
// Notify system to reload
lstCmd.Add(new CmdItem()
{
Cmd = "dbus-send",
Arguments = ["--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''"]
});
}
return lstCmd;
}
@@ -57,44 +71,58 @@
var isKde = IsKde(out var configDir);
List<CmdItem> lstCmd = [];
//GNOME
lstCmd.Add(new CmdItem()
{
Cmd = "gsettings",
Arguments = ["set", "org.gnome.system.proxy", "mode", "none"]
});
if (isKde)
{
lstCmd.Add(new CmdItem()
{
Cmd = "kwriteconfig5",
Cmd = GetKdeVersion(),
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "0"]
});
}
else
{
// Notify system to reload
lstCmd.Add(new CmdItem()
{
Cmd = "gsettings",
Arguments = ["set", "org.gnome.system.proxy", "mode", "none"]
Cmd = "dbus-send",
Arguments = ["--type=signal", "/KIO/Scheduler", "org.kde.KIO.Scheduler.reparseSlaveConfiguration", "string:''"]
});
}
return lstCmd;
}
private static List<CmdItem> GetSetCmd4Kde(string type, string host, int port, string configDir)
{
List<CmdItem> lstCmd = [];
var cmd = GetKdeVersion();
if (type.IsNullOrEmpty())
{
lstCmd.Add(new()
{
Cmd = "kwriteconfig5",
Cmd = cmd,
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "ProxyType", "1"]
});
}
else if (type == "exceptions")
{
lstCmd.Add(new()
{
Cmd = cmd,
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", "NoProxyFor", host]
});
}
else
{
var type2 = type.Equals("https") ? "http" : type;
lstCmd.Add(new CmdItem()
{
Cmd = "kwriteconfig5",
Cmd = cmd,
Arguments = ["--file", $"{configDir}/kioslaverc", "--group", "Proxy Settings", "--key", $"{type}Proxy", $"{type2}://{host}:{port}"]
});
}
@@ -114,6 +142,14 @@
Arguments = ["set", "org.gnome.system.proxy", "mode", "manual"]
});
}
else if (type == "exceptions")
{
lstCmd.Add(new()
{
Cmd = "gsettings",
Arguments = ["set", $"org.gnome.system.proxy", "ignore-hosts", JsonUtils.Serialize(host.Split(','), false)]
});
}
else
{
lstCmd.Add(new()
@@ -136,7 +172,11 @@
{
configDir = "/home";
var desktop = Environment.GetEnvironmentVariable("XDG_CURRENT_DESKTOP");
var isKde = string.Equals(desktop, "KDE", StringComparison.OrdinalIgnoreCase);
var desktop2 = Environment.GetEnvironmentVariable("XDG_SESSION_DESKTOP");
var isKde = string.Equals(desktop, "KDE", StringComparison.OrdinalIgnoreCase)
|| string.Equals(desktop, "plasma", StringComparison.OrdinalIgnoreCase)
|| string.Equals(desktop2, "KDE", StringComparison.OrdinalIgnoreCase)
|| string.Equals(desktop2, "plasma", StringComparison.OrdinalIgnoreCase);
if (isKde)
{
var homeDir = Environment.GetEnvironmentVariable("HOME");
@@ -148,5 +188,15 @@
return isKde;
}
private static string GetKdeVersion()
{
var ver = Environment.GetEnvironmentVariable("KDE_SESSION_VERSION") ?? "0";
return ver switch
{
"6" => "kwriteconfig6",
_ => "kwriteconfig5"
};
}
}
}

View File

@@ -2,29 +2,27 @@
{
public class ProxySettingOSX
{
/*
* 仅测试了MacOS 13.7.1 x86 版本,其他版本有待确认
*/
/// <summary>
/// 应用接口类型
/// </summary>
private static readonly List<string> LstInterface = ["Ethernet", "Wi-Fi", "Thunderbolt Bridge"];
private static readonly List<string> LstInterface = ["Ethernet", "Wi-Fi", "Thunderbolt Bridge", "USB 10/100/1000 LAN"];
/// <summary>
/// 代理类型,对应 http,https,socks
/// </summary>
private static readonly List<string> LstTypes = ["setwebproxy", "setsecurewebproxy", "setsocksfirewallproxy"];
public static async Task SetProxy(string host, int port)
public static async Task SetProxy(string host, int port, string exceptions)
{
var lstCmd = GetSetCmds(host, port);
var lstInterface = await GetListNetworkServices();
var lstCmd = GetSetCmds(lstInterface, host, port, exceptions);
await ExecCmd(lstCmd);
}
public static async Task UnsetProxy()
{
var lstCmd = GetUnsetCmds();
var lstInterface = await GetListNetworkServices();
var lstCmd = GetUnsetCmds(lstInterface);
await ExecCmd(lstCmd);
}
@@ -42,17 +40,27 @@
}
}
private static List<CmdItem> GetSetCmds(string host, int port)
private static List<CmdItem> GetSetCmds(List<string> lstInterface, string host, int port, string exceptions)
{
List<CmdItem> lstCmd = [];
foreach (var interf in LstInterface)
foreach (var interf in lstInterface)
{
foreach (var type in LstTypes)
{
lstCmd.Add(new CmdItem()
{
Cmd = "networksetup",
Arguments = [$"-{type}", interf, host, (type.Contains("socks") ? (port - 1) : port).ToString()]
Arguments = [$"-{type}", interf, host, port.ToString()]
});
}
if (exceptions.IsNotEmpty())
{
List<string> args = [$"-setproxybypassdomains", interf];
args.AddRange(exceptions.Split(','));
lstCmd.Add(new CmdItem()
{
Cmd = "networksetup",
Arguments = args
});
}
}
@@ -60,10 +68,10 @@
return lstCmd;
}
private static List<CmdItem> GetUnsetCmds()
private static List<CmdItem> GetUnsetCmds(List<string> lstInterface)
{
List<CmdItem> lstCmd = [];
foreach (var interf in LstInterface)
foreach (var interf in lstInterface)
{
foreach (var type in LstTypes)
{
@@ -77,5 +85,17 @@
return lstCmd;
}
public static async Task<List<string>> GetListNetworkServices()
{
var services = await Utils.GetListNetworkServices();
if (services.IsNullOrEmpty())
{
return LstInterface;
}
var lst = services.Split(Environment.NewLine).Where(t => t.Length > 0 && t.Contains('*') == false);
return lst.ToList();
}
}
}

View File

@@ -69,10 +69,9 @@ namespace ServiceLib.Handler.SysProxy
}
return result;
}
catch (Exception ex)
catch
{
SetProxyFallback(strProxy, exceptions, type);
//Logging.SaveLog(ex.Message, ex);
return false;
}
}
@@ -177,7 +176,8 @@ namespace ServiceLib.Handler.SysProxy
}
// FREE the data ASAP
if (list.szConnection != nint.Zero) Marshal.FreeHGlobal(list.szConnection); // release mem 3
if (list.szConnection != nint.Zero)
Marshal.FreeHGlobal(list.szConnection); // release mem 3
if (optionCount > 1)
{
Marshal.FreeHGlobal(options[1].m_Value.m_StringPtr); // release mem 1
@@ -357,4 +357,4 @@ namespace ServiceLib.Handler.SysProxy
);
}
}
}
}

View File

@@ -2,6 +2,8 @@
{
public static class SysProxyHandler
{
private static readonly string _tag = "SysProxyHandler";
public static async Task<bool> UpdateSysProxy(Config config, bool forceDisable)
{
var type = config.SystemProxyItem.SysProxyType;
@@ -13,8 +15,8 @@
try
{
var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.http);
var portSocks = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
var exceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
if (port <= 0)
{
return false;
@@ -23,16 +25,16 @@
{
case ESysProxyType.ForcedChange when Utils.IsWindows():
{
GetWindowsProxyString(config, port, portSocks, out var strProxy, out var strExceptions);
GetWindowsProxyString(config, port, out var strProxy, out var strExceptions);
ProxySettingWindows.SetProxy(strProxy, strExceptions, 2);
break;
}
case ESysProxyType.ForcedChange when Utils.IsLinux():
await ProxySettingLinux.SetProxy(Global.Loopback, port);
await ProxySettingLinux.SetProxy(Global.Loopback, port, exceptions);
break;
case ESysProxyType.ForcedChange when Utils.IsOSX():
await ProxySettingOSX.SetProxy(Global.Loopback, port);
await ProxySettingOSX.SetProxy(Global.Loopback, port, exceptions);
break;
case ESysProxyType.ForcedClear when Utils.IsWindows():
@@ -59,17 +61,17 @@
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return true;
}
private static void GetWindowsProxyString(Config config, int port, int portSocks, out string strProxy, out string strExceptions)
private static void GetWindowsProxyString(Config config, int port, out string strProxy, out string strExceptions)
{
strExceptions = "";
strExceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
if (config.SystemProxyItem.NotProxyLocalAddress)
{
strExceptions = $"<local>;{config.ConstItem.DefIEProxyExceptions};{config.SystemProxyItem.SystemProxyExceptions}";
strExceptions = $"<local>;{strExceptions}";
}
strProxy = string.Empty;
@@ -82,7 +84,7 @@
strProxy = config.SystemProxyItem.SystemProxyAdvancedProtocol
.Replace("{ip}", Global.Loopback)
.Replace("{http_port}", port.ToString())
.Replace("{socks_port}", portSocks.ToString());
.Replace("{socks_port}", port.ToString());
}
}

View File

@@ -1,4 +1,4 @@
using System.Net;
using System.Net;
using WebDav;
namespace ServiceLib.Handler
@@ -13,7 +13,7 @@ namespace ServiceLib.Handler
private string? _lastDescription;
private string _webDir = Global.AppName + "_backup";
private readonly string _webFileName = "backup.zip";
private string _logTitle = "WebDav--";
private readonly string _tag = "WebDav--";
public WebDavHandler()
{
@@ -61,7 +61,8 @@ namespace ServiceLib.Handler
private async Task<bool> TryCreateDir()
{
if (_client is null) return false;
if (_client is null)
return false;
try
{
var result2 = await _client.Mkcol(_webDir);
@@ -81,13 +82,13 @@ namespace ServiceLib.Handler
private void SaveLog(string desc)
{
_lastDescription = desc;
Logging.SaveLog(_logTitle + desc);
Logging.SaveLog(_tag + desc);
}
private void SaveLog(Exception ex)
{
_lastDescription = ex.Message;
Logging.SaveLog(_logTitle, ex);
Logging.SaveLog(_tag, ex);
}
public async Task<bool> CheckConnection()
@@ -176,4 +177,4 @@ namespace ServiceLib.Handler
public string GetLastError() => _lastDescription ?? string.Empty;
}
}
}

View File

@@ -29,7 +29,7 @@
public string? destinationPort { get; set; }
public string? host { get; set; }
public string? nsMode { get; set; }
public object uid { get; set; }
public object? uid { get; set; }
public string? process { get; set; }
public string? processPath { get; set; }
public string? remoteDestination { get; set; }

View File

@@ -47,6 +47,7 @@
public SystemProxyItem SystemProxyItem { get; set; }
public WebDavItem WebDavItem { get; set; }
public CheckUpdateItem CheckUpdateItem { get; set; }
public Fragment4RayItem? Fragment4RayItem { get; set; }
public List<InItem> Inbound { get; set; }
public List<KeyEventItem> GlobalHotkeys { get; set; }
public List<CoreTypeItem> CoreTypeItem { get; set; }

View File

@@ -24,21 +24,16 @@
public class InItem
{
public int LocalPort { get; set; }
public string Protocol { get; set; }
public bool UdpEnabled { get; set; }
public bool SniffingEnabled { get; set; } = true;
public List<string>? DestOverride { get; set; } = ["http", "tls"];
public bool RouteOnly { get; set; }
public bool AllowLANConn { get; set; }
public bool NewPort4LAN { get; set; }
public string User { get; set; }
public string Pass { get; set; }
public bool SecondLocalPortEnabled { get; set; }
}
[Serializable]
@@ -72,21 +67,13 @@
public class GUIItem
{
public bool AutoRun { get; set; }
public bool EnableStatistics { get; set; }
public bool DisplayRealTimeSpeed { get; set; }
public bool KeepOlderDedupl { get; set; }
public bool IgnoreGeoUpdateCore { get; set; } = true;
public int AutoUpdateInterval { get; set; }
public bool EnableSecurityProtocolTls13 { get; set; }
public int TrayMenuServersLimit { get; set; } = 20;
public bool EnableHWA { get; set; } = false;
public bool EnableLog { get; set; } = true;
}
@@ -107,9 +94,8 @@
public double MainGirdHeight1 { get; set; }
public double MainGirdHeight2 { get; set; }
public EGirdOrientation MainGirdOrientation { get; set; } = EGirdOrientation.Vertical;
public bool ColorModeDark { get; set; }
public bool FollowSystemTheme { get; set; }
public string? ColorPrimaryName { get; set; }
public string? CurrentTheme { get; set; }
public string CurrentLanguage { get; set; }
public string CurrentFontFamily { get; set; }
public int CurrentFontSize { get; set; }
@@ -124,8 +110,7 @@
[Serializable]
public class ConstItem
{
public string DefIEProxyExceptions { get; set; }
public string SubConvertUrl { get; set; } = string.Empty;
public string? SubConvertUrl { get; set; }
public string? GeoSourceUrl { get; set; }
public string? SrsSourceUrl { get; set; }
public string? RouteRulesTemplateSourceUrl { get; set; }
@@ -171,6 +156,7 @@
public int SpeedTestTimeout { get; set; }
public string SpeedTestUrl { get; set; }
public string SpeedPingTestUrl { get; set; }
public int SpeedTestPageSize { get; set; }
}
[Serializable]
@@ -222,7 +208,6 @@
public int ProxiesSorting { get; set; }
public bool ProxiesAutoRefresh { get; set; }
public int ProxiesAutoDelayTestInterval { get; set; } = 10;
public int ConnectionsSorting { get; set; }
public bool ConnectionsAutoRefresh { get; set; }
public int ConnectionsRefreshInterval { get; set; } = 2;
}
@@ -251,4 +236,12 @@
public bool CheckPreReleaseUpdate { get; set; }
public List<string>? SelectedCoreTypes { get; set; }
}
[Serializable]
public class Fragment4RayItem
{
public string? Packets { get; set; }
public string? Length { get; set; }
public string? Interval { get; set; }
}
}

View File

@@ -1,4 +1,4 @@
namespace ServiceLib.Models
namespace ServiceLib.Models
{
[Serializable]
public class CoreInfo
@@ -16,6 +16,6 @@
public string? DownloadUrlOSXArm64 { get; set; }
public string? Match { get; set; }
public string? VersionArg { get; set; }
public bool RedirectInfo { get; set; }
public bool AbsolutePath { get; set; }
}
}
}

View File

@@ -324,7 +324,8 @@ namespace ServiceLib.Models
public class WsSettings4Ray
{
public string path { get; set; }
public string? path { get; set; }
public string? host { get; set; }
public Headers4Ray headers { get; set; }
}
@@ -349,21 +350,9 @@ namespace ServiceLib.Models
public string? path { get; set; }
public string? host { get; set; }
public string? mode { get; set; }
public string? scMaxEachPostBytes { get; set; }
public string? scMaxConcurrentPosts { get; set; }
public string? scMinPostsIntervalMs { get; set; }
public Xmux4Ray? xmux { get; set; }
public object? extra { get; set; }
}
public class Xmux4Ray
{
public int? maxConcurrency { get; set; }
public int? maxConnections { get; set; }
public int? cMaxReuseTimes { get; set; }
public int? cMaxLifetimeMs { get; set; }
}
public class HttpSettings4Ray
{
public string? path { get; set; }

View File

@@ -403,7 +403,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Custom Icon 的本地化字符串。
/// 查找类似 Custom icon 的本地化字符串。
/// </summary>
public static string LvCustomIcon {
get {
@@ -610,7 +610,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 URL(Optional) 的本地化字符串。
/// 查找类似 URL (optional) 的本地化字符串。
/// </summary>
public static string LvUrl {
get {
@@ -843,6 +843,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Copy proxy command to clipboard 的本地化字符串。
/// </summary>
public static string menuCopyProxyCmdToClipboard {
get {
return ResourceManager.GetString("menuCopyProxyCmdToClipboard", resourceCulture);
}
}
/// <summary>
/// 查找类似 Clone selected server 的本地化字符串。
/// </summary>
@@ -942,15 +951,6 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Import old config (guiNConfig) 的本地化字符串。
/// </summary>
public static string menuImportOldGuiConfig {
get {
return ResourceManager.GetString("menuImportOldGuiConfig", resourceCulture);
}
}
/// <summary>
/// 查找类似 Import Rules From Clipboard 的本地化字符串。
/// </summary>
@@ -1006,7 +1006,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 One-click multi test Latency and speed (Ctrl+E) 的本地化字符串。
/// 查找类似 One-click multi-test latency and speed (Ctrl+E) 的本地化字符串。
/// </summary>
public static string menuMixedTestServer {
get {
@@ -1248,6 +1248,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Iran 的本地化字符串。
/// </summary>
public static string menuRegionalPresetsIran {
get {
return ResourceManager.GetString("menuRegionalPresetsIran", resourceCulture);
}
}
/// <summary>
/// 查找类似 Russia 的本地化字符串。
/// </summary>
@@ -1339,7 +1348,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Import Advanced Rules 的本地化字符串。
/// 查找类似 Import Rules 的本地化字符串。
/// </summary>
public static string menuRoutingAdvancedImportRules {
get {
@@ -1357,7 +1366,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Set as active rule(Enter) 的本地化字符串。
/// 查找类似 Set as active rule (Enter) 的本地化字符串。
/// </summary>
public static string menuRoutingAdvancedSetDefault {
get {
@@ -1527,15 +1536,6 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Save Interface Layout 的本地化字符串。
/// </summary>
public static string menuStorageUI {
get {
return ResourceManager.GetString("menuStorageUI", resourceCulture);
}
}
/// <summary>
/// 查找类似 Add 的本地化字符串。
/// </summary>
@@ -2094,6 +2094,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Starting retesting failed parts, {0} remaining. Press ESC to terminate... 的本地化字符串。
/// </summary>
public static string SpeedtestingTestFailedPart {
get {
return ResourceManager.GetString("SpeedtestingTestFailedPart", resourceCulture);
}
}
/// <summary>
/// 查找类似 Waiting for testing (press ESC to terminate)... 的本地化字符串。
/// </summary>
@@ -2294,7 +2303,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Support DnsObject, Click to view the document 的本地化字符串。
/// 查找类似 Supports DnsObject; Click to view documentation 的本地化字符串。
/// </summary>
public static string TbDnsObjectDoc {
get {
@@ -2347,15 +2356,6 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Enable advanced function 的本地化字符串。
/// </summary>
public static string TbenableRoutingAdvanced {
get {
return ResourceManager.GetString("TbenableRoutingAdvanced", resourceCulture);
}
}
/// <summary>
/// 查找类似 Enable Tun 的本地化字符串。
/// </summary>
@@ -2393,7 +2393,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Set directly by pressing the keyboard, take effect after restart 的本地化字符串。
/// 查找类似 Set directly by pressing the keyboard; Takes effect after restart 的本地化字符串。
/// </summary>
public static string TbGlobalHotkeySettingTip {
get {
@@ -2599,6 +2599,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 socks: local port, socks2: second local port, socks3: LAN port 的本地化字符串。
/// </summary>
public static string TbRoutingInboundTagTips {
get {
return ResourceManager.GetString("TbRoutingInboundTagTips", resourceCulture);
}
}
/// <summary>
/// 查找类似 Domain 的本地化字符串。
/// </summary>
@@ -2663,7 +2672,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 *Set the rules, separated by commas (,); The comma in the regular is replaced by &lt;COMMA&gt; 的本地化字符串。
/// 查找类似 *Separate rules by commas (,); For a literal comma use &lt;COMMA&gt;; Prefix # to ignore a rule 的本地化字符串。
/// </summary>
public static string TbRoutingTips {
get {
@@ -2771,7 +2780,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Automatic update interval of Geo (hours) 的本地化字符串。
/// 查找类似 Automatic update interval for Geo files (hours) 的本地化字符串。
/// </summary>
public static string TbSettingsAutoUpdateInterval {
get {
@@ -2797,15 +2806,6 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Dark Mode 的本地化字符串。
/// </summary>
public static string TbSettingsColorMode {
get {
return ResourceManager.GetString("TbSettingsColorMode", resourceCulture);
}
}
/// <summary>
/// 查找类似 Core: basic settings 的本地化字符串。
/// </summary>
@@ -2852,7 +2852,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 FontFamily(Require restart) 的本地化字符串。
/// 查找类似 Font family (requires restart) 的本地化字符串。
/// </summary>
public static string TbSettingsCurrentFontFamily {
get {
@@ -2870,7 +2870,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Copy the font TTF/TTC file to the directory guiFonts, restart the settings 的本地化字符串。
/// 查找类似 Copy the font TTF/TTC file to the directory guiFonts; Reopen the settings window 的本地化字符串。
/// </summary>
public static string TbSettingsCurrentFontFamilyTip {
get {
@@ -2914,6 +2914,24 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Sniffing type 的本地化字符串。
/// </summary>
public static string TbSettingsDestOverride {
get {
return ResourceManager.GetString("TbSettingsDestOverride", resourceCulture);
}
}
/// <summary>
/// 查找类似 Display real-time speed (requires restart) 的本地化字符串。
/// </summary>
public static string TbSettingsDisplayRealTimeSpeed {
get {
return ResourceManager.GetString("TbSettingsDisplayRealTimeSpeed", resourceCulture);
}
}
/// <summary>
/// 查找类似 Outbound DNS address 的本地化字符串。
/// </summary>
@@ -2942,7 +2960,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Double-click server make active 的本地化字符串。
/// 查找类似 Double-clicking server makes it active 的本地化字符串。
/// </summary>
public static string TbSettingsDoubleClick2Activate {
get {
@@ -2951,7 +2969,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Automatically adjust column width after updating subscription 的本地化字符串。
/// 查找类似 Automatically adjust column width after subscription update 的本地化字符串。
/// </summary>
public static string TbSettingsEnableAutoAdjustMainLvColWidth {
get {
@@ -2978,7 +2996,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Enable Server Drag Drop Sort(Require restart) 的本地化字符串。
/// 查找类似 Enable sorting servers by drag-n-drop (requires restart) 的本地化字符串。
/// </summary>
public static string TbSettingsEnableDragDropSort {
get {
@@ -3014,7 +3032,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Enable hardware acceleration(Require restart) 的本地化字符串。
/// 查找类似 Enable hardware acceleration (requires restart) 的本地化字符串。
/// </summary>
public static string TbSettingsEnableHWA {
get {
@@ -3050,7 +3068,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Exception. Do not use proxy server for addresses beginning with,Use semicolon (;) 的本地化字符串。
/// 查找类似 Exclusions: Do not use proxy server for addresses beginning with the following. Use semicolon (;) to separate entries. 的本地化字符串。
/// </summary>
public static string TbSettingsExceptionTip {
get {
@@ -3059,11 +3077,11 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Follow System Theme 的本地化字符串。
/// 查找类似 Exclusions: Do not use proxy server for the following addresses. Use comma (,) to separate entries. 的本地化字符串。
/// </summary>
public static string TbSettingsFollowSystemTheme {
public static string TbSettingsExceptionTip2 {
get {
return ResourceManager.GetString("TbSettingsFollowSystemTheme", resourceCulture);
return ResourceManager.GetString("TbSettingsExceptionTip2", resourceCulture);
}
}
@@ -3113,16 +3131,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Ignore Geo files when updating core 的本地化字符串。
/// </summary>
public static string TbSettingsIgnoreGeoUpdateCore {
get {
return ResourceManager.GetString("TbSettingsIgnoreGeoUpdateCore", resourceCulture);
}
}
/// <summary>
/// 查找类似 Keep older when deduplication 的本地化字符串。
/// 查找类似 Keep the older when de-duplicating 的本地化字符串。
/// </summary>
public static string TbSettingsKeepOlderDedupl {
get {
@@ -3203,7 +3212,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Main layout orientation(Require restart) 的本地化字符串。
/// 查找类似 Main layout orientation (requires restart) 的本地化字符串。
/// </summary>
public static string TbSettingsMainGirdOrientation {
get {
@@ -3292,6 +3301,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Enable second mixed port 的本地化字符串。
/// </summary>
public static string TbSettingsSecondLocalPortEnabled {
get {
return ResourceManager.GetString("TbSettingsSecondLocalPortEnabled", resourceCulture);
}
}
/// <summary>
/// 查找类似 Set Win10 UWP Loopback 的本地化字符串。
/// </summary>
@@ -3311,7 +3329,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 SOCKS Port 的本地化字符串。
/// 查找类似 Mixed Port 的本地化字符串。
/// </summary>
public static string TbSettingsSocksPort {
get {
@@ -3320,7 +3338,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 http port = +1; Pac port = +4; *ray API port = +5; mihomo API port = +6; 的本地化字符串。
/// 查找类似 Pac port = +3; Xray API port = +4; mihomo API port = +5; 的本地化字符串。
/// </summary>
public static string TbSettingsSocksPortTip {
get {
@@ -3337,6 +3355,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Number per time for auto batch during speedtest(max 1000) 的本地化字符串。
/// </summary>
public static string TbSettingsSpeedTestPageSize {
get {
return ResourceManager.GetString("TbSettingsSpeedTestPageSize", resourceCulture);
}
}
/// <summary>
/// 查找类似 SpeedTest Single Timeout Value 的本地化字符串。
/// </summary>
@@ -3383,7 +3410,7 @@ namespace ServiceLib.Resx {
}
/// <summary>
/// 查找类似 Enable Statistics (Require restart) 的本地化字符串。
/// 查找类似 Enable traffic statistics (requires restart) 的本地化字符串。
/// </summary>
public static string TbSettingsStatistics {
get {
@@ -3409,6 +3436,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Theme 的本地化字符串。
/// </summary>
public static string TbSettingsTheme {
get {
return ResourceManager.GetString("TbSettingsTheme", resourceCulture);
}
}
/// <summary>
/// 查找类似 Enable Security Protocol TLS v1.3 (subscription/update) 的本地化字符串。
/// </summary>

View File

@@ -118,7 +118,7 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="BatchExportURLSuccessfully" xml:space="preserve">
<value>Batch export share URL to clipboard successfully</value>
<value>ارسال دسته ای آدرس اینترنتی اشتراک گذاری به کلیپ بورد با موفقیت.</value>
</data>
<data name="CheckServerSettings" xml:space="preserve">
<value>لطفا ابتدا تنظیمات سرور را بررسی کنید</value>
@@ -136,7 +136,7 @@
<value>دانلود</value>
</data>
<data name="DownloadYesNo" xml:space="preserve">
<value>Whether to download? {0}</value>
<value>آیا برای دانلود؟ {0}</value>
</data>
<data name="FailedConversionConfiguration" xml:space="preserve">
<value>تبدیل فایل پیکربندی انجام نشد</value>
@@ -226,7 +226,7 @@
<value>هیچ اشتراک معتبری تنظیم نشده است</value>
</data>
<data name="MsgParsingSuccessfully" xml:space="preserve">
<value>Resolve {0} successfully</value>
<value>حل {0} با موفقیت</value>
</data>
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
<value>شروع به دریافت اشتراک شد</value>
@@ -253,19 +253,19 @@
<value>هسته با موفقیت بروزرسانی شد! راه اندازی مجدد سرویس...</value>
</data>
<data name="NonvmessOrssProtocol" xml:space="preserve">
<value>Non-VMess or ss protocol</value>
<value>پروتکل غیر VMess یا ss</value>
</data>
<data name="NotFoundCore" xml:space="preserve">
<value>The Core file (file name: {1}) was not found under the folder ({0}), please download and put it in the folder, download address: {2}</value>
<value>فایل Core (نام فایل: {1}) در زیر پوشه ({0}) یافت نشد، لطفاً آن را دانلود کرده و در پوشه قرار دهید، آدرس دانلود: {2}</value>
</data>
<data name="NoValidQRcodeFound" xml:space="preserve">
<value>Scan completed, no valid QR code found</value>
<value>اسکن کامل شد، QRcode معتبری یافت نشد</value>
</data>
<data name="OperationFailed" xml:space="preserve">
<value> عملیات انجام نشد، لطفا بررسی کنید و دوباره امتحان کنید</value>
</data>
<data name="PleaseFillRemarks" xml:space="preserve">
<value>Please Fill Remarks</value>
<value>لطفا ملاحظات را پر کنید</value>
</data>
<data name="PleaseSelectEncryption" xml:space="preserve">
<value>لطفاً روش رمزگذاری را انتخاب کنید</value>
@@ -277,16 +277,16 @@
<value>لطفا ابتدا سرور را انتخاب کنید</value>
</data>
<data name="RemoveDuplicateServerResult" xml:space="preserve">
<value>Servers deduplication completed. Old: {0}, New: {1}.</value>
<value>حذف مجدد سرورها تکمیل شد. قدیمی: {0}، جدید: {1}.</value>
</data>
<data name="RemoveServer" xml:space="preserve">
<value>آیا مطمئن هستید که سرور را حذف می کنید؟</value>
</data>
<data name="SaveClientConfigurationIn" xml:space="preserve">
<value>The client configuration file is saved at: {0}</value>
<value>فایل پیکربندی کلاینت در این آدرس ذخیره می شود: {0}</value>
</data>
<data name="StartService" xml:space="preserve">
<value>Start service ({0})...</value>
<value>شروع سرویس ({0})...</value>
</data>
<data name="SuccessfulConfiguration" xml:space="preserve">
<value>پیکربندی با موفقیت انجام شد
@@ -317,19 +317,19 @@
<value>{0},یکی از مورد نیاز.</value>
</data>
<data name="LvRemarks" xml:space="preserve">
<value>Remarks</value>
<value>ملاحظات</value>
</data>
<data name="LvUrl" xml:space="preserve">
<value>Url(Optional)</value>
<value>آدرس اینترنتی (اختیاری)</value>
</data>
<data name="LvCount" xml:space="preserve">
<value>Count</value>
<value>شمارش</value>
</data>
<data name="MsgNeedUrl" xml:space="preserve">
<value>Please fill in the address (Url)</value>
<value>لطفا آدرس (آدرس اینترنتی) را وارد کنید</value>
</data>
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
<value>Do you want to append rules? Choose yes to append, choose otherwise to replace</value>
<value>آیا می خواهید قوانین را اضافه کنید؟ برای ضمیمه بله را انتخاب کنید، در غیر این صورت جایگزین کنید</value>
</data>
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
<value>دانلود GeoFile: {0} با موفقیت</value>
@@ -386,10 +386,10 @@
<value>*Kcp seed</value>
</data>
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
<value>Global hotkey {0} registered failed, reason {1}</value>
<value>کلید میانبر جهانی {0} ثبت نشد، دلیل کلید میانبر جهانی {0} ثبت ناموفق بود، دلیل {1}{1}</value>
</data>
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
<value>Global hotkey {0} registered successfully</value>
<value>کلید میانبر جهانی {0} با موفقیت ثبت شد</value>
</data>
<data name="UngroupedServers" xml:space="preserve">
<value>گروه بندی نشده</value>
@@ -398,7 +398,7 @@
<value>همه سرورها</value>
</data>
<data name="FillServerAddressCustom" xml:space="preserve">
<value>Please browse to import server configuration</value>
<value>لطفاً برای وارد کردن پیکربندی سرور مرور کنید</value>
</data>
<data name="Speedtesting" xml:space="preserve">
<value>درحال تست کردن...</value>
@@ -481,9 +481,6 @@
<data name="TbSettingsColor" xml:space="preserve">
<value>رنگ</value>
</data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>حالت تاریک</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>زبان</value>
</data>
@@ -593,7 +590,7 @@
<value>آدرس</value>
</data>
<data name="TbAllowInsecure" xml:space="preserve">
<value>اجازه ناامن</value>
<value>اعطای مجوز ناامن</value>
</data>
<data name="TbAlpn" xml:space="preserve">
<value>Alpn</value>
@@ -602,10 +599,10 @@
<value>AlterId</value>
</data>
<data name="TbFingerprint" xml:space="preserve">
<value>Fingerprint</value>
<value>اثرانگشت</value>
</data>
<data name="TbHeaderType" xml:space="preserve">
<value>Camouflage type</value>
<value>نوع Camouflage</value>
</data>
<data name="TbId" xml:space="preserve">
<value>UUID(id)</value>
@@ -620,13 +617,13 @@
<value>پورت</value>
</data>
<data name="TbRemarks" xml:space="preserve">
<value>Alias (remarks)</value>
<value>نام مستعار (ملاحظات)</value>
</data>
<data name="TbRequestHost" xml:space="preserve">
<value>Camouflage domain(host)</value>
</data>
<data name="TbSecurity" xml:space="preserve">
<value>Encryption method (security)</value>
<value>روش رمزگذاری (امنیتی)</value>
</data>
<data name="TbSNI" xml:space="preserve">
<value>SNI</value>
@@ -635,7 +632,7 @@
<value>TLS</value>
</data>
<data name="TipNetwork" xml:space="preserve">
<value>*Default value tcp</value>
<value>*مقدار پیش فرض tcp</value>
</data>
<data name="TbCoreType" xml:space="preserve">
<value>نوع هسته</value>
@@ -644,7 +641,7 @@
<value>جریان</value>
</data>
<data name="TbGUID" xml:space="preserve">
<value>Generate</value>
<value>ساختن</value>
</data>
<data name="TbId3" xml:space="preserve">
<value>رمزعبور</value>
@@ -668,10 +665,10 @@
<value>txtPreSocksPort</value>
</data>
<data name="TipPreSocksPort" xml:space="preserve">
<value>* After setting this value, an socks service will be started using Xray/sing-box(Tun) to provide functions such as speed display</value>
<value>* پس از تنظیم این مقدار، یک سرویس جوراب با استفاده از Xray/sing-box (Tun) برای ارائه عملکردهایی مانند نمایش سرعت شروع می شود.</value>
</data>
<data name="TbBrowse" xml:space="preserve">
<value>Browse</value>
<value>مرور کردن</value>
</data>
<data name="TbEdit" xml:space="preserve">
<value>ویرایش</value>
@@ -683,16 +680,16 @@
<value>اتصالات از LAN را مجاز کنید</value>
</data>
<data name="TbSettingsAutoHideStartup" xml:space="preserve">
<value>Auto hide startup</value>
<value>راه اندازی مخفی کردن خودکار</value>
</data>
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
<value>فاصله به روز رسانی خودکار و Geo (ساعت)</value>
<value>فاصله به روز رسانی خودکار برای فایل های Geo (ساعت)</value>
</data>
<data name="TbSettingsCore" xml:space="preserve">
<value>هسته: تنظیمات اولیه</value>
</data>
<data name="TbSettingsCoreDns" xml:space="preserve">
<value>V2ray DNS settings</value>
<value>تنظیمات V2ray DNS</value>
</data>
<data name="TbSettingsCoreKcp" xml:space="preserve">
<value>هسته: تنظیمات KCP</value>
@@ -701,13 +698,13 @@
<value>تنظیمات CoreType</value>
</data>
<data name="TbSettingsDefAllowInsecure" xml:space="preserve">
<value>اجازه ناامن</value>
<value>اعطای مجوز ناامن</value>
</data>
<data name="TbSettingsDomainStrategy4Freedom" xml:space="preserve">
<value>Outbound Freedom domainStrategy</value>
</data>
<data name="TbSettingsEnableAutoAdjustMainLvColWidth" xml:space="preserve">
<value>پس از به‌روزرسانی اشتراک، عرض ستون را به صورت خودکار تنظیم شود</value>
<value>پس از به‌روزرسانی اشتراک، عرض ستون به صورت خودکار تنظیم شود</value>
</data>
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
<value>به روز رسانی های پیش از انتشار را بررسی شود</value>
@@ -716,16 +713,16 @@
<value>استثنا</value>
</data>
<data name="TbSettingsExceptionTip" xml:space="preserve">
<value>Exception. Do not use proxy server for addresses beginning with,Use semicolon (;)</value>
<value>استثناها: از سرور پروکسی برای آدرس هایی که با موارد زیر شروع می شوند استفاده نکنید. برای جدا کردن ورودی ها از نقطه ویرگول (;) استفاده کنید.</value>
</data>
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>پورت Http</value>
</data>
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
<value>هنگام به‌روزرسانی هسته، فایل‌های Geo را نادیده بگیرید</value>
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
<value>نمایش سرعت واقعی (نیاز به راه اندازی مجدد)</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>Keep older when deduplication</value>
<value>هنگام حذف کپی، قدیمی تر را نگه دارید</value>
</data>
<data name="TbSettingsLogEnabled" xml:space="preserve">
<value>ثبت گزارش های محلی</value>
@@ -734,49 +731,49 @@
<value>سطح ثبت رویداد</value>
</data>
<data name="TbSettingsMuxEnabled" xml:space="preserve">
<value>Turn on Mux Multiplexing</value>
<value>فعال کردن Mux Multiplexing</value>
</data>
<data name="TbSettingsN" xml:space="preserve">
<value>تنظیمات v2rayN</value>
</data>
<data name="TbSettingsPass" xml:space="preserve">
<value>Auth pass</value>
<value>مجوز احراز هویت</value>
</data>
<data name="TbSettingsRemoteDNS" xml:space="preserve">
<value>سفارشی DNS (multiple, separated by commas (,))</value>
</data>
<data name="TbSettingsSetUWP" xml:space="preserve">
<value>Set Win10 UWP Loopback</value>
<value>تنظیم کردن Win10 UWP Loopback</value>
</data>
<data name="TbSettingsSniffingEnabled" xml:space="preserve">
<value>Turn on Sniffing</value>
<value>فعال کردن Sniffing</value>
</data>
<data name="TbSettingsSocksPort" xml:space="preserve">
<value>ساکس Port</value>
<value>پورت Mixed</value>
</data>
<data name="TbSettingsStartBoot" xml:space="preserve">
<value>درهنگام راه ائدازی شروع شود</value>
</data>
<data name="TbSettingsStatistics" xml:space="preserve">
<value>فعال کردن آمار (نیاز به راه اندازی مجدد)</value>
<value>فعال کردن آمار ترافیک (نیاز به راه اندازی مجدد)</value>
</data>
<data name="TbSettingsSubConvert" xml:space="preserve">
<value>Subscription conversion Url</value>
<value>آدرس اینترنتی تبدیل اشتراک</value>
</data>
<data name="TbSettingsSystemproxy" xml:space="preserve">
<value>تنظیمات پراکسی سیستم</value>
</data>
<data name="TbSettingsTLS13" xml:space="preserve">
<value>Enable Security Protocol TLS v1.3 (subscription/update)</value>
<value>فعال کردن پروتکل امنیتی TLS نسخه 1.3 (اشتراک/به‌روزرسانی)</value>
</data>
<data name="TbSettingsTrayMenuServersLimit" xml:space="preserve">
<value>Tray right-click menu servers display limit</value>
<value>محدودیت نمایش سرورهای منوی سینی کلیک راست</value>
</data>
<data name="TbSettingsUdpEnabled" xml:space="preserve">
<value>UDP را فعال شود</value>
<value>فعال سازی UDP</value>
</data>
<data name="TbSettingsUser" xml:space="preserve">
<value>Auth user</value>
<value>تایید کاربر</value>
</data>
<data name="TbClearSystemProxy" xml:space="preserve">
<value>پاک کردن پروکسی سیستم</value>
@@ -821,16 +818,16 @@
<value>پایین (D)</value>
</data>
<data name="menuMoveTop" xml:space="preserve">
<value>Move to top (T)</value>
<value>حرکت به بالا (T)</value>
</data>
<data name="menuMoveUp" xml:space="preserve">
<value>Up (U)</value>
<value>بالا (U)</value>
</data>
<data name="MsgFilterTitle" xml:space="preserve">
<value>Filter, support regular</value>
<value>فیلتر، پشتیبانی منظم</value>
</data>
<data name="menuWebsiteItem" xml:space="preserve">
<value>{0} Website</value>
<value>{0} وب سایت</value>
</data>
<data name="menuRoutingAdvanced" xml:space="preserve">
<value>عملکرد پیشرفته</value>
@@ -839,13 +836,13 @@
<value>اضافه کردن</value>
</data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>وارد کردن قوانین پیشرفته</value>
<value>وارد کردن مجموعه قوانین</value>
</data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>حذف انتخاب شده</value>
</data>
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
<value>Set as active rule</value>
<value>تنظیم کردن به عنوان قانون فعال</value>
</data>
<data name="TbdomainMatcher" xml:space="preserve">
<value>تطبیق دامنه</value>
@@ -853,23 +850,20 @@
<data name="TbdomainStrategy" xml:space="preserve">
<value>استراتژی دامنه</value>
</data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>فعال کردن عملکرد پیشرفته</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.Block Domain or IP</value>
<value>3. مسدود کردن دامنه یا آیپی</value>
</data>
<data name="TbRoutingTabDirect" xml:space="preserve">
<value>2.Direct Domain or IP</value>
<value>2. دایرکت کردن دامنه یا IP</value>
</data>
<data name="TbRoutingTabProxy" xml:space="preserve">
<value>1.Proxy Domain or IP</value>
<value>1. پروکسی کردن دامنه یا IP</value>
</data>
<data name="TbRoutingTabRuleList" xml:space="preserve">
<value>لیست مجموعه قوانین از پیش تعریف شده</value>
</data>
<data name="TbRoutingTips" xml:space="preserve">
<value>*Set the rules, separated by commas (,); The comma in the regular is replaced by &lt;COMMA&gt;</value>
<value>*قوانین را با کاما (,) جدا کنید. برای کاما به معنای واقعی کلمه از &lt;COMMA&gt;; پیشوند # برای نادیده گرفتن یک قانون</value>
</data>
<data name="menuImportRulesFromClipboard" xml:space="preserve">
<value>وارد کردن قوانین از کلیپ بورد</value>
@@ -878,7 +872,7 @@
<value>وارد کردن قوانین از فایل</value>
</data>
<data name="menuImportRulesFromUrl" xml:space="preserve">
<value>وارد کردن قوانین از Sub Url</value>
<value>وارد کردن قوانین از آدرس اینترنتی Sub</value>
</data>
<data name="menuRoutingRuleSetting" xml:space="preserve">
<value>تنظیم قانون</value>
@@ -902,10 +896,10 @@
<value>دامنه و آی پی در هنگام ذخیره به طور خودکار مرتب می شوند</value>
</data>
<data name="TbRuleobjectDoc" xml:space="preserve">
<value>Ruleobject Doc</value>
<value>مستندات شی قانون</value>
</data>
<data name="TbDnsObjectDoc" xml:space="preserve">
<value>پشتیبانی از DnsObject</value>
<value>پشتیبانی از DnsObject. برای مشاهده مستندات کلیک کنید</value>
</data>
<data name="SubUrlTips" xml:space="preserve">
<value>گروه لطفا اینجا را خالی بگذارید</value>
@@ -920,16 +914,16 @@
<value>فقط مسیر</value>
</data>
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
<value>يەرلىك (Intranet) ئادرېسلارغا ۋاكالەتچى مۇلازىمېتىر ئىشلەتمەڭ</value>
<value>از سرورهای پروکسی برای آدرس های محلی (اینترانت) استفاده نکنید</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve">
<value>One-click test Latency and speed (Ctrl+E)</value>
<value>تاخیر و سرعت تست با یک کلیک (Ctrl+E)</value>
</data>
<data name="LvTestDelay" xml:space="preserve">
<value>تاخیر (میلی‌ثانیه)</value>
</data>
<data name="LvTestSpeed" xml:space="preserve">
<value>Speed(M/s)</value>
<value>سرعت (M/s)</value>
</data>
<data name="FailedToRunCore" xml:space="preserve">
<value>Core اجرا نشد، لطفاً گزارش را ببینید</value>
@@ -940,11 +934,8 @@
<data name="TbDisplayLog" xml:space="preserve">
<value>نمایش گزارش</value>
</data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>پیکربندی قدیمی guiNConfig را وارد شود</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>Tun را فعال شود</value>
<value>فعال سازی Tun</value>
</data>
<data name="TbSettingsNewPort4LAN" xml:space="preserve">
<value>پورت جدید برای LAN</value>
@@ -956,10 +947,10 @@
<value>User-Agent</value>
</data>
<data name="TbSettingsDefUserAgentTips" xml:space="preserve">
<value>This parameter is valid only for tcp/http and ws</value>
<value>این پارامتر فقط برای tcp/http و ws معتبر است</value>
</data>
<data name="TbSettingsEnableHWA" xml:space="preserve">
<value>فعال‌سازی شتاب‌دهنده سخت‌افزاری (نیاز به راه‌اندازی مجدد)</value>
<value>فعال‌ سازی شتاب‌ دهنده سخت‌ افزاری (نیاز به راه‌اندازی مجدد)</value>
</data>
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
<value>فعال کردن کش فایل مجموعه قوانین برای sing-box</value>
@@ -968,7 +959,7 @@
<value>مرتب سازی</value>
</data>
<data name="TbSortingDefault" xml:space="preserve">
<value>Default</value>
<value>پیش فرض</value>
</data>
<data name="TbSortingDelay" xml:space="preserve">
<value>تاخیر</value>
@@ -1007,10 +998,10 @@
<value>نوع قانون</value>
</data>
<data name="menuModeDirect" xml:space="preserve">
<value>Direct</value>
<value>مستقیم</value>
</data>
<data name="menuModeGlobal" xml:space="preserve">
<value>Global</value>
<value>جهانی</value>
</data>
<data name="menuModeNothing" xml:space="preserve">
<value>تغییر نده</value>
@@ -1019,193 +1010,193 @@
<value>قانون</value>
</data>
<data name="menuProxiesDelaytest" xml:space="preserve">
<value>Latency Test</value>
<value>تست تأخیر</value>
</data>
<data name="menuProxiesDelaytestPart" xml:space="preserve">
<value>Part Node Latency Test</value>
<value>تست تاخیر قسمت گره (نقطه اتصال)</value>
</data>
<data name="menuProxiesSelectActivity" xml:space="preserve">
<value>Select active node (Enter)</value>
<value>انتخاب گره فعال (Enter)</value>
</data>
<data name="menuRemoteBackup" xml:space="preserve">
<value>Backup to remote (WebDAV)</value>
<value>پشتیبان گیری از راه دور (WebDAV)</value>
</data>
<data name="menuRemoteRestore" xml:space="preserve">
<value>Restore from remote (WebDAV)</value>
<value>بازیابی از راه دور (WebDAV)</value>
</data>
<data name="TbSettingsDomainStrategy4Out" xml:space="preserve">
<value>Default domain strategy for outbound</value>
<value>استراتژی دامنه پیش فرض برای خروجی</value>
</data>
<data name="menuSetDefaultMultipleServer" xml:space="preserve">
<value>Multi-Server lowest latency</value>
<value>کمترین تأخیر چند سروره</value>
</data>
<data name="TbSettingsMainGirdOrientation" xml:space="preserve">
<value>Main layout orientation(Require restart)</value>
<value>جهت چیدمان اصلی (نیاز به راه اندازی مجدد)</value>
</data>
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
<value>Multi-server load balancing</value>
<value>تعادل بار چند سروره</value>
</data>
<data name="TbSettingsDomainDNSAddress" xml:space="preserve">
<value>Outbound DNS address</value>
<value>آدرس DNS خروجی</value>
</data>
<data name="menuProfileAutofitColumnWidth" xml:space="preserve">
<value>Auto column width adjustment</value>
<value>تنظیم خودکار عرض ستون</value>
</data>
<data name="menuExport2ShareUrlBase64" xml:space="preserve">
<value>Export Base64-encoded Share Links to Clipboard</value>
<value>صادر کردن پیوندهای اشتراک گذاری کدگذاری شده با Base64 به کلیپ بورد</value>
</data>
<data name="menuExport2ClientConfigClipboard" xml:space="preserve">
<value>Export selected server for complete configuration to clipboard</value>
<value>صادر کردن سرور انتخاب شده برای پیکربندی کامل به کلیپ بورد</value>
</data>
<data name="menuShowOrHideMainWindow" xml:space="preserve">
<value>Show or hide the main window</value>
<value>نمایش یا پنهان کردن پنجره اصلی</value>
</data>
<data name="UpdateStandalonePackageTip" xml:space="preserve">
<value>You are currently running a standalone package, please manually download the SelfContained.7z file to unzip and overwrite it!</value>
<value>شما در حال حاضر در حال اجرای یک بسته مستقل هستید، لطفاً فایل SelfContained.7z را به صورت دستی دانلود کنید تا آن را از حالت فشرده خارج کرده و بازنویسی کنید!</value>
</data>
<data name="TbPreSocksPort4Sub" xml:space="preserve">
<value>Custom config socks port</value>
<value>پیکربندی سفارشی ساکس پورت</value>
</data>
<data name="menuBackupAndRestore" xml:space="preserve">
<value>Backup and Restore</value>
<value>پشتیبان گیری و بازیابی</value>
</data>
<data name="menuLocalBackup" xml:space="preserve">
<value>Backup to local</value>
<value>پشتیبان گیری به محلی</value>
</data>
<data name="menuLocalRestore" xml:space="preserve">
<value>Restore from local</value>
<value>بازیابی از محلی</value>
</data>
<data name="menuLocalBackupAndRestore" xml:space="preserve">
<value>Local</value>
<value>محلی</value>
</data>
<data name="menuRemoteBackupAndRestore" xml:space="preserve">
<value>Remote (WebDAV)</value>
<value>از راه دور (WebDAV)</value>
</data>
<data name="LvWebDavUrl" xml:space="preserve">
<value>WebDav Url</value>
<value>آدرس اینترنتی WebDav</value>
</data>
<data name="LvWebDavUserName" xml:space="preserve">
<value>WebDav User Name</value>
<value>نام کاربری WebDav</value>
</data>
<data name="LvWebDavPassword" xml:space="preserve">
<value>WebDav Password</value>
<value>پسورد WebDav</value>
</data>
<data name="LvWebDavCheck" xml:space="preserve">
<value>WebDav Check</value>
<value>چک کردن WebDav</value>
</data>
<data name="LvWebDavDirName" xml:space="preserve">
<value>Remote folder name (optional)</value>
<value>نام پوشه راه دور (اختیاری)</value>
</data>
<data name="LocalRestoreInvalidZipTips" xml:space="preserve">
<value>Invalid backup file</value>
<value>فایل پشتیبان نامعتبر است</value>
</data>
<data name="ConnectionsHostFilterTitle" xml:space="preserve">
<value>Host filter</value>
</data>
<data name="TipActiveServer" xml:space="preserve">
<value>Active</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>Save Interface Layout</value>
<value>فعال سازی</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo files source (optional)</value>
<value>منبع فایل های جغرافیایی (اختیاری)</value>
</data>
<data name="TbSettingsSrsFilesSource" xml:space="preserve">
<value>sing-box ruleset files source (optional)</value>
<value>منبع فایل های مجموعه قوانین sing-box (اختیاری)</value>
</data>
<data name="UpgradeAppNotExistTip" xml:space="preserve">
<value>UpgradeApp does not exist</value>
<value>برنامه ارتقا وجود ندارد</value>
</data>
<data name="TbSettingsRoutingRulesSource" xml:space="preserve">
<value>Routing rules source (optional)</value>
<value>منبع قوانین مسیریابی (اختیاری)</value>
</data>
<data name="menuRegionalPresets" xml:space="preserve">
<value>Regional presets setting</value>
<value>تنظیمات از پیش تعیین شده منطقه ای</value>
</data>
<data name="menuRegionalPresetsDefault" xml:space="preserve">
<value>Default</value>
<value>پیش فرض</value>
</data>
<data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>Russia</value>
<value>روسیه</value>
</data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>ایران</value>
</data>
<data name="TbSettingsChinaUserTip" xml:space="preserve">
<value>Users in China region can ignore this item</value>
<value>کاربران در منطقه چین می توانند این مورد را نادیده بگیرند</value>
</data>
<data name="menuAddServerViaImage" xml:space="preserve">
<value>Scan QR code in the image</value>
<value>اسکن کردن QRcode موجود در تصویر</value>
</data>
<data name="InvalidUrlTip" xml:space="preserve">
<value>Invalid address (Url)</value>
<value>آدرس نامعتبر (آدرس اینترنتی)</value>
</data>
<data name="InsecureUrlProtocol" xml:space="preserve">
<value>Please do not use the insecure HTTP protocol subscription address</value>
<value>لطفاً از آدرس اشتراک پروتکل HTTP ناامن استفاده نکنید</value>
</data>
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
<value>Install the font to the system and restart the settings</value>
<value>فونت را روی سیستم نصب کنید و تنظیمات را مجددا راه اندازی کنید</value>
</data>
<data name="menuExitTips" xml:space="preserve">
<value>Are you sure to exit?</value>
<value>آیا مطمئن هستید که خارج می شوید؟</value>
</data>
<data name="LvMemo" xml:space="preserve">
<value>Remarks Memo</value>
<value>یادداشت ملاحظات</value>
</data>
<data name="TbSettingsLogEnabledToFile" xml:space="preserve">
<value>Enable logging to file</value>
<value>فعال کردن ورود به فایل</value>
</data>
<data name="MsgSkipSubscriptionUpdate" xml:space="preserve">
<value>Updates are not enabled, skip this subscription</value>
<value>به روز رسانی ها فعال نیستند، از این اشتراک رد شوید</value>
</data>
<data name="menuRebootAsAdmin" xml:space="preserve">
<value>Restart as Administrator</value>
<value>به عنوان مدیر راه اندازی مجدد</value>
</data>
<data name="LvMoreUrl" xml:space="preserve">
<value>More URLs, separated by commas; Subscription conversion will be invalid</value>
<value>نشانی‌های وب بیشتر که با کاما از هم جدا شده‌اند. تبدیل اشتراک نامعتبر خواهد بود</value>
</data>
<data name="SpeedDisplayText" xml:space="preserve">
<value>{0} : {1}/s↑ | {2}/s↓</value>
</data>
<data name="LvAutoUpdateInterval" xml:space="preserve">
<value>Automatic update interval (minutes)</value>
<value>فاصله به روز رسانی خودکار (دقیقه)</value>
</data>
<data name="LvConvertTarget" xml:space="preserve">
<value>Convert target type</value>
<value>تبدیل نوع هدف</value>
</data>
<data name="LvConvertTargetTip" xml:space="preserve">
<value>Please leave blank if no conversion is required</value>
<value>اگر نیازی به تبدیل نیست، لطفاً خالی بگذارید</value>
</data>
<data name="TipDisplayLog" xml:space="preserve">
<value>Please turn off when there is an abnormal disconnection</value>
<value>لطفاً در صورت قطع غیرعادی آن را خاموش کنید</value>
</data>
<data name="menuDNSSetting" xml:space="preserve">
<value>DNS Settings</value>
<value>تنظیمات DNS</value>
</data>
<data name="TbDnsSingboxObjectDoc" xml:space="preserve">
<value>Please fill in DNS Structure, Click to view the document</value>
<value>لطفا ساختار DNS را پر کنید، برای مشاهده سند کلیک کنید</value>
</data>
<data name="TbSettingDnsImportDefConfig" xml:space="preserve">
<value>Click to import default DNS config</value>
<value>برای وارد کردن تنظیمات پیش‌فرض DNS کلیک کنید</value>
</data>
<data name="TbdomainStrategy4Singbox" xml:space="preserve">
<value>sing-box domain strategy</value>
<value>استراتژی دامنه sing-box</value>
</data>
<data name="TbSettingsMux4SboxProtocol" xml:space="preserve">
<value>sing-box Mux Protocol</value>
<value>پروتکل sing-box Mux</value>
</data>
<data name="TbRoutingRuleProcess" xml:space="preserve">
<value>Full process name (Tun mode)</value>
<value>نام کامل فرانید (حالت Tun)</value>
</data>
<data name="TbRoutingRuleIP" xml:space="preserve">
<value>IP or IP CIDR</value>
</data>
<data name="TbRoutingRuleDomain" xml:space="preserve">
<value>Domain</value>
<value>دامنه</value>
</data>
<data name="TbSettingsCoreDnsSingbox" xml:space="preserve">
<value>sing-box DNS settings</value>
<value>تنظیمات DNS sing-box</value>
</data>
<data name="SpeedtestingWait" xml:space="preserve">
<value>Waiting for testing (press ESC to terminate)...</value>
<value>در انتظار آزمایش (برای پایان دادن به ESC فشار دهید)...</value>
</data>
<data name="TbSpiderX" xml:space="preserve">
<value>SpiderX</value>
@@ -1214,52 +1205,52 @@
<value>ShortId</value>
</data>
<data name="menuMoveToGroup" xml:space="preserve">
<value>Move to group</value>
<value>انتقال به گروه</value>
</data>
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
<value>Enable Server Drag Drop Sort(Require restart)</value>
<value>فعال کردن مرتب‌سازی سرورها با کشیدن و رها کردن (نیاز به راه‌اندازی مجدد)</value>
</data>
<data name="TbAutoRefresh" xml:space="preserve">
<value>AutoRefresh</value>
<value>بازخوانی خودکار</value>
</data>
<data name="SpeedtestingSkip" xml:space="preserve">
<value>Skip test</value>
<value>رد شدن از آزمون</value>
</data>
<data name="menuEditServer" xml:space="preserve">
<value>Edit Server (Ctrl+D)</value>
<value>ویرایش سرور (Ctrl+D)</value>
</data>
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
<value>Double-click server make active</value>
<value>دوبار کلیک کردن سرور باعث فعال شدن آن می شود</value>
</data>
<data name="SpeedtestingCompleted" xml:space="preserve">
<value>Test completed</value>
<value>تست تکمیل شد</value>
</data>
<data name="TbSettingsDefFingerprint" xml:space="preserve">
<value>Default TLS fingerprint</value>
<value>اثر انگشت tls پیش فرض</value>
</data>
<data name="TbSettingsCurrentFontFamily" xml:space="preserve">
<value>FontFamily(Require restart)</value>
<value>FontFamily (نیاز به راه اندازی مجدد)</value>
</data>
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
<value>Copy the font TTF/TTC file to the directory guiFonts, restart the settings</value>
<value>فایل TTF/TTC فونت را در دایرکتوری guiFonts کپی کنید. پنجره تنظیمات را دوباره باز کنید</value>
</data>
<data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>http port = +1; Pac port = +4; *ray API port = +5; mihomo API port = +6;</value>
<value>پورت Pac = +3; پورت Xray API = +4; پورت mihomo API = +5;</value>
</data>
<data name="TbSettingsStartBootTip" xml:space="preserve">
<value>Set this with admin privileges, get admin privileges after startup</value>
<value>این را با امتیازات ادمین تنظیم کنید، پس از راه اندازی، امتیازات مدیر را دریافت کنید</value>
</data>
<data name="TbSettingsFontSize" xml:space="preserve">
<value>Font Size</value>
<value>اندازه فونت</value>
</data>
<data name="TbSettingsSpeedTestTimeout" xml:space="preserve">
<value>SpeedTest Single Timeout Value</value>
<value>یمقدار تاخیر تست سرعت منفرد</value>
</data>
<data name="TbSettingsSpeedTestUrl" xml:space="preserve">
<value>SpeedTest URL</value>
<value>/آدرس اینترنتی SpeedTest</value>
</data>
<data name="menuMoveTo" xml:space="preserve">
<value>Move up and down</value>
<value>بالا و پایین حرکت کنید</value>
</data>
<data name="TbPublicKey" xml:space="preserve">
<value>PublicKey</value>
@@ -1268,46 +1259,43 @@
<value>Add [Hysteria2] server</value>
</data>
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
<value>Hysteria Max bandwidth (Up/Dw)</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>Follow System Theme</value>
<value>حداکتر پهنای باند هیستریا (آپلود/دانلود)</value>
</data>
<data name="menuAddTuicServer" xml:space="preserve">
<value>Add [TUIC] server</value>
<value>افزودن سرور [TUIC]</value>
</data>
<data name="TbSettingsEnableUpdateSubOnlyRemarksExist" xml:space="preserve">
<value>Updating subscription, only determine remarks exists</value>
<value>اشتراک در حال به‌روزرسانی، فقط مشخص کنید که ملاحظاتی وجود دارد</value>
</data>
<data name="menuProxiesReload" xml:space="preserve">
<value>Refresh Proxies</value>
<value>تازه سازی پروکسی ها</value>
</data>
<data name="TbSortingNetwork" xml:space="preserve">
<value>Network</value>
<value>شبکه</value>
</data>
<data name="TbSortingType" xml:space="preserve">
<value>Type</value>
<value>نوع</value>
</data>
<data name="TransportRequestHostTip5" xml:space="preserve">
<value>*grpc Authority</value>
</data>
<data name="menuAddHttpServer" xml:space="preserve">
<value>Add [HTTP] server</value>
<value>افزودن سرور [HTTP]</value>
</data>
<data name="TbSettingsSpeedPingTestUrl" xml:space="preserve">
<value>Speed Ping Test URL</value>
<value>آدرس اینترنتی تست پینگ سرعت</value>
</data>
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
<value>Use Xray and enable non-Tun mode, which conflicts with the group previous proxy</value>
<value>از Xray استفاده کنید و حالت non-Tun را فعال کنید، که با پراکسی قبلی گروه در تضاد است</value>
</data>
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
<value>Custom the rule-set of sing-box</value>
<value>سفارش سازی مجموعه قوانین از sing box</value>
</data>
<data name="NeedRebootTips" xml:space="preserve">
<value>Successful operation. Click the settings menu to reboot the app.</value>
<value>عملکرد موفقیت آمیز بود، روی منوی تنظیمات کلیک کنید تا برنامه راه اندازی مجدد شود.</value>
</data>
<data name="menuOpenTheFileLocation" xml:space="preserve">
<value>Open the storage location</value>
<value>باز کردن محل ذخیره سازی</value>
</data>
<data name="TbSortingChain" xml:space="preserve">
<value>Chain</value>
@@ -1316,72 +1304,96 @@
<value>Host</value>
</data>
<data name="TbSettingsUseSystemHosts" xml:space="preserve">
<value>Use System Hosts</value>
<value>استفاده کردن از System Hosts</value>
</data>
<data name="TbSettingsEnableFragment" xml:space="preserve">
<value>Enable fragment</value>
<value>فعال کردن فرگمنت</value>
</data>
<data name="TbAutoScrollToEnd" xml:space="preserve">
<value>Auto ScrollToEnd</value>
<value>خودکار ScrollToEnd</value>
</data>
<data name="SpeedtestingStop" xml:space="preserve">
<value>Test terminating...</value>
<value>پایان تست...</value>
</data>
<data name="LvNextProfile" xml:space="preserve">
<value>Next proxy remarks</value>
</data>
<data name="TbPath7" xml:space="preserve">
<value>obfs password</value>
<value>پسورد obfs</value>
</data>
<data name="TbHeaderType8" xml:space="preserve">
<value>Congestion control</value>
<value>کنترل تراکم</value>
</data>
<data name="LvPrevProfile" xml:space="preserve">
<value>Previous proxy remarks</value>
</data>
<data name="TbLocalAddress" xml:space="preserve">
<value>Address(Ip,Ipv6)</value>
<value>آدرس (IP, IPv6)</value>
</data>
<data name="TbReserved" xml:space="preserve">
<value>Reserved(2,3,4)</value>
</data>
<data name="TbPrivateKey" xml:space="preserve">
<value>PrivateKey</value>
<value>کلید خصوصی</value>
</data>
<data name="menuAddWireguardServer" xml:space="preserve">
<value>Add [WireGuard] server</value>
<value>افزودن سرور [WireGuard]</value>
</data>
<data name="TbSettingsEnableIPv6Address" xml:space="preserve">
<value>Enable IPv6 Address</value>
<value>فعال سازی آدرس IPv6</value>
</data>
<data name="TbSettingsEnableExInbound" xml:space="preserve">
<value>Enable additional Inbound</value>
<value>فعال سازی additional Inbound</value>
</data>
<data name="LvPrevProfileTip" xml:space="preserve">
<value>Please make sure the remarks exists and is unique</value>
<value>لطفاً مطمئن شوید که ملاحظات وجود دارد و منحصر به فرد است</value>
</data>
<data name="TbRuleMatchingTips" xml:space="preserve">
<value>(Domain or IP or ProcName) and Port and Protocol and InboundTag =&gt; OutboundTag</value>
</data>
<data name="TbSettingsLinuxSudoPassword" xml:space="preserve">
<value>System sudo password</value>
<value>رمز عبور sudo سیستم</value>
</data>
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
<value>The password is encrypted and stored only in local files.</value>
<value>رمز عبور رمزگذاری شده و فقط در فایل های محلی ذخیره می شود.</value>
</data>
<data name="TbSettingsLinuxSudoPasswordIsEmpty" xml:space="preserve">
<value>Please set the sudo password in Tun mode settings first</value>
<value>لطفاً ابتدا رمز عبور sudo را در تنظیمات حالت Tun تنظیم کنید</value>
</data>
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
<value>Please do not run this app with sudo</value>
<value>لطفا این برنامه را با sudo اجرا نکنید</value>
</data>
<data name="TransportHeaderTypeTip5" xml:space="preserve">
<value>*xhttp mode</value>
<value>*حالت xhttp</value>
</data>
<data name="TransportExtraTip" xml:space="preserve">
<value>XHTTP Extra raw JSON, format: { XHTTPObject }</value>
<value>جیسون خام XHTTP Extra, فرمت: { XHTTPObject }</value>
</data>
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
<value>Hide to tray when closing the window</value>
<value>هنگام بستن پنجره در سینی پنهان شوید</value>
</data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>تعداد در هر زمان برای دسته خودکار در طول تست سرعت (حداکثر 1000)</value>
</data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>موارد استثنا: از سرور پروکسی برای آدرس های زیر استفاده نکنید. برای جدا کردن ورودی ها از کاما (،) استفاده کنید.</value>
</data>
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>نوع Sniffing</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>فعال کردن دومین پورت ترکیبی</value>
</data>
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks:پورت محلی، socks2: پورت دوم محلی، socks3: پورت LAN</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>تم</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>کپی کردن دستور پروکسی در کلیپ بورد</value>
</data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
</data>
</root>

File diff suppressed because it is too large Load Diff

View File

@@ -320,7 +320,7 @@
<value>Remarks</value>
</data>
<data name="LvUrl" xml:space="preserve">
<value>URL(Optional)</value>
<value>URL (optional)</value>
</data>
<data name="LvCount" xml:space="preserve">
<value>Count</value>
@@ -338,7 +338,7 @@
<value>Information</value>
</data>
<data name="LvCustomIcon" xml:space="preserve">
<value>Custom Icon</value>
<value>Custom icon</value>
</data>
<data name="FillCorrectDNSText" xml:space="preserve">
<value>Please fill in the correct custom DNS</value>
@@ -481,12 +481,6 @@
<data name="TbSettingsColor" xml:space="preserve">
<value>Color</value>
</data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>Dark Mode</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>Follow System Theme</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>Language (Restart)</value>
</data>
@@ -689,7 +683,7 @@
<value>Auto hide startup</value>
</data>
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
<value>Automatic update interval of Geo (hours)</value>
<value>Automatic update interval for Geo files (hours)</value>
</data>
<data name="TbSettingsCore" xml:space="preserve">
<value>Core: basic settings</value>
@@ -710,7 +704,7 @@
<value>Outbound Freedom domainStrategy</value>
</data>
<data name="TbSettingsEnableAutoAdjustMainLvColWidth" xml:space="preserve">
<value>Automatically adjust column width after updating subscription</value>
<value>Automatically adjust column width after subscription update</value>
</data>
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
<value>Check for pre-release updates</value>
@@ -719,16 +713,16 @@
<value>Exception</value>
</data>
<data name="TbSettingsExceptionTip" xml:space="preserve">
<value>Exception. Do not use proxy server for addresses beginning with,Use semicolon (;)</value>
<value>Exclusions: Do not use proxy server for addresses beginning with the following. Use semicolon (;) to separate entries.</value>
</data>
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>HTTP Port</value>
</data>
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
<value>Ignore Geo files when updating core</value>
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
<value>Display real-time speed (requires restart)</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>Keep older when deduplication</value>
<value>Keep the older when de-duplicating</value>
</data>
<data name="TbSettingsLogEnabled" xml:space="preserve">
<value>Enable Log</value>
@@ -755,13 +749,13 @@
<value>Turn on Sniffing</value>
</data>
<data name="TbSettingsSocksPort" xml:space="preserve">
<value>SOCKS Port</value>
<value>Mixed Port</value>
</data>
<data name="TbSettingsStartBoot" xml:space="preserve">
<value>Start on boot</value>
</data>
<data name="TbSettingsStatistics" xml:space="preserve">
<value>Enable Statistics (Require restart)</value>
<value>Enable traffic statistics (requires restart)</value>
</data>
<data name="TbSettingsSubConvert" xml:space="preserve">
<value>Subscription conversion URL</value>
@@ -791,7 +785,7 @@
<value>Global Hotkey Settings</value>
</data>
<data name="TbGlobalHotkeySettingTip" xml:space="preserve">
<value>Set directly by pressing the keyboard, take effect after restart</value>
<value>Set directly by pressing the keyboard; Takes effect after restart</value>
</data>
<data name="TbNotChangeSystemProxy" xml:space="preserve">
<value>Do not change system proxy</value>
@@ -842,13 +836,13 @@
<value>Add</value>
</data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>Import Advanced Rules</value>
<value>Import Rules</value>
</data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>Remove selected (Delete)</value>
</data>
<data name="menuRoutingAdvancedSetDefault" xml:space="preserve">
<value>Set as active rule(Enter)</value>
<value>Set as active rule (Enter)</value>
</data>
<data name="TbdomainMatcher" xml:space="preserve">
<value>Domain Matcher</value>
@@ -856,9 +850,6 @@
<data name="TbdomainStrategy" xml:space="preserve">
<value>Domain strategy</value>
</data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>Enable advanced function</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.Block Domain or IP</value>
</data>
@@ -872,7 +863,7 @@
<value>Pre-defined Rule Set List</value>
</data>
<data name="TbRoutingTips" xml:space="preserve">
<value>*Set the rules, separated by commas (,); The comma in the regular is replaced by &lt;COMMA&gt;</value>
<value>*Separate rules by commas (,); For a literal comma use &lt;COMMA&gt;; Prefix # to ignore a rule</value>
</data>
<data name="menuImportRulesFromClipboard" xml:space="preserve">
<value>Import Rules From Clipboard</value>
@@ -908,7 +899,7 @@
<value>Ruleobject Doc</value>
</data>
<data name="TbDnsObjectDoc" xml:space="preserve">
<value>Support DnsObject, Click to view the document</value>
<value>Supports DnsObject; Click to view documentation</value>
</data>
<data name="SubUrlTips" xml:space="preserve">
<value>For group please leave blank here</value>
@@ -926,7 +917,7 @@
<value>Do not use proxy servers for local (intranet) addresses</value>
</data>
<data name="menuMixedTestServer" xml:space="preserve">
<value>One-click multi test Latency and speed (Ctrl+E)</value>
<value>One-click multi-test latency and speed (Ctrl+E)</value>
</data>
<data name="LvTestDelay" xml:space="preserve">
<value>Delay(ms)</value>
@@ -943,9 +934,6 @@
<data name="TbDisplayLog" xml:space="preserve">
<value>Display Log</value>
</data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>Import old config (guiNConfig)</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>Enable Tun</value>
</data>
@@ -959,7 +947,7 @@
<value>Move to group</value>
</data>
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
<value>Enable Server Drag Drop Sort(Require restart)</value>
<value>Enable sorting servers by drag-n-drop (requires restart)</value>
</data>
<data name="TbAutoRefresh" xml:space="preserve">
<value>AutoRefresh</value>
@@ -971,7 +959,7 @@
<value>Edit Server (Ctrl+D)</value>
</data>
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
<value>Double-click server make active</value>
<value>Double-clicking server makes it active</value>
</data>
<data name="SpeedtestingCompleted" xml:space="preserve">
<value>Test completed</value>
@@ -986,13 +974,13 @@
<value>This parameter is valid only for tcp/http and ws</value>
</data>
<data name="TbSettingsCurrentFontFamily" xml:space="preserve">
<value>FontFamily(Require restart)</value>
<value>Font family (requires restart)</value>
</data>
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
<value>Copy the font TTF/TTC file to the directory guiFonts, restart the settings</value>
<value>Copy the font TTF/TTC file to the directory guiFonts; Reopen the settings window</value>
</data>
<data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>http port = +1; Pac port = +4; *ray API port = +5; mihomo API port = +6;</value>
<value>Pac port = +3; Xray API port = +4; mihomo API port = +5;</value>
</data>
<data name="TbSettingsStartBootTip" xml:space="preserve">
<value>Set this with admin privileges, get admin privileges after startup</value>
@@ -1019,7 +1007,7 @@
<value>SpiderX</value>
</data>
<data name="TbSettingsEnableHWA" xml:space="preserve">
<value>Enable hardware acceleration(Require restart)</value>
<value>Enable hardware acceleration (requires restart)</value>
</data>
<data name="SpeedtestingWait" xml:space="preserve">
<value>Waiting for testing (press ESC to terminate)...</value>
@@ -1247,7 +1235,7 @@
<value>Multi-Server lowest latency</value>
</data>
<data name="TbSettingsMainGirdOrientation" xml:space="preserve">
<value>Main layout orientation(Require restart)</value>
<value>Main layout orientation (requires restart)</value>
</data>
<data name="menuSetDefaultLoadBalanceServer" xml:space="preserve">
<value>Multi-server load balancing</value>
@@ -1318,9 +1306,6 @@
<data name="TipActiveServer" xml:space="preserve">
<value>Active</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>Save Interface Layout</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo files source (optional)</value>
</data>
@@ -1342,6 +1327,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>Russia</value>
</data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>Iran</value>
</data>
<data name="TbSettingsChinaUserTip" xml:space="preserve">
<value>Users in China region can ignore this item</value>
</data>
@@ -1384,4 +1372,28 @@
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
<value>Hide to tray when closing the window</value>
</data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>Number per time for auto batch during speedtest(max 1000)</value>
</data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>Exclusions: Do not use proxy server for the following addresses. Use comma (,) to separate entries.</value>
</data>
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>Sniffing type</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>Enable second mixed port</value>
</data>
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks: local port, socks2: second local port, socks3: LAN port</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>Theme</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value>
</data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
</data>
</root>

View File

@@ -481,12 +481,6 @@
<data name="TbSettingsColor" xml:space="preserve">
<value>Цвет</value>
</data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>Тёмный режим</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>Следить за системной темой</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>Язык (требуется перезапуск)</value>
</data>
@@ -730,8 +724,8 @@
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>HTTP порт</value>
</data>
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
<value>Игнорировать файлы Geo при обновлении ядра</value>
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
<value>Display real-time speed</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>Сохранить старые при удалении дублей</value>
@@ -761,7 +755,7 @@
<value>Включить сниффинг</value>
</data>
<data name="TbSettingsSocksPort" xml:space="preserve">
<value>Порт Socks</value>
<value>Mixed Port</value>
</data>
<data name="TbSettingsStartBoot" xml:space="preserve">
<value>Автозапуск</value>
@@ -862,9 +856,6 @@
<data name="TbdomainStrategy" xml:space="preserve">
<value>Доменная стратегия</value>
</data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>Включить расширенные функции</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.Заблокировать домен или IP</value>
</data>
@@ -949,9 +940,6 @@
<data name="TbDisplayLog" xml:space="preserve">
<value>Показать логи</value>
</data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>Импортировать старый конфиг guiNConfig</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>Режим VPN</value>
</data>
@@ -1039,6 +1027,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>Россия</value>
</data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>Иран</value>
</data>
<data name="TbSettingsChinaUserTip" xml:space="preserve">
<value>Используйте Настройки -&gt; Региональные пресеты вместо изменения этого поля</value>
</data>
@@ -1267,9 +1258,6 @@
<data name="LvConvertTarget" xml:space="preserve">
<value>Convert target type</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>Save Interface Layout</value>
</data>
<data name="SpeedDisplayText" xml:space="preserve">
<value>{0} : {1}/s↑ | {2}/s↓</value>
</data>
@@ -1310,7 +1298,7 @@
<value>Move up and down</value>
</data>
<data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>http port = +1; Pac port = +4; *ray API port = +5; mihomo API port = +6;</value>
<value>Pac port = +3; Xray API port = +4; mihomo API port = +5;</value>
</data>
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
<value>Install the font to the system and restart the settings</value>
@@ -1384,4 +1372,28 @@
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
<value>Hide to tray when closing the window</value>
</data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>Number per time for auto batch during speedtest(max 1000)</value>
</data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>Exception. Do not use proxy server for addresses,with a comma (,)</value>
</data>
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>Sniffing type</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>Enable second mixed port</value>
</data>
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks: local port, socks2: second local port, socks3: LAN port</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>Theme</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>Copy proxy command to clipboard</value>
</data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>
</data>
</root>

View File

@@ -127,7 +127,7 @@
<value>配置格式不正确</value>
</data>
<data name="CustomServerTips" xml:space="preserve">
<value>注意,自定义配置完全依赖您自己的配置,不能使用所有设置功能。如需使用系统代理请手动修改监听端口。</value>
<value>注意自定义配置完全依赖您自己的配置,不能使用所有设置功能。如需使用系统代理请手动修改监听端口。</value>
</data>
<data name="Downloading" xml:space="preserve">
<value>下载开始...</value>
@@ -136,7 +136,7 @@
<value>下载</value>
</data>
<data name="DownloadYesNo" xml:space="preserve">
<value>是否下载? {0}</value>
<value>是否下载{0}</value>
</data>
<data name="FailedConversionConfiguration" xml:space="preserve">
<value>转换配置文件失败</value>
@@ -154,7 +154,7 @@
<value>读取配置文件失败</value>
</data>
<data name="FillCorrectServerPort" xml:space="preserve">
<value>请填写正确格式服务器端口</value>
<value>请填写正确格式服务器端口</value>
</data>
<data name="FillLocalListeningPort" xml:space="preserve">
<value>请填写本地监听端口</value>
@@ -169,16 +169,16 @@
<value>请填写用户ID</value>
</data>
<data name="Incorrectconfiguration" xml:space="preserve">
<value>不是正确的配置,请检查</value>
<value>配置不正确,请检查</value>
</data>
<data name="InitialConfiguration" xml:space="preserve">
<value>初始化配置</value>
</data>
<data name="IsLatestCore" xml:space="preserve">
<value>{0} {1} 已是最新版本</value>
<value>{0} {1} 已是最新版本</value>
</data>
<data name="IsLatestN" xml:space="preserve">
<value>{0} {1} 已是最新版本</value>
<value>{0} {1} 已是最新版本</value>
</data>
<data name="LvAddress" xml:space="preserve">
<value>地址</value>
@@ -226,7 +226,7 @@
<value>未设置有效的订阅</value>
</data>
<data name="MsgParsingSuccessfully" xml:space="preserve">
<value>解析{0}成功</value>
<value>解析 {0} 成功</value>
</data>
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
<value>开始获取订阅内容</value>
@@ -259,10 +259,10 @@
<value>在文件夹 ({0}) 下未找到Core文件 (文件名:{1}),请下载后放入文件夹,下载地址: {2}</value>
</data>
<data name="NoValidQRcodeFound" xml:space="preserve">
<value>扫描完成,未发现有效二维码</value>
<value>扫描完成未发现有效二维码</value>
</data>
<data name="OperationFailed" xml:space="preserve">
<value>操作失败,请检查重试</value>
<value>操作失败,请检查重试</value>
</data>
<data name="PleaseFillRemarks" xml:space="preserve">
<value>请填写别名</value>
@@ -280,10 +280,10 @@
<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>
<value>客户端配置文件保存在{0}</value>
</data>
<data name="StartService" xml:space="preserve">
<value>启动服务({0})...</value>
@@ -311,10 +311,10 @@
<value>请先选择规则</value>
</data>
<data name="RemoveRules" xml:space="preserve">
<value>是否确定移除规则?</value>
<value>是否确定移除规则</value>
</data>
<data name="RoutingRuleDetailRequiredTips" xml:space="preserve">
<value>{0},必填其中一项.</value>
<value>{0}必填其中一项.</value>
</data>
<data name="LvRemarks" xml:space="preserve">
<value>别名</value>
@@ -329,10 +329,10 @@
<value>请填写Url</value>
</data>
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
<value>是否追加规则?选择则追加,选择否则替换</value>
<value>是否追加规则选择“是”则追加选择“否”则全部替换</value>
</data>
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
<value>下载 GeoFile: {0} 成功</value>
<value>下载 GeoFile{0} 成功</value>
</data>
<data name="MsgInformationTitle" xml:space="preserve">
<value>信息</value>
@@ -386,7 +386,7 @@
<value>*Kcp seed</value>
</data>
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
<value>注册全局热键 {0} 失败,原因 {1}</value>
<value>注册全局热键 {0} 失败原因{1}</value>
</data>
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
<value>注册全局热键 {0} 成功</value>
@@ -481,14 +481,8 @@
<data name="TbSettingsColor" xml:space="preserve">
<value>颜色</value>
</data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>暗黑模式</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>是否跟随系统主题</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>语言(重启)</value>
<value>语言(重启)</value>
</data>
<data name="menuAddServerViaClipboard" xml:space="preserve">
<value>从剪贴板导入分享链接 (Ctrl+V)</value>
@@ -638,7 +632,7 @@
<value>传输层安全(TLS)</value>
</data>
<data name="TipNetwork" xml:space="preserve">
<value>*默认tcp,选错会无法连接</value>
<value>*默认tcp选错会无法连接</value>
</data>
<data name="TbCoreType" xml:space="preserve">
<value>Core类型</value>
@@ -671,7 +665,7 @@
<value>Socks端口</value>
</data>
<data name="TipPreSocksPort" xml:space="preserve">
<value>* 自定义配置的Socks端口值可不设置当设置此值后将使用Xray/sing-box(Tun)额外启动一个前置Socks服务提供分流和速度显示等功能</value>
<value>*自定义配置的Socks端口值可不设置当设置此值后将使用Xray/sing-box(Tun)额外启动一个前置Socks服务提供分流和速度显示等功能</value>
</data>
<data name="TbBrowse" xml:space="preserve">
<value>浏览</value>
@@ -680,7 +674,7 @@
<value>编辑</value>
</data>
<data name="TbSettingsAdvancedProtocol" xml:space="preserve">
<value>高级代理设置, 协议选择(可选)</value>
<value>高级代理设置协议选择(可选)</value>
</data>
<data name="TbSettingsAllowLAN" xml:space="preserve">
<value>允许来自局域网的连接</value>
@@ -689,19 +683,19 @@
<value>启动后隐藏窗口</value>
</data>
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
<value>自动更新Geo文件的间隔(单位小时)</value>
<value>自动更新Geo文件的间隔(小时)</value>
</data>
<data name="TbSettingsCore" xml:space="preserve">
<value>Core: 基础设置</value>
</data>
<data name="TbSettingsCoreDns" xml:space="preserve">
<value>V2ray DNS设置</value>
<value>v2ray DNS设置</value>
</data>
<data name="TbSettingsCoreKcp" xml:space="preserve">
<value>Core: KCP设置</value>
</data>
<data name="TbSettingsCoreType" xml:space="preserve">
<value>Core类型设置</value>
<value>Core 类型设置</value>
</data>
<data name="TbSettingsDefAllowInsecure" xml:space="preserve">
<value>默认跳过证书验证(allowInsecure)</value>
@@ -719,13 +713,13 @@
<value>例外</value>
</data>
<data name="TbSettingsExceptionTip" xml:space="preserve">
<value>例外. 对于下列字符开头的地址不使用代理配置文件:使用分号(;)分隔</value>
<value>例外对于下列字符开头的地址不使用代理配置文件使用分号(;)分隔</value>
</data>
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>本地http监听端口</value>
</data>
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
<value>更新Core时忽略Geo文件</value>
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
<value>显示实时速度(需重启)</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>去重时保留序号较小的项</value>
@@ -746,7 +740,7 @@
<value>认证密码</value>
</data>
<data name="TbSettingsRemoteDNS" xml:space="preserve">
<value>自定义DNS(可多个,用逗号(,)分隔)</value>
<value>自定义DNS(可多个用逗号(,)分隔)</value>
</data>
<data name="TbSettingsSetUWP" xml:space="preserve">
<value>解除Win10 UWP应用回环代理限制</value>
@@ -755,13 +749,13 @@
<value>开启流量探测</value>
</data>
<data name="TbSettingsSocksPort" xml:space="preserve">
<value>本地socks监听端口</value>
<value>本地混合监听端口</value>
</data>
<data name="TbSettingsStartBoot" xml:space="preserve">
<value>开机启动(可能会不成功)</value>
</data>
<data name="TbSettingsStatistics" xml:space="preserve">
<value>启用统计(实时网速显示,需重启)</value>
<value>启用流量统计(需重启</value>
</data>
<data name="TbSettingsSubConvert" xml:space="preserve">
<value>订阅转换网址(可选)</value>
@@ -791,7 +785,7 @@
<value>全局热键设置</value>
</data>
<data name="TbGlobalHotkeySettingTip" xml:space="preserve">
<value>直接按键盘进行设置, 重启后生效</value>
<value>直接按键盘进行设置重启后生效</value>
</data>
<data name="TbNotChangeSystemProxy" xml:space="preserve">
<value>不改变系统代理</value>
@@ -830,7 +824,7 @@
<value>上移 (U)</value>
</data>
<data name="MsgFilterTitle" xml:space="preserve">
<value>过滤器, 支持正则</value>
<value>过滤器(支持正则)</value>
</data>
<data name="menuWebsiteItem" xml:space="preserve">
<value>{0} 官网</value>
@@ -842,7 +836,7 @@
<value>添加规则集</value>
</data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>一键导入高级规则</value>
<value>一键导入规则</value>
</data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>移除所选规则 (Delete)</value>
@@ -856,9 +850,6 @@
<data name="TbdomainStrategy" xml:space="preserve">
<value>域名解析策略</value>
</data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>启用高级功能</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.阻止的Domain或IP</value>
</data>
@@ -872,7 +863,7 @@
<value>预定义规则集列表</value>
</data>
<data name="TbRoutingTips" xml:space="preserve">
<value>*设置的路由规则,用逗号(,)分隔;正则中的逗号用&lt;COMMA&gt;替代</value>
<value>*设置的路由规则用逗号(,)分隔正则中的逗号用&lt;COMMA&gt;替代</value>
</data>
<data name="menuImportRulesFromClipboard" xml:space="preserve">
<value>从剪贴板中导入规则</value>
@@ -902,13 +893,13 @@
<value>路由规则详情设置</value>
</data>
<data name="TbAutoSort" xml:space="preserve">
<value>保存时Domain, IP, 进程名 自动排序</value>
<value>保存时 Domain, IP, 进程名 自动排序</value>
</data>
<data name="TbRuleobjectDoc" xml:space="preserve">
<value>规则详细说明文档</value>
</data>
<data name="TbDnsObjectDoc" xml:space="preserve">
<value>支持填写DnsObject,JSON格式点击查看文档</value>
<value>支持填写DnsObjectJSON格式点击查看文档</value>
</data>
<data name="SubUrlTips" xml:space="preserve">
<value>普通分组此处请留空</value>
@@ -920,7 +911,7 @@
<value>系统代理设置改变</value>
</data>
<data name="TbSettingsRouteOnly" xml:space="preserve">
<value>RouteOnly</value>
<value>仅限路由(routeOnly)</value>
</data>
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
<value>请勿将代理服务器用于本地Intranet地址</value>
@@ -935,7 +926,7 @@
<value>速度(M/s)</value>
</data>
<data name="FailedToRunCore" xml:space="preserve">
<value>运行Core失败请看日志</value>
<value>运行Core失败看日志</value>
</data>
<data name="LvFilter" xml:space="preserve">
<value>别名正则过滤</value>
@@ -943,9 +934,6 @@
<data name="TbDisplayLog" xml:space="preserve">
<value>显示日志</value>
</data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>导入旧的配置文件guiNConfig</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>启用Tun</value>
</data>
@@ -953,7 +941,7 @@
<value>为局域网开启新的端口</value>
</data>
<data name="TbSettingsTunMode" xml:space="preserve">
<value>Tun模式设置</value>
<value>Tun 模式设置</value>
</data>
<data name="menuMoveToGroup" xml:space="preserve">
<value>移至订阅分组</value>
@@ -992,7 +980,7 @@
<value>拷贝字体TTF/TTC文件到目录guiFonts重启设置</value>
</data>
<data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>http端口= +1Pac端口= +4*ray API端口= +5mihomo API端口= +6</value>
<value>Pac端口= +3Xray API端口= +4mihomo API端口= +5</value>
</data>
<data name="TbSettingsStartBootTip" xml:space="preserve">
<value>以管理员权限设置此项,在启动后获得管理员权限</value>
@@ -1315,9 +1303,6 @@
<data name="TipActiveServer" xml:space="preserve">
<value>活动</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>保存界面布局</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo文件来源(可选)</value>
</data>
@@ -1342,6 +1327,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>俄罗斯</value>
</data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>伊朗</value>
</data>
<data name="menuAddServerViaImage" xml:space="preserve">
<value>扫描图片中的二维码</value>
</data>
@@ -1370,7 +1358,7 @@
<value>请先在Tun模式设置中设置sudo密码</value>
</data>
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
<value>请不要用sudo运行本app</value>
<value>请不要用sudo运行本程序</value>
</data>
<data name="TransportHeaderTypeTip5" xml:space="preserve">
<value>*xhttp 模式</value>
@@ -1381,4 +1369,28 @@
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
<value>关闭窗口时隐藏至托盘</value>
</data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>测试时自动分批的每批数量最大1000</value>
</data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>例外:对于下列地址不使用代理配置文件。使用逗号(,)分隔。</value>
</data>
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>流量探测类型</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>开启第二个本地监听端口</value>
</data>
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks本地端口socks2第二个本地端口socks3局域网端口</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>主题</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>复制终端代理命令至剪贴板</value>
</data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>开始对失败部分进行重新测试,剩余 {0} 个。可按 ESC 终止...</value>
</data>
</root>

View File

@@ -136,7 +136,7 @@
<value>下載</value>
</data>
<data name="DownloadYesNo" xml:space="preserve">
<value>是否下載? {0}</value>
<value>是否下載{0}</value>
</data>
<data name="FailedConversionConfiguration" xml:space="preserve">
<value>轉換設定檔失敗</value>
@@ -154,7 +154,7 @@
<value>讀取設定檔失敗</value>
</data>
<data name="FillCorrectServerPort" xml:space="preserve">
<value>請填寫正確格式伺服器埠</value>
<value>請填寫正確格式伺服器埠</value>
</data>
<data name="FillLocalListeningPort" xml:space="preserve">
<value>請填寫本機偵聽埠</value>
@@ -169,16 +169,16 @@
<value>請填寫使用者ID</value>
</data>
<data name="Incorrectconfiguration" xml:space="preserve">
<value>不是正確的設定,請檢查</value>
<value>設定不正確,請檢查</value>
</data>
<data name="InitialConfiguration" xml:space="preserve">
<value>初始化設定</value>
</data>
<data name="IsLatestCore" xml:space="preserve">
<value>{0} {1} 已是最新版本</value>
<value>{0} {1} 已是最新版本</value>
</data>
<data name="IsLatestN" xml:space="preserve">
<value>{0} {1} 已是最新版本</value>
<value>{0} {1} 已是最新版本</value>
</data>
<data name="LvAddress" xml:space="preserve">
<value>位址</value>
@@ -226,7 +226,7 @@
<value>未設定有效的訂閱</value>
</data>
<data name="MsgParsingSuccessfully" xml:space="preserve">
<value>解析{0}成功</value>
<value>解析 {0} 成功</value>
</data>
<data name="MsgStartGettingSubscriptions" xml:space="preserve">
<value>開始獲取訂閱內容</value>
@@ -259,10 +259,10 @@
<value>在資料夾 ({0}) 下未找到Core檔案 (檔案名:{1}),請下載後放入資料夾,下載網址: {2}</value>
</data>
<data name="NoValidQRcodeFound" xml:space="preserve">
<value>掃描完成,未發現有效二維碼</value>
<value>掃描完成未發現有效二維碼</value>
</data>
<data name="OperationFailed" xml:space="preserve">
<value>操作失敗,請檢查重試</value>
<value>操作失敗,請檢查重試</value>
</data>
<data name="PleaseFillRemarks" xml:space="preserve">
<value>請填寫別名</value>
@@ -280,16 +280,17 @@
<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>
<value>用戶端設定檔儲存在{0}</value>
</data>
<data name="StartService" xml:space="preserve">
<value>啟動服務({0})...</value>
</data>
<data name="SuccessfulConfiguration" xml:space="preserve">
<value>設定成功{0}</value>
<value>設定成功
{0}</value>
</data>
<data name="SuccessfullyImportedCustomServer" xml:space="preserve">
<value>成功匯入自訂設定伺服器</value>
@@ -310,10 +311,10 @@
<value>請先選擇規則</value>
</data>
<data name="RemoveRules" xml:space="preserve">
<value>是否確定移除規則?</value>
<value>是否確定移除規則</value>
</data>
<data name="RoutingRuleDetailRequiredTips" xml:space="preserve">
<value>{0},必填其中一項.</value>
<value>{0}必填其中一項.</value>
</data>
<data name="LvRemarks" xml:space="preserve">
<value>別名</value>
@@ -328,10 +329,10 @@
<value>請填寫URL</value>
</data>
<data name="AddBatchRoutingRulesYesNo" xml:space="preserve">
<value>是否追加規則?選擇則追加,選擇否則取代</value>
<value>是否追加規則選擇“是”則追加選擇“否”則完全取代</value>
</data>
<data name="MsgDownloadGeoFileSuccessfully" xml:space="preserve">
<value>下載 GeoFile: {0} 成功</value>
<value>下載 GeoFile{0} 成功</value>
</data>
<data name="MsgInformationTitle" xml:space="preserve">
<value>資訊</value>
@@ -385,7 +386,7 @@
<value>*KCP seed</value>
</data>
<data name="RegisterGlobalHotkeyFailed" xml:space="preserve">
<value>註冊全域快速鍵 {0} 失敗,原因 {1}</value>
<value>註冊全域快速鍵 {0} 失敗原因{1}</value>
</data>
<data name="RegisterGlobalHotkeySuccessfully" xml:space="preserve">
<value>註冊全域快速鍵 {0} 成功</value>
@@ -480,14 +481,8 @@
<data name="TbSettingsColor" xml:space="preserve">
<value>顏色</value>
</data>
<data name="TbSettingsColorMode" xml:space="preserve">
<value>暗黑模式</value>
</data>
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
<value>是否跟隨系統主題</value>
</data>
<data name="TbSettingsLanguage" xml:space="preserve">
<value>語言(重啟)</value>
<value>語言(重啟)</value>
</data>
<data name="menuAddServerViaClipboard" xml:space="preserve">
<value>從剪貼簿導入分享鏈接 (Ctrl+V)</value>
@@ -637,7 +632,7 @@
<value>傳輸層安全(TLS)</value>
</data>
<data name="TipNetwork" xml:space="preserve">
<value>*預設TCP,選錯會無法連接</value>
<value>*預設TCP選錯會無法連接</value>
</data>
<data name="TbCoreType" xml:space="preserve">
<value>Core類型</value>
@@ -670,7 +665,7 @@
<value>SOCKS埠</value>
</data>
<data name="TipPreSocksPort" xml:space="preserve">
<value>* 自訂設定的Socks埠值可不設定當設定此值後將使用Xray/sing-box(Tun)額外啟動一個前置Socks服務提供分流和速度顯示等功能</value>
<value>*自訂設定的Socks埠值可不設定當設定此值後將使用Xray/sing-box(Tun)額外啟動一個前置Socks服務提供分流和速度顯示等功能</value>
</data>
<!--********************************************-->
<data name="TbBrowse" xml:space="preserve">
@@ -680,7 +675,7 @@
<value>編輯</value>
</data>
<data name="TbSettingsAdvancedProtocol" xml:space="preserve">
<value>進階代理設定, 協定選擇(可選)</value>
<value>進階代理設定協定選擇(可選)</value>
</data>
<data name="TbSettingsAllowLAN" xml:space="preserve">
<value>允許來自區域網路的連線</value>
@@ -689,7 +684,7 @@
<value>啟動後隱藏視窗</value>
</data>
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
<value>自動更新Geo檔案的間隔(單位小時)</value>
<value>自動更新Geo檔案的間隔(小時)</value>
</data>
<data name="TbSettingsCore" xml:space="preserve">
<value>Core: 基礎設定</value>
@@ -701,7 +696,7 @@
<value>Core: KCP設定</value>
</data>
<data name="TbSettingsCoreType" xml:space="preserve">
<value>Core類型設定</value>
<value>Core 類型設定</value>
</data>
<data name="TbSettingsDefAllowInsecure" xml:space="preserve">
<value>預設跳過憑證驗證(allowinsecure)</value>
@@ -719,13 +714,13 @@
<value>例外</value>
</data>
<data name="TbSettingsExceptionTip" xml:space="preserve">
<value>例外. 對於下列字元開頭的位址不使用代理設定檔:使用分號(;)分隔</value>
<value>例外對於下列字元開頭的位址不使用代理設定檔使用分號(;)分隔</value>
</data>
<data name="TbSettingsHttpPort" xml:space="preserve">
<value>本機HTTP偵聽埠</value>
</data>
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
<value>更新Core時忽略Geo檔案</value>
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
<value>顯示即時速度(需重啟)</value>
</data>
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
<value>去重時保留序號較小的項</value>
@@ -746,7 +741,7 @@
<value>認證密碼</value>
</data>
<data name="TbSettingsRemoteDNS" xml:space="preserve">
<value>自訂DNS(可多個,用逗號(,)分隔)</value>
<value>自訂DNS(可多個用逗號(,)分隔)</value>
</data>
<data name="TbSettingsSetUWP" xml:space="preserve">
<value>解除Win10 UWP應用回環代理限制</value>
@@ -755,13 +750,13 @@
<value>開啟流量探測</value>
</data>
<data name="TbSettingsSocksPort" xml:space="preserve">
<value>本機SOCKS偵聽埠</value>
<value>本機混合偵聽埠</value>
</data>
<data name="TbSettingsStartBoot" xml:space="preserve">
<value>開機啟動(可能會不成功)</value>
</data>
<data name="TbSettingsStatistics" xml:space="preserve">
<value>啟用統計(即時網速顯示,需重啟)</value>
<value>啟用流量統計(需重啟</value>
</data>
<data name="TbSettingsSubConvert" xml:space="preserve">
<value>訂閱轉換網址(可選)</value>
@@ -791,7 +786,7 @@
<value>全域快速鍵設定</value>
</data>
<data name="TbGlobalHotkeySettingTip" xml:space="preserve">
<value>直接按鍵盤進行設定, 重啟後生效</value>
<value>直接按鍵盤進行設定重啟後生效</value>
</data>
<data name="TbNotChangeSystemProxy" xml:space="preserve">
<value>不改變系統代理</value>
@@ -830,7 +825,7 @@
<value>上移 (U)</value>
</data>
<data name="MsgFilterTitle" xml:space="preserve">
<value>過濾, 支援正則</value>
<value>過濾(允許正則)</value>
</data>
<data name="menuWebsiteItem" xml:space="preserve">
<value>{0} 官網</value>
@@ -842,7 +837,7 @@
<value>新增規則集</value>
</data>
<data name="menuRoutingAdvancedImportRules" xml:space="preserve">
<value>一鍵匯入進階規則</value>
<value>一鍵匯入規則</value>
</data>
<data name="menuRoutingAdvancedRemove" xml:space="preserve">
<value>移除所選規則 (Delete)</value>
@@ -856,9 +851,6 @@
<data name="TbdomainStrategy" xml:space="preserve">
<value>域名解析策略</value>
</data>
<data name="TbenableRoutingAdvanced" xml:space="preserve">
<value>啟動進階功能</value>
</data>
<data name="TbRoutingTabBlock" xml:space="preserve">
<value>3.阻止的Domain或IP</value>
</data>
@@ -872,7 +864,7 @@
<value>預定義規則集列表</value>
</data>
<data name="TbRoutingTips" xml:space="preserve">
<value>*設定的路由規則,用逗號(,)分隔;正則中的逗號用&lt;COMMA&gt;替代</value>
<value>*設定的路由規則用逗號(,)分隔正則中的逗號用&lt;COMMA&gt;替代</value>
</data>
<data name="menuImportRulesFromClipboard" xml:space="preserve">
<value>從剪貼簿中匯入規則</value>
@@ -902,13 +894,13 @@
<value>路由規則詳情設定</value>
</data>
<data name="TbAutoSort" xml:space="preserve">
<value>儲存時Domain, IP, 行程名 自動排序</value>
<value>儲存時 Domain, IP, 行程名 自動排序</value>
</data>
<data name="TbRuleobjectDoc" xml:space="preserve">
<value>規則詳細說明檔案</value>
</data>
<data name="TbDnsObjectDoc" xml:space="preserve">
<value>支援填寫DnsObject,JSON格式點擊查看檔案</value>
<value>支援填寫DnsObjectJSON格式點擊查看説明</value>
</data>
<data name="SubUrlTips" xml:space="preserve">
<value>普通分組此處請留空</value>
@@ -920,7 +912,7 @@
<value>系統代理設定已改變</value>
</data>
<data name="TbSettingsRouteOnly" xml:space="preserve">
<value>RouteOnly</value>
<value>僅限路由(routeOnly)</value>
</data>
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
<value>請勿將代理伺服器用於本機Intranet位址</value>
@@ -935,7 +927,7 @@
<value>速度(M/s)</value>
</data>
<data name="FailedToRunCore" xml:space="preserve">
<value>執行Core失敗日誌</value>
<value>執行Core失敗查閲日誌</value>
</data>
<data name="LvFilter" xml:space="preserve">
<value>別名正則過濾</value>
@@ -943,17 +935,14 @@
<data name="TbDisplayLog" xml:space="preserve">
<value>顯示日誌</value>
</data>
<data name="menuImportOldGuiConfig" xml:space="preserve">
<value>匯入舊的設定檔guiNConfig</value>
</data>
<data name="TbEnableTunAs" xml:space="preserve">
<value>啟用TUN</value>
<value>啟用Tun</value>
</data>
<data name="TbSettingsNewPort4LAN" xml:space="preserve">
<value>為區域網路開啟新的埠</value>
</data>
<data name="TbSettingsTunMode" xml:space="preserve">
<value>TUN模式設定</value>
<value>Tun 模式設定</value>
</data>
<data name="menuMoveToGroup" xml:space="preserve">
<value>移至訂閱分組</value>
@@ -992,7 +981,7 @@
<value>複製字型TTF/TTC檔案到目錄guiFonts重啟設定</value>
</data>
<data name="TbSettingsSocksPortTip" xml:space="preserve">
<value>http連接埠= +1Pac連接埠= +4*ray API連接埠= +5mihomo API連接埠= +6</value>
<value>Pac連接埠= +3Xray API連接埠= +4mihomo API連接埠= +5</value>
</data>
<data name="TbSettingsStartBootTip" xml:space="preserve">
<value>以管理員權限設定此項,在啟動後獲得管理員權限</value>
@@ -1067,7 +1056,7 @@
<value>sing-box Mux 多路復用協定</value>
</data>
<data name="TbRoutingRuleProcess" xml:space="preserve">
<value>行程名全稱 (TUN模式)</value>
<value>行程名全稱 (Tun模式)</value>
</data>
<data name="TbRoutingRuleDomain" xml:space="preserve">
<value>Domain</value>
@@ -1195,9 +1184,6 @@
<data name="TipActiveServer" xml:space="preserve">
<value>活動</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>儲存介面佈局</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo檔案來源(可選)</value>
</data>
@@ -1222,6 +1208,9 @@
<data name="menuRegionalPresetsRussia" xml:space="preserve">
<value>俄羅斯</value>
</data>
<data name="menuRegionalPresetsIran" xml:space="preserve">
<value>伊朗</value>
</data>
<data name="menuAddServerViaImage" xml:space="preserve">
<value>掃描圖片中的二維碼</value>
</data>
@@ -1370,7 +1359,7 @@
<value>請先在Tun模式設定中設定sudo密碼</value>
</data>
<data name="TbSettingsLinuxSudoPasswordNotSudoRunApp" xml:space="preserve">
<value>請不要用sudo來運行本app</value>
<value>請不要用sudo來運行此App</value>
</data>
<data name="TransportHeaderTypeTip5" xml:space="preserve">
<value>*xhttp 模式</value>
@@ -1381,4 +1370,28 @@
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
<value>關閉視窗時隱藏至托盤</value>
</data>
<data name="TbSettingsSpeedTestPageSize" xml:space="preserve">
<value>測試時自動分批的每批數量最大1000</value>
</data>
<data name="TbSettingsExceptionTip2" xml:space="preserve">
<value>例外:對於下列位址不使用代理設定檔,使用逗號(,)分隔。</value>
</data>
<data name="TbSettingsDestOverride" xml:space="preserve">
<value>流量探測類型</value>
</data>
<data name="TbSettingsSecondLocalPortEnabled" xml:space="preserve">
<value>開啟第二個本機監聽埠</value>
</data>
<data name="TbRoutingInboundTagTips" xml:space="preserve">
<value>socks本地端口socks2第二個本地端口socks3區域網路端口</value>
</data>
<data name="TbSettingsTheme" xml:space="preserve">
<value>主題</value>
</data>
<data name="menuCopyProxyCmdToClipboard" xml:space="preserve">
<value>複製終端代理指令至剪貼簿</value>
</data>
<data name="SpeedtestingTestFailedPart" xml:space="preserve">
<value>開始對失敗部分進行重新測試,剩餘 {0} 個。可按 ESC 終止...</value>
</data>
</root>

View File

@@ -5,24 +5,25 @@
"loglevel": "warning"
},
"inbounds": [],
"outbounds": [{
"outbounds": [
{
"tag": "proxy",
"protocol": "vmess",
"settings": {
"vnext": [{
"address": "v2ray.cool",
"port": 10086,
"address": "",
"port": 0,
"users": [{
"id": "a3482e88-686a-4a58-8126-99c9df64b7bf",
"id": "",
"security": "auto"
}]
}],
"servers": [{
"address": "v2ray.cool",
"method": "chacha20",
"address": "",
"method": "",
"ota": false,
"password": "123456",
"port": 10086,
"password": "",
"port": 0,
"level": 1
}]
},
@@ -35,27 +36,23 @@
},
{
"protocol": "freedom",
"settings": {},
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block",
"settings": {
"response": {
"type": "http"
}
}
"tag": "block"
}
],
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"inboundTag": ["api"],
"outboundTag": "api",
"type": "field"
}
{
"inboundTag": [
"api"
],
"outboundTag": "api",
"type": "field"
}
]
}
}

View File

@@ -1,149 +1,156 @@
[
{
"remarks": "绕过bittorrent",
"outboundTag": "direct",
"protocol": [
"bittorrent"
]
},
{
"remarks": "Google cn",
"outboundTag": "proxy",
"domain": [
"domain:googleapis.cn",
"domain:gstatic.com"
]
},
{
"remarks": "阻断udp443",
"outboundTag": "block",
"port": "443",
"network": "udp"
},
{
"remarks": "阻断广告",
"outboundTag": "block",
"domain": [
"geosite:category-ads-all"
]
},
{
"remarks": "绕过局域网IP",
"outboundTag": "direct",
"ip": [
"geoip:private"
]
},
{
"remarks": "绕过局域网域名",
"outboundTag": "direct",
"domain": [
"geosite:private"
]
},
{
"remarks": "代理海外公共DNSIP",
"outboundTag": "proxy",
"ip": [
"1.1.1.1",
"1.0.0.1",
"2606:4700:4700::1111",
"2606:4700:4700::1001",
"1.1.1.2",
"1.0.0.2",
"2606:4700:4700::1112",
"2606:4700:4700::1002",
"1.1.1.3",
"1.0.0.3",
"2606:4700:4700::1113",
"2606:4700:4700::1003",
"8.8.8.8",
"8.8.4.4",
"2001:4860:4860::8888",
"2001:4860:4860::8844",
"94.140.14.14",
"94.140.15.15",
"2a10:50c0::ad1:ff",
"2a10:50c0::ad2:ff",
"94.140.14.15",
"94.140.15.16",
"2a10:50c0::bad1:ff",
"2a10:50c0::bad2:ff",
"94.140.14.140",
"94.140.14.141",
"2a10:50c0::1:ff",
"2a10:50c0::2:ff",
"208.67.222.222",
"208.67.220.220",
"2620:119:35::35",
"2620:119:53::53",
"208.67.222.123",
"208.67.220.123",
"2620:119:35::123",
"2620:119:53::123",
"9.9.9.9",
"149.112.112.112",
"2620:fe::9",
"2620:fe::fe",
"9.9.9.11",
"149.112.112.11",
"2620:fe::11",
"2620:fe::fe:11",
"9.9.9.10",
"149.112.112.10",
"2620:fe::10",
"2620:fe::fe:10",
"77.88.8.8",
"77.88.8.1",
"2a02:6b8::feed:0ff",
"2a02:6b8:0:1::feed:0ff",
"77.88.8.88",
"77.88.8.2",
"2a02:6b8::feed:bad",
"2a02:6b8:0:1::feed:bad",
"77.88.8.7",
"77.88.8.3",
"2a02:6b8::feed:a11",
"2a02:6b8:0:1::feed:a11"
]
},
{
"remarks": "代理海外公共DNS域名",
"outboundTag": "proxy",
"domain": [
"domain:cloudflare-dns.com",
"domain:one.one.one.one",
"domain:dns.google",
"domain:adguard-dns.com",
"domain:opendns.com",
"domain:umbrella.com",
"domain:quad9.net",
"domain:yandex.net"
]
},
{
"remarks": "代理IP",
"outboundTag": "proxy",
"ip": [
"geoip:facebook",
"geoip:fastly",
"geoip:google",
"geoip:netflix",
"geoip:telegram",
"geoip:twitter"
]
},
{
"remarks": "代理GFW",
"outboundTag": "proxy",
"domain": [
"geosite:gfw",
"geosite:greatfire"
]
},
{
"remarks": "最终直连",
"port": "0-65535",
"outboundTag": "direct"
}
{
"remarks": "绕过bittorrent",
"outboundTag": "direct",
"protocol": [
"bittorrent"
]
},
{
"remarks": "api.ip.sb",
"outboundTag": "proxy",
"domain": [
"api.ip.sb"
]
},
{
"remarks": "Google cn",
"outboundTag": "proxy",
"domain": [
"domain:googleapis.cn",
"domain:gstatic.com"
]
},
{
"remarks": "阻断udp443",
"outboundTag": "block",
"port": "443",
"network": "udp"
},
{
"remarks": "阻断广告",
"outboundTag": "block",
"domain": [
"geosite:category-ads-all"
]
},
{
"remarks": "绕过局域网IP",
"outboundTag": "direct",
"ip": [
"geoip:private"
]
},
{
"remarks": "绕过局域网域名",
"outboundTag": "direct",
"domain": [
"geosite:private"
]
},
{
"remarks": "代理海外公共DNSIP",
"outboundTag": "proxy",
"ip": [
"1.1.1.1",
"1.0.0.1",
"2606:4700:4700::1111",
"2606:4700:4700::1001",
"1.1.1.2",
"1.0.0.2",
"2606:4700:4700::1112",
"2606:4700:4700::1002",
"1.1.1.3",
"1.0.0.3",
"2606:4700:4700::1113",
"2606:4700:4700::1003",
"8.8.8.8",
"8.8.4.4",
"2001:4860:4860::8888",
"2001:4860:4860::8844",
"94.140.14.14",
"94.140.15.15",
"2a10:50c0::ad1:ff",
"2a10:50c0::ad2:ff",
"94.140.14.15",
"94.140.15.16",
"2a10:50c0::bad1:ff",
"2a10:50c0::bad2:ff",
"94.140.14.140",
"94.140.14.141",
"2a10:50c0::1:ff",
"2a10:50c0::2:ff",
"208.67.222.222",
"208.67.220.220",
"2620:119:35::35",
"2620:119:53::53",
"208.67.222.123",
"208.67.220.123",
"2620:119:35::123",
"2620:119:53::123",
"9.9.9.9",
"149.112.112.112",
"2620:fe::9",
"2620:fe::fe",
"9.9.9.11",
"149.112.112.11",
"2620:fe::11",
"2620:fe::fe:11",
"9.9.9.10",
"149.112.112.10",
"2620:fe::10",
"2620:fe::fe:10",
"77.88.8.8",
"77.88.8.1",
"2a02:6b8::feed:0ff",
"2a02:6b8:0:1::feed:0ff",
"77.88.8.88",
"77.88.8.2",
"2a02:6b8::feed:bad",
"2a02:6b8:0:1::feed:bad",
"77.88.8.7",
"77.88.8.3",
"2a02:6b8::feed:a11",
"2a02:6b8:0:1::feed:a11"
]
},
{
"remarks": "代理海外公共DNS域名",
"outboundTag": "proxy",
"domain": [
"domain:cloudflare-dns.com",
"domain:one.one.one.one",
"domain:dns.google",
"domain:adguard-dns.com",
"domain:opendns.com",
"domain:umbrella.com",
"domain:quad9.net",
"domain:yandex.net"
]
},
{
"remarks": "代理IP",
"outboundTag": "proxy",
"ip": [
"geoip:facebook",
"geoip:fastly",
"geoip:google",
"geoip:netflix",
"geoip:telegram",
"geoip:twitter"
]
},
{
"remarks": "代理GFW",
"outboundTag": "proxy",
"domain": [
"geosite:gfw",
"geosite:greatfire"
]
},
{
"remarks": "最终直连",
"port": "0-65535",
"outboundTag": "direct"
}
]

View File

@@ -1,21 +0,0 @@
[
{
"domain": [
"geosite:google"
],
"outboundTag": "proxy"
},
{
"outboundTag": "direct",
"domain": [
"domain:example-example.com",
"domain:example-example2.com"
]
},
{
"outboundTag": "block",
"domain": [
"geosite:category-ads-all"
]
}
]

View File

@@ -1,29 +0,0 @@
[
{
"remarks": "block",
"outboundTag": "block",
"domain": [
"geosite:category-ads-all"
]
},
{
"remarks": "direct",
"outboundTag": "direct",
"domain": [
"geosite:cn"
]
},
{
"remarks": "direct",
"outboundTag": "direct",
"ip": [
"geoip:private",
"geoip:cn"
]
},
{
"remarks": "proxy",
"port": "0-65535",
"outboundTag": "proxy"
}
]

View File

@@ -99,10 +99,5 @@
"domain": [
"geosite:cn"
]
},
{
"remarks": "最终代理",
"port": "0-65535",
"outboundTag": "proxy"
}
]

View File

@@ -2,7 +2,7 @@
"servers": [
{
"tag": "remote",
"address": "8.8.8.8",
"address": "tcp://8.8.8.8",
"strategy": "prefer_ipv4",
"detour": "proxy"
},
@@ -32,4 +32,4 @@
}
],
"final": "remote"
}
}

View File

@@ -4,6 +4,15 @@
"proxy.example.com": "127.0.0.1"
},
"servers": [
{
"address": "1.1.1.1",
"domains": [
"geosite:geolocation-!cn"
],
"expectIPs": [
"geoip:!cn"
]
},
{
"address": "223.5.5.5",
"domains": [
@@ -13,7 +22,6 @@
"geoip:cn"
]
},
"1.1.1.1",
"8.8.8.8",
"https://dns.google/dns-query"
]

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"servers": [
{
"tag": "remote",
"address": "8.8.8.8",
"address": "tcp://8.8.8.8",
"strategy": "prefer_ipv4",
"detour": "proxy"
},
@@ -33,4 +33,4 @@
}
],
"final": "remote"
}
}

View File

@@ -1,82 +1,77 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>7.2.3</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Downloader" Version="3.3.0" />
<PackageReference Include="ReactiveUI" Version="20.1.63" />
<PackageReference Include="ReactiveUI.Fody" Version="19.5.41" />
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
<PackageReference Include="Splat.NLog" Version="15.2.22" />
<PackageReference Include="WebDav.Client" Version="2.8.0" />
<PackageReference Include="YamlDotNet" Version="16.2.0" />
<PackageReference Include="QRCoder" Version="1.6.0" />
<PackageReference Include="CliWrap" Version="3.6.7" />
<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
<PackageReference Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
<PackageReference Include="TaskScheduler" Version="2.11.0" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Sample\clash_mixin_yaml" />
<EmbeddedResource Include="Sample\clash_tun_yaml" />
<EmbeddedResource Include="Sample\custom_routing_black" />
<EmbeddedResource Include="Sample\custom_routing_global" />
<EmbeddedResource Include="Sample\custom_routing_locked" />
<EmbeddedResource Include="Sample\custom_routing_rules" />
<EmbeddedResource Include="Sample\custom_routing_white" />
<EmbeddedResource Include="Sample\dns_singbox_normal" />
<EmbeddedResource Include="Sample\dns_v2ray_normal" />
<EmbeddedResource Include="Sample\pac" />
<EmbeddedResource Include="Sample\SampleClientConfig" />
<EmbeddedResource Include="Sample\SampleHttpRequest" />
<EmbeddedResource Include="Sample\SampleHttpResponse" />
<EmbeddedResource Include="Sample\SampleInbound" />
<EmbeddedResource Include="Sample\SampleOutbound" />
<EmbeddedResource Include="Sample\SingboxSampleClientConfig" />
<EmbeddedResource Include="Sample\SingboxSampleOutbound" />
<EmbeddedResource Include="Sample\tun_singbox_dns" />
<EmbeddedResource Include="Sample\tun_singbox_inbound" />
<EmbeddedResource Include="Sample\tun_singbox_rules" />
<EmbeddedResource Include="Sample\linux_autostart_config" />
</ItemGroup>
<PropertyGroup>
<OutputType>Library</OutputType>
</PropertyGroup>
<ItemGroup>
<Compile Update="Resx\ResUI.Designer.cs">
<DependentUpon>ResUI.resx</DependentUpon>
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
</Compile>
<PackageReference Include="Downloader" />
<PackageReference Include="ReactiveUI">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="ReactiveUI.Fody" />
<PackageReference Include="sqlite-net-pcl" />
<PackageReference Include="Splat.NLog" />
<PackageReference Include="WebDav.Client" />
<PackageReference Include="YamlDotNet" />
<PackageReference Include="QRCoder" />
<PackageReference Include="CliWrap" />
<PackageReference Include="ZXing.Net.Bindings.SkiaSharp" />
<PackageReference Include="TaskScheduler" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resx\ResUI.fa-Ir.resx">
<SubType>Designer</SubType>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resx\ResUI.resx">
<SubType>Designer</SubType>
<LastGenOutput>ResUI.Designer.cs</LastGenOutput>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resx\ResUI.ru.resx">
<SubType>Designer</SubType>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resx\ResUI.zh-Hans.resx">
<SubType>Designer</SubType>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resx\ResUI.zh-Hant.resx">
<SubType>Designer</SubType>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Include="Sample\clash_mixin_yaml" />
<EmbeddedResource Include="Sample\clash_tun_yaml" />
<EmbeddedResource Include="Sample\custom_routing_black" />
<EmbeddedResource Include="Sample\custom_routing_global" />
<EmbeddedResource Include="Sample\custom_routing_white" />
<EmbeddedResource Include="Sample\dns_singbox_normal" />
<EmbeddedResource Include="Sample\dns_v2ray_normal" />
<EmbeddedResource Include="Sample\pac" />
<EmbeddedResource Include="Sample\SampleClientConfig" />
<EmbeddedResource Include="Sample\SampleHttpRequest" />
<EmbeddedResource Include="Sample\SampleHttpResponse" />
<EmbeddedResource Include="Sample\SampleInbound" />
<EmbeddedResource Include="Sample\SampleOutbound" />
<EmbeddedResource Include="Sample\SingboxSampleClientConfig" />
<EmbeddedResource Include="Sample\SingboxSampleOutbound" />
<EmbeddedResource Include="Sample\tun_singbox_dns" />
<EmbeddedResource Include="Sample\tun_singbox_inbound" />
<EmbeddedResource Include="Sample\tun_singbox_rules" />
<EmbeddedResource Include="Sample\linux_autostart_config" />
</ItemGroup>
</Project>
<ItemGroup>
<Compile Update="Resx\ResUI.Designer.cs">
<DependentUpon>ResUI.resx</DependentUpon>
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
</Compile>
<EmbeddedResource Update="Resx\ResUI.fa-Ir.resx">
<SubType>Designer</SubType>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resx\ResUI.hu.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resx\ResUI.resx">
<SubType>Designer</SubType>
<LastGenOutput>ResUI.Designer.cs</LastGenOutput>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resx\ResUI.ru.resx">
<SubType>Designer</SubType>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resx\ResUI.zh-Hans.resx">
<SubType>Designer</SubType>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resx\ResUI.zh-Hant.resx">
<SubType>Designer</SubType>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -6,6 +6,7 @@ namespace ServiceLib.Services.CoreConfig
public class CoreConfigClashService
{
private Config _config;
private static readonly string _tag = "CoreConfigClashService";
public CoreConfigClashService(Config config)
{
@@ -78,17 +79,15 @@ namespace ServiceLib.Services.CoreConfig
return ret;
}
//port
fileContent["port"] = AppHandler.Instance.GetLocalPort(EInboundProtocol.http);
//socks-port
fileContent["socks-port"] = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
//mixed-port
fileContent["mixed-port"] = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
//log-level
fileContent["log-level"] = GetLogLevel(_config.CoreBasicItem.Loglevel);
//external-controller
fileContent["external-controller"] = $"{Global.Loopback}:{AppHandler.Instance.StatePort2}";
//allow-lan
if (_config.Inbound[0].AllowLANConn)
if (_config.Inbound.First().AllowLANConn)
{
fileContent["allow-lan"] = "true";
fileContent["bind-address"] = "*";
@@ -117,7 +116,7 @@ namespace ServiceLib.Services.CoreConfig
//enable tun mode
if (_config.TunModeItem.EnableTun)
{
string tun = Utils.GetEmbedText(Global.ClashTunYaml);
string tun = EmbedUtils.GetEmbedText(Global.ClashTunYaml);
if (Utils.IsNotEmpty(tun))
{
var tunContent = YamlUtils.FromYaml<Dictionary<string, object>>(tun);
@@ -133,7 +132,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog("GenerateClientConfigClash-Mixin", ex);
Logging.SaveLog($"{_tag}-Mixin", ex);
}
var txtFileNew = YamlUtils.ToYaml(fileContent).Replace(tagYamlStr2, tagYamlStr3);
@@ -153,7 +152,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog("GenerateClientConfigClash", ex);
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}

View File

@@ -7,6 +7,7 @@ namespace ServiceLib.Services.CoreConfig
public class CoreConfigSingboxService
{
private Config _config;
private static readonly string _tag = "CoreConfigSingboxService";
public CoreConfigSingboxService(Config config)
{
@@ -26,7 +27,7 @@ namespace ServiceLib.Services.CoreConfig
ret.Msg = ResUI.CheckServerSettings;
return ret;
}
if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp))
if (node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp))
{
ret.Msg = ResUI.Incorrectconfiguration + $" - {node.GetNetwork()}";
return ret;
@@ -34,7 +35,7 @@ namespace ServiceLib.Services.CoreConfig
ret.Msg = ResUI.InitialConfiguration;
string result = Utils.GetEmbedText(Global.SingboxSampleClient);
string result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
if (Utils.IsNullOrEmpty(result))
{
ret.Msg = ResUI.FailedGetDefaultConfiguration;
@@ -52,7 +53,7 @@ namespace ServiceLib.Services.CoreConfig
await GenInbounds(singboxConfig);
await GenOutbound(node, singboxConfig.outbounds[0]);
await GenOutbound(node, singboxConfig.outbounds.First());
await GenMoreOutbounds(node, singboxConfig);
@@ -71,7 +72,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog("GenerateClientConfig4Singbox", ex);
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
@@ -90,8 +91,8 @@ namespace ServiceLib.Services.CoreConfig
ret.Msg = ResUI.InitialConfiguration;
var result = Utils.GetEmbedText(Global.SingboxSampleClient);
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
{
ret.Msg = ResUI.FailedGetDefaultConfiguration;
@@ -114,7 +115,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
await GenLog(singboxConfig);
@@ -122,7 +123,7 @@ namespace ServiceLib.Services.CoreConfig
singboxConfig.inbounds.Clear();
singboxConfig.outbounds.RemoveAt(0);
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
var initPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
foreach (var it in selecteds)
{
@@ -144,8 +145,8 @@ namespace ServiceLib.Services.CoreConfig
}
//find unused port
var port = httpPort;
for (int k = httpPort; k < Global.MaxPort; k++)
var port = initPort;
for (int k = initPort; k < Global.MaxPort; k++)
{
if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)
{
@@ -157,7 +158,7 @@ namespace ServiceLib.Services.CoreConfig
}
//found
port = k;
httpPort = port + 1;
initPort = port + 1;
break;
}
@@ -174,7 +175,7 @@ namespace ServiceLib.Services.CoreConfig
{
listen = Global.Loopback,
listen_port = port,
type = EInboundProtocol.http.ToString(),
type = EInboundProtocol.mixed.ToString(),
};
inbound.tag = inbound.type + inbound.listen_port.ToString();
singboxConfig.inbounds.Add(inbound);
@@ -235,7 +236,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
@@ -254,8 +255,8 @@ namespace ServiceLib.Services.CoreConfig
ret.Msg = ResUI.InitialConfiguration;
string result = Utils.GetEmbedText(Global.SingboxSampleClient);
string txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
string result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);
string txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
{
ret.Msg = ResUI.FailedGetDefaultConfiguration;
@@ -312,7 +313,7 @@ namespace ServiceLib.Services.CoreConfig
var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);
await GenOutbound(item, outbound);
outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}";
singboxConfig.outbounds.Add(outbound);
singboxConfig.outbounds.Insert(0, outbound);
tagProxy.Add(outbound.tag);
}
if (tagProxy.Count <= 0)
@@ -332,7 +333,7 @@ namespace ServiceLib.Services.CoreConfig
outbounds = tagProxy,
interrupt_exist_connections = false,
};
singboxConfig.outbounds.Add(outUrltest);
singboxConfig.outbounds.Insert(0, outUrltest);
//add selector outbound
var outSelector = new Outbound4Sbox
@@ -343,7 +344,7 @@ namespace ServiceLib.Services.CoreConfig
interrupt_exist_connections = false,
};
outSelector.outbounds.Insert(0, outUrltest.tag);
singboxConfig.outbounds.Add(outSelector);
singboxConfig.outbounds.Insert(0, outSelector);
ret.Success = true;
ret.Data = JsonUtils.Serialize(singboxConfig);
@@ -351,7 +352,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
@@ -409,7 +410,9 @@ namespace ServiceLib.Services.CoreConfig
{
await GenInbounds(singboxConfig);
await GenExperimental(singboxConfig);
JsonUtils.ToFile(singboxConfig, fileName, false);
var content = JsonUtils.Serialize(singboxConfig, true);
await File.WriteAllTextAsync(fileName, content);
}
}
else
@@ -430,7 +433,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
@@ -440,7 +443,7 @@ namespace ServiceLib.Services.CoreConfig
#region private gen function
public async Task<int> GenLog(SingboxConfig singboxConfig)
private async Task<int> GenLog(SingboxConfig singboxConfig)
{
try
{
@@ -471,9 +474,9 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenInbounds(SingboxConfig singboxConfig)
@@ -488,15 +491,15 @@ namespace ServiceLib.Services.CoreConfig
{
var inbound = new Inbound4Sbox()
{
type = EInboundProtocol.socks.ToString(),
type = EInboundProtocol.mixed.ToString(),
tag = EInboundProtocol.socks.ToString(),
listen = Global.Loopback,
};
singboxConfig.inbounds.Add(inbound);
inbound.listen_port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
inbound.sniff = _config.Inbound[0].SniffingEnabled;
inbound.sniff_override_destination = _config.Inbound[0].RouteOnly ? false : _config.Inbound[0].SniffingEnabled;
inbound.sniff = _config.Inbound.First().SniffingEnabled;
inbound.sniff_override_destination = _config.Inbound.First().RouteOnly ? false : _config.Inbound.First().SniffingEnabled;
inbound.domain_strategy = Utils.IsNullOrEmpty(_config.RoutingBasicItem.DomainStrategy4Singbox) ? null : _config.RoutingBasicItem.DomainStrategy4Singbox;
var routing = await ConfigHandler.GetDefaultRouting(_config);
@@ -505,33 +508,29 @@ namespace ServiceLib.Services.CoreConfig
inbound.domain_strategy = routing.DomainStrategy4Singbox;
}
//http
var inbound2 = GetInbound(inbound, EInboundProtocol.http, false);
singboxConfig.inbounds.Add(inbound2);
if (_config.Inbound[0].AllowLANConn)
if (_config.Inbound.First().SecondLocalPortEnabled)
{
if (_config.Inbound[0].NewPort4LAN)
var inbound2 = GetInbound(inbound, EInboundProtocol.socks2, true);
singboxConfig.inbounds.Add(inbound2);
}
if (_config.Inbound.First().AllowLANConn)
{
if (_config.Inbound.First().NewPort4LAN)
{
var inbound3 = GetInbound(inbound, EInboundProtocol.socks2, true);
var inbound3 = GetInbound(inbound, EInboundProtocol.socks3, true);
inbound3.listen = listen;
singboxConfig.inbounds.Add(inbound3);
var inbound4 = GetInbound(inbound, EInboundProtocol.http2, false);
inbound4.listen = listen;
singboxConfig.inbounds.Add(inbound4);
//auth
if (Utils.IsNotEmpty(_config.Inbound[0].User) && Utils.IsNotEmpty(_config.Inbound[0].Pass))
if (Utils.IsNotEmpty(_config.Inbound.First().User) && Utils.IsNotEmpty(_config.Inbound.First().Pass))
{
inbound3.users = new() { new() { username = _config.Inbound[0].User, password = _config.Inbound[0].Pass } };
inbound4.users = new() { new() { username = _config.Inbound[0].User, password = _config.Inbound[0].Pass } };
inbound3.users = new() { new() { username = _config.Inbound.First().User, password = _config.Inbound.First().Pass } };
}
}
else
{
inbound.listen = listen;
inbound2.listen = listen;
}
}
}
@@ -540,20 +539,20 @@ namespace ServiceLib.Services.CoreConfig
{
if (_config.TunModeItem.Mtu <= 0)
{
_config.TunModeItem.Mtu = Utils.ToInt(Global.TunMtus[0]);
_config.TunModeItem.Mtu = Utils.ToInt(Global.TunMtus.First());
}
if (Utils.IsNullOrEmpty(_config.TunModeItem.Stack))
{
_config.TunModeItem.Stack = Global.TunStacks[0];
_config.TunModeItem.Stack = Global.TunStacks.First();
}
var tunInbound = JsonUtils.Deserialize<Inbound4Sbox>(Utils.GetEmbedText(Global.TunSingboxInboundFileName)) ?? new Inbound4Sbox { };
tunInbound.interface_name = Utils.IsOSX()? $"utun{new Random().Next(99)}": "singbox_tun";
var tunInbound = JsonUtils.Deserialize<Inbound4Sbox>(EmbedUtils.GetEmbedText(Global.TunSingboxInboundFileName)) ?? new Inbound4Sbox { };
tunInbound.interface_name = Utils.IsOSX() ? $"utun{new Random().Next(99)}" : "singbox_tun";
tunInbound.mtu = _config.TunModeItem.Mtu;
tunInbound.strict_route = _config.TunModeItem.StrictRoute;
tunInbound.stack = _config.TunModeItem.Stack;
tunInbound.sniff = _config.Inbound[0].SniffingEnabled;
//tunInbound.sniff_override_destination = _config.inbound[0].routeOnly ? false : _config.inbound[0].sniffingEnabled;
tunInbound.sniff = _config.Inbound.First().SniffingEnabled;
//tunInbound.sniff_override_destination = _config.inbound.First().routeOnly ? false : _config.inbound.First().sniffingEnabled;
if (_config.TunModeItem.EnableIPv6Address == false)
{
tunInbound.address = ["172.18.0.1/30"];
@@ -564,7 +563,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
}
@@ -574,11 +573,11 @@ namespace ServiceLib.Services.CoreConfig
var inbound = JsonUtils.DeepCopy(inItem);
inbound.tag = protocol.ToString();
inbound.listen_port = inItem.listen_port + (int)protocol;
inbound.type = bSocks ? EInboundProtocol.socks.ToString() : EInboundProtocol.http.ToString();
inbound.type = EInboundProtocol.mixed.ToString();
return inbound;
}
public async Task<int> GenOutbound(ProfileItem node, Outbound4Sbox outbound)
private async Task<int> GenOutbound(ProfileItem node, Outbound4Sbox outbound)
{
try
{
@@ -697,12 +696,12 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
}
public async Task<int> GenOutboundMux(ProfileItem node, Outbound4Sbox outbound)
private async Task<int> GenOutboundMux(ProfileItem node, Outbound4Sbox outbound)
{
try
{
@@ -720,12 +719,12 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
public async Task<int> GenOutboundTls(ProfileItem node, Outbound4Sbox outbound)
private async Task<int> GenOutboundTls(ProfileItem node, Outbound4Sbox outbound)
{
try
{
@@ -770,12 +769,12 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
public async Task<int> GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound)
private async Task<int> GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound)
{
try
{
@@ -847,9 +846,9 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenMoreOutbounds(ProfileItem node, SingboxConfig singboxConfig)
@@ -867,8 +866,8 @@ namespace ServiceLib.Services.CoreConfig
}
//current proxy
var outbound = singboxConfig.outbounds[0];
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
var outbound = singboxConfig.outbounds.First();
var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
//Previous proxy
var prevNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.PrevProfile);
@@ -899,7 +898,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
@@ -910,7 +909,7 @@ namespace ServiceLib.Services.CoreConfig
try
{
var dnsOutbound = "dns_out";
if (!_config.Inbound[0].SniffingEnabled)
if (!_config.Inbound.First().SniffingEnabled)
{
singboxConfig.route.rules.Add(new()
{
@@ -935,7 +934,7 @@ namespace ServiceLib.Services.CoreConfig
{
singboxConfig.route.auto_detect_interface = true;
var tunRules = JsonUtils.Deserialize<List<Rule4Sbox>>(Utils.GetEmbedText(Global.TunSingboxRulesFileName));
var tunRules = JsonUtils.Deserialize<List<Rule4Sbox>>(EmbedUtils.GetEmbedText(Global.TunSingboxRulesFileName));
if (tunRules != null)
{
singboxConfig.route.rules.AddRange(tunRules);
@@ -971,7 +970,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
}
@@ -1002,7 +1001,7 @@ namespace ServiceLib.Services.CoreConfig
}
}
public async Task<int> GenRoutingUserRule(RulesItem item, List<Rule4Sbox> rules)
private async Task<int> GenRoutingUserRule(RulesItem item, List<Rule4Sbox> rules)
{
try
{
@@ -1049,7 +1048,8 @@ namespace ServiceLib.Services.CoreConfig
var countDomain = 0;
foreach (var it in item.Domain)
{
if (ParseV2Domain(it, rule1)) countDomain++;
if (ParseV2Domain(it, rule1))
countDomain++;
}
if (countDomain > 0)
{
@@ -1063,7 +1063,8 @@ namespace ServiceLib.Services.CoreConfig
var countIp = 0;
foreach (var it in item.Ip)
{
if (ParseV2Address(it, rule2)) countIp++;
if (ParseV2Address(it, rule2))
countIp++;
}
if (countIp > 0)
{
@@ -1087,9 +1088,9 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private bool ParseV2Domain(string domain, Rule4Sbox rule)
@@ -1149,18 +1150,20 @@ namespace ServiceLib.Services.CoreConfig
}
else if (address.StartsWith("geoip:"))
{
if (rule.geoip is null) { rule.geoip = new(); }
if (rule.geoip is null)
{ rule.geoip = new(); }
rule.geoip?.Add(address.Substring(6));
}
else
{
if (rule.ip_cidr is null) { rule.ip_cidr = new(); }
if (rule.ip_cidr is null)
{ rule.ip_cidr = new(); }
rule.ip_cidr?.Add(address);
}
return true;
}
public async Task<int> GenDns(ProfileItem? node, SingboxConfig singboxConfig)
private async Task<int> GenDns(ProfileItem? node, SingboxConfig singboxConfig)
{
try
{
@@ -1168,11 +1171,11 @@ namespace ServiceLib.Services.CoreConfig
var strDNS = string.Empty;
if (_config.TunModeItem.EnableTun)
{
strDNS = Utils.IsNullOrEmpty(item?.TunDNS) ? Utils.GetEmbedText(Global.TunSingboxDNSFileName) : item?.TunDNS;
strDNS = Utils.IsNullOrEmpty(item?.TunDNS) ? EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName) : item?.TunDNS;
}
else
{
strDNS = Utils.IsNullOrEmpty(item?.NormalDNS) ? Utils.GetEmbedText(Global.DNSSingboxNormalFileName) : item?.NormalDNS;
strDNS = Utils.IsNullOrEmpty(item?.NormalDNS) ? EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName) : item?.NormalDNS;
}
var dns4Sbox = JsonUtils.Deserialize<Dns4Sbox>(strDNS);
@@ -1186,12 +1189,12 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
}
public async Task<int> GenDnsDomains(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem)
private async Task<int> GenDnsDomains(ProfileItem? node, SingboxConfig singboxConfig, DNSItem? dNSItem)
{
var dns4Sbox = singboxConfig.dns ?? new();
dns4Sbox.servers ??= [];
@@ -1241,10 +1244,10 @@ namespace ServiceLib.Services.CoreConfig
}
singboxConfig.dns = dns4Sbox;
return 0;
return await Task.FromResult(0);
}
public async Task<int> GenExperimental(SingboxConfig singboxConfig)
private async Task<int> GenExperimental(SingboxConfig singboxConfig)
{
//if (_config.guiItem.enableStatistics)
{
@@ -1260,18 +1263,20 @@ namespace ServiceLib.Services.CoreConfig
singboxConfig.experimental ??= new Experimental4Sbox();
singboxConfig.experimental.cache_file = new CacheFile4Sbox()
{
enabled = true
enabled = true,
path = Utils.GetConfigPath("cache.db")
};
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> ConvertGeo2Ruleset(SingboxConfig singboxConfig)
{
static void AddRuleSets(List<string> ruleSets, List<string>? rule_set)
{
if (rule_set != null) ruleSets.AddRange(rule_set);
if (rule_set != null)
ruleSets.AddRange(rule_set);
}
var geosite = "geosite";
var geoip = "geoip";
@@ -1321,7 +1326,7 @@ namespace ServiceLib.Services.CoreConfig
var routing = await ConfigHandler.GetDefaultRouting(_config);
if (Utils.IsNotEmpty(routing.CustomRulesetPath4Singbox))
{
var result = Utils.LoadResource(routing.CustomRulesetPath4Singbox);
var result = EmbedUtils.LoadResource(routing.CustomRulesetPath4Singbox);
if (Utils.IsNotEmpty(result))
{
customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])
@@ -1339,7 +1344,8 @@ namespace ServiceLib.Services.CoreConfig
singboxConfig.route.rule_set = [];
foreach (var item in new HashSet<string>(ruleSets))
{
if (Utils.IsNullOrEmpty(item)) { continue; }
if (Utils.IsNullOrEmpty(item))
{ continue; }
var customRuleset = customRulesets.FirstOrDefault(t => t.tag != null && t.tag.Equals(item));
if (customRuleset is null)
{
@@ -1378,4 +1384,4 @@ namespace ServiceLib.Services.CoreConfig
#endregion private gen function
}
}
}

View File

@@ -1,4 +1,4 @@
using System.Net;
using System.Net;
using System.Net.NetworkInformation;
using System.Text.Json.Nodes;
@@ -7,6 +7,7 @@ namespace ServiceLib.Services.CoreConfig
public class CoreConfigV2rayService
{
private Config _config;
private static readonly string _tag = "CoreConfigV2rayService";
public CoreConfigV2rayService(Config config)
{
@@ -35,7 +36,7 @@ namespace ServiceLib.Services.CoreConfig
ret.Msg = ResUI.InitialConfiguration;
var result = Utils.GetEmbedText(Global.V2raySampleClient);
var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
if (Utils.IsNullOrEmpty(result))
{
ret.Msg = ResUI.FailedGetDefaultConfiguration;
@@ -55,7 +56,7 @@ namespace ServiceLib.Services.CoreConfig
await GenRouting(v2rayConfig);
await GenOutbound(node, v2rayConfig.outbounds[0]);
await GenOutbound(node, v2rayConfig.outbounds.First());
await GenMoreOutbounds(node, v2rayConfig);
@@ -70,7 +71,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog("GenerateClientConfig4V2ray", ex);
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
@@ -90,8 +91,8 @@ namespace ServiceLib.Services.CoreConfig
ret.Msg = ResUI.InitialConfiguration;
string result = Utils.GetEmbedText(Global.V2raySampleClient);
string txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
string result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
string txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
{
ret.Msg = ResUI.FailedGetDefaultConfiguration;
@@ -153,7 +154,7 @@ namespace ServiceLib.Services.CoreConfig
var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
await GenOutbound(item, outbound);
outbound.tag = $"{Global.ProxyTag}-{tagProxy.Count + 1}";
v2rayConfig.outbounds.Add(outbound);
v2rayConfig.outbounds.Insert(0, outbound);
tagProxy.Add(outbound.tag);
}
if (tagProxy.Count <= 0)
@@ -181,15 +182,12 @@ namespace ServiceLib.Services.CoreConfig
rule.balancerTag = balancer.tag;
}
}
else
v2rayConfig.routing.rules.Add(new()
{
v2rayConfig.routing.rules.Add(new()
{
network = "tcp,udp",
balancerTag = balancer.tag,
type = "field"
});
}
network = "tcp,udp",
balancerTag = balancer.tag,
type = "field"
});
ret.Success = true;
ret.Data = JsonUtils.Serialize(v2rayConfig);
@@ -197,7 +195,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
@@ -216,8 +214,8 @@ namespace ServiceLib.Services.CoreConfig
ret.Msg = ResUI.InitialConfiguration;
var result = Utils.GetEmbedText(Global.V2raySampleClient);
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
var txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);
if (Utils.IsNullOrEmpty(result) || txtOutbound.IsNullOrEmpty())
{
ret.Msg = ResUI.FailedGetDefaultConfiguration;
@@ -240,7 +238,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
await GenLog(v2rayConfig);
@@ -248,7 +246,7 @@ namespace ServiceLib.Services.CoreConfig
v2rayConfig.outbounds.Clear();
v2rayConfig.routing.rules.Clear();
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
var initPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.speedtest);
foreach (var it in selecteds)
{
@@ -270,8 +268,8 @@ namespace ServiceLib.Services.CoreConfig
}
//find unused port
var port = httpPort;
for (var k = httpPort; k < Global.MaxPort; k++)
var port = initPort;
for (var k = initPort; k < Global.MaxPort; k++)
{
if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)
{
@@ -283,7 +281,7 @@ namespace ServiceLib.Services.CoreConfig
}
//found
port = k;
httpPort = port + 1;
initPort = port + 1;
break;
}
@@ -322,7 +320,7 @@ namespace ServiceLib.Services.CoreConfig
{
listen = Global.Loopback,
port = port,
protocol = EInboundProtocol.http.ToString(),
protocol = EInboundProtocol.socks.ToString(),
};
inbound.tag = inbound.protocol + inbound.port.ToString();
v2rayConfig.inbounds.Add(inbound);
@@ -349,7 +347,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
ret.Msg = ResUI.FailedGenDefaultConfiguration;
return ret;
}
@@ -359,7 +357,7 @@ namespace ServiceLib.Services.CoreConfig
#region private gen function
public async Task<int> GenLog(V2rayConfig v2rayConfig)
private async Task<int> GenLog(V2rayConfig v2rayConfig)
{
try
{
@@ -379,64 +377,58 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
public async Task<int> GenInbounds(V2rayConfig v2rayConfig)
private async Task<int> GenInbounds(V2rayConfig v2rayConfig)
{
try
{
var listen = "0.0.0.0";
v2rayConfig.inbounds = [];
Inbounds4Ray? inbound = GetInbound(_config.Inbound[0], EInboundProtocol.socks, true);
var inbound = GetInbound(_config.Inbound.First(), EInboundProtocol.socks, true);
v2rayConfig.inbounds.Add(inbound);
//http
Inbounds4Ray? inbound2 = GetInbound(_config.Inbound[0], EInboundProtocol.http, false);
v2rayConfig.inbounds.Add(inbound2);
if (_config.Inbound[0].AllowLANConn)
if (_config.Inbound.First().SecondLocalPortEnabled)
{
if (_config.Inbound[0].NewPort4LAN)
var inbound2 = GetInbound(_config.Inbound.First(), EInboundProtocol.socks2, true);
v2rayConfig.inbounds.Add(inbound2);
}
if (_config.Inbound.First().AllowLANConn)
{
if (_config.Inbound.First().NewPort4LAN)
{
var inbound3 = GetInbound(_config.Inbound[0], EInboundProtocol.socks2, true);
var inbound3 = GetInbound(_config.Inbound.First(), EInboundProtocol.socks3, true);
inbound3.listen = listen;
v2rayConfig.inbounds.Add(inbound3);
var inbound4 = GetInbound(_config.Inbound[0], EInboundProtocol.http2, false);
inbound4.listen = listen;
v2rayConfig.inbounds.Add(inbound4);
//auth
if (Utils.IsNotEmpty(_config.Inbound[0].User) && Utils.IsNotEmpty(_config.Inbound[0].Pass))
if (Utils.IsNotEmpty(_config.Inbound.First().User) && Utils.IsNotEmpty(_config.Inbound.First().Pass))
{
inbound3.settings.auth = "password";
inbound3.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.Inbound[0].User, pass = _config.Inbound[0].Pass } };
inbound4.settings.auth = "password";
inbound4.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.Inbound[0].User, pass = _config.Inbound[0].Pass } };
inbound3.settings.accounts = new List<AccountsItem4Ray> { new AccountsItem4Ray() { user = _config.Inbound.First().User, pass = _config.Inbound.First().Pass } };
}
}
else
{
inbound.listen = listen;
inbound2.listen = listen;
}
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
private Inbounds4Ray GetInbound(InItem inItem, EInboundProtocol protocol, bool bSocks)
{
string result = Utils.GetEmbedText(Global.V2raySampleInbound);
string result = EmbedUtils.GetEmbedText(Global.V2raySampleInbound);
if (Utils.IsNullOrEmpty(result))
{
return new();
@@ -449,7 +441,7 @@ namespace ServiceLib.Services.CoreConfig
}
inbound.tag = protocol.ToString();
inbound.port = inItem.LocalPort + (int)protocol;
inbound.protocol = bSocks ? EInboundProtocol.socks.ToString() : EInboundProtocol.http.ToString();
inbound.protocol = EInboundProtocol.socks.ToString();
inbound.settings.udp = inItem.UdpEnabled;
inbound.sniffing.enabled = inItem.SniffingEnabled;
inbound.sniffing.destOverride = inItem.DestOverride;
@@ -488,12 +480,12 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
}
public async Task<int> GenRoutingUserRule(RulesItem4Ray? rule, V2rayConfig v2rayConfig)
private async Task<int> GenRoutingUserRule(RulesItem4Ray? rule, V2rayConfig v2rayConfig)
{
try
{
@@ -566,15 +558,16 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
public async Task<int> GenOutbound(ProfileItem node, Outbounds4Ray outbound)
private async Task<int> GenOutbound(ProfileItem node, Outbounds4Ray outbound)
{
try
{
var muxEnabled = _config.CoreBasicItem.MuxEnabled;
switch (node.ConfigType)
{
case EConfigType.VMess:
@@ -587,7 +580,7 @@ namespace ServiceLib.Services.CoreConfig
}
else
{
vnextItem = outbound.settings.vnext[0];
vnextItem = outbound.settings.vnext.First();
}
vnextItem.address = node.Address;
vnextItem.port = node.Port;
@@ -600,7 +593,7 @@ namespace ServiceLib.Services.CoreConfig
}
else
{
usersItem = vnextItem.users[0];
usersItem = vnextItem.users.First();
}
//远程服务器用户ID
usersItem.id = node.Id;
@@ -615,7 +608,7 @@ namespace ServiceLib.Services.CoreConfig
usersItem.security = Global.DefaultSecurity;
}
await GenOutboundMux(node, outbound, _config.CoreBasicItem.MuxEnabled);
await GenOutboundMux(node, outbound, muxEnabled, muxEnabled);
outbound.settings.servers = null;
break;
@@ -630,7 +623,7 @@ namespace ServiceLib.Services.CoreConfig
}
else
{
serversItem = outbound.settings.servers[0];
serversItem = outbound.settings.servers.First();
}
serversItem.address = node.Address;
serversItem.port = node.Port;
@@ -640,7 +633,7 @@ namespace ServiceLib.Services.CoreConfig
serversItem.ota = false;
serversItem.level = 1;
await GenOutboundMux(node, outbound, false);
await GenOutboundMux(node, outbound);
outbound.settings.vnext = null;
break;
@@ -656,7 +649,7 @@ namespace ServiceLib.Services.CoreConfig
}
else
{
serversItem = outbound.settings.servers[0];
serversItem = outbound.settings.servers.First();
}
serversItem.address = node.Address;
serversItem.port = node.Port;
@@ -676,7 +669,7 @@ namespace ServiceLib.Services.CoreConfig
serversItem.users = new List<SocksUsersItem4Ray>() { socksUsersItem };
}
await GenOutboundMux(node, outbound, false);
await GenOutboundMux(node, outbound);
outbound.settings.vnext = null;
break;
@@ -691,7 +684,7 @@ namespace ServiceLib.Services.CoreConfig
}
else
{
vnextItem = outbound.settings.vnext[0];
vnextItem = outbound.settings.vnext.First();
}
vnextItem.address = node.Address;
vnextItem.port = node.Port;
@@ -704,29 +697,21 @@ namespace ServiceLib.Services.CoreConfig
}
else
{
usersItem = vnextItem.users[0];
usersItem = vnextItem.users.First();
}
usersItem.id = node.Id;
usersItem.email = Global.UserEMail;
usersItem.encryption = node.Security;
await GenOutboundMux(node, outbound, _config.CoreBasicItem.MuxEnabled);
if (node.StreamSecurity == Global.StreamSecurityReality
|| node.StreamSecurity == Global.StreamSecurity)
if (node.Flow.IsNullOrEmpty())
{
if (Utils.IsNotEmpty(node.Flow))
{
usersItem.flow = node.Flow;
await GenOutboundMux(node, outbound, false);
}
await GenOutboundMux(node, outbound, muxEnabled, muxEnabled);
}
if (node.StreamSecurity == Global.StreamSecurityReality && Utils.IsNullOrEmpty(node.Flow))
else
{
await GenOutboundMux(node, outbound, _config.CoreBasicItem.MuxEnabled);
usersItem.flow = node.Flow;
await GenOutboundMux(node, outbound, false, muxEnabled);
}
outbound.settings.servers = null;
break;
}
@@ -740,7 +725,7 @@ namespace ServiceLib.Services.CoreConfig
}
else
{
serversItem = outbound.settings.servers[0];
serversItem = outbound.settings.servers.First();
}
serversItem.address = node.Address;
serversItem.port = node.Port;
@@ -749,7 +734,7 @@ namespace ServiceLib.Services.CoreConfig
serversItem.ota = false;
serversItem.level = 1;
await GenOutboundMux(node, outbound, false);
await GenOutboundMux(node, outbound);
outbound.settings.vnext = null;
break;
@@ -757,47 +742,51 @@ namespace ServiceLib.Services.CoreConfig
}
outbound.protocol = Global.ProtocolTypes[node.ConfigType];
await GenBoundStreamSettings(node, outbound.streamSettings);
await GenBoundStreamSettings(node, outbound);
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
}
public async Task<int> GenOutboundMux(ProfileItem node, Outbounds4Ray outbound, bool enabled)
private async Task<int> GenOutboundMux(ProfileItem node, Outbounds4Ray outbound, bool enabledTCP = false, bool enabledUDP = false)
{
try
{
if (enabled)
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
if (enabledTCP)
{
outbound.mux.enabled = true;
outbound.mux.concurrency = _config.Mux4RayItem.Concurrency;
}
else if (enabledUDP)
{
outbound.mux.enabled = true;
outbound.mux.xudpConcurrency = _config.Mux4RayItem.XudpConcurrency;
outbound.mux.xudpProxyUDP443 = _config.Mux4RayItem.XudpProxyUDP443;
}
else
{
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
return await Task.FromResult(0);
}
public async Task<int> GenBoundStreamSettings(ProfileItem node, StreamSettings4Ray streamSettings)
private async Task<int> GenBoundStreamSettings(ProfileItem node, Outbounds4Ray outbound)
{
try
{
var streamSettings = outbound.streamSettings;
streamSettings.network = node.GetNetwork();
string host = node.RequestHost.TrimEx();
string sni = node.Sni;
string useragent = "";
var host = node.RequestHost.TrimEx();
var path = node.Path.TrimEx();
var sni = node.Sni.TrimEx();
var useragent = "";
if (!_config.CoreBasicItem.DefUserAgent.IsNullOrEmpty())
{
try
@@ -870,9 +859,9 @@ namespace ServiceLib.Services.CoreConfig
{
type = node.HeaderType
};
if (Utils.IsNotEmpty(node.Path))
if (Utils.IsNotEmpty(path))
{
kcpSettings.seed = node.Path;
kcpSettings.seed = path;
}
streamSettings.kcpSettings = kcpSettings;
break;
@@ -880,9 +869,10 @@ namespace ServiceLib.Services.CoreConfig
case nameof(ETransport.ws):
WsSettings4Ray wsSettings = new();
wsSettings.headers = new Headers4Ray();
string path = node.Path;
if (Utils.IsNotEmpty(host))
{
wsSettings.host = host;
wsSettings.headers.Host = host;
}
if (Utils.IsNotEmpty(path))
@@ -900,9 +890,9 @@ namespace ServiceLib.Services.CoreConfig
case nameof(ETransport.httpupgrade):
HttpupgradeSettings4Ray httpupgradeSettings = new();
if (Utils.IsNotEmpty(node.Path))
if (Utils.IsNotEmpty(path))
{
httpupgradeSettings.path = node.Path;
httpupgradeSettings.path = path;
}
if (Utils.IsNotEmpty(host))
{
@@ -914,16 +904,11 @@ namespace ServiceLib.Services.CoreConfig
//xhttp
case nameof(ETransport.xhttp):
streamSettings.network = ETransport.xhttp.ToString();
XhttpSettings4Ray xhttpSettings = new()
{
scMaxEachPostBytes = "500000-1000000",
scMaxConcurrentPosts = "50-100",
scMinPostsIntervalMs = "30-50"
};
XhttpSettings4Ray xhttpSettings = new();
if (Utils.IsNotEmpty(node.Path))
if (Utils.IsNotEmpty(path))
{
xhttpSettings.path = node.Path;
xhttpSettings.path = path;
}
if (Utils.IsNotEmpty(host))
{
@@ -939,6 +924,7 @@ namespace ServiceLib.Services.CoreConfig
}
streamSettings.xhttpSettings = xhttpSettings;
await GenOutboundMux(node, outbound);
break;
//h2
@@ -949,7 +935,7 @@ namespace ServiceLib.Services.CoreConfig
{
httpSettings.host = Utils.String2List(host);
}
httpSettings.path = node.Path;
httpSettings.path = path;
streamSettings.httpSettings = httpSettings;
@@ -959,7 +945,7 @@ namespace ServiceLib.Services.CoreConfig
QuicSettings4Ray quicsettings = new()
{
security = host,
key = node.Path,
key = path,
header = new Header4Ray
{
type = node.HeaderType
@@ -983,7 +969,7 @@ namespace ServiceLib.Services.CoreConfig
GrpcSettings4Ray grpcSettings = new()
{
authority = Utils.IsNullOrEmpty(host) ? null : host,
serviceName = node.Path,
serviceName = path,
multiMode = node.HeaderType == Global.GrpcMultiMode,
idle_timeout = _config.GrpcItem.IdleTimeout,
health_check_timeout = _config.GrpcItem.HealthCheckTimeout,
@@ -1006,16 +992,16 @@ namespace ServiceLib.Services.CoreConfig
};
//request Host
string request = Utils.GetEmbedText(Global.V2raySampleHttpRequestFileName);
string request = EmbedUtils.GetEmbedText(Global.V2raySampleHttpRequestFileName);
string[] arrHost = host.Split(',');
string host2 = string.Join(",".AppendQuotes(), arrHost);
request = request.Replace("$requestHost$", $"{host2.AppendQuotes()}");
request = request.Replace("$requestUserAgent$", $"{useragent.AppendQuotes()}");
//Path
string pathHttp = @"/";
if (Utils.IsNotEmpty(node.Path))
if (Utils.IsNotEmpty(path))
{
string[] arrPath = node.Path.Split(',');
string[] arrPath = path.Split(',');
pathHttp = string.Join(",".AppendQuotes(), arrPath);
}
request = request.Replace("$requestPath$", $"{pathHttp.AppendQuotes()}");
@@ -1028,12 +1014,12 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
}
public async Task<int> GenDns(ProfileItem? node, V2rayConfig v2rayConfig)
private async Task<int> GenDns(ProfileItem? node, V2rayConfig v2rayConfig)
{
try
{
@@ -1042,15 +1028,19 @@ namespace ServiceLib.Services.CoreConfig
var domainStrategy4Freedom = item?.DomainStrategy4Freedom;
if (Utils.IsNullOrEmpty(normalDNS))
{
normalDNS = Utils.GetEmbedText(Global.DNSV2rayNormalFileName);
normalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName);
}
//Outbound Freedom domainStrategy
if (Utils.IsNotEmpty(domainStrategy4Freedom))
{
var outbound = v2rayConfig.outbounds[1];
outbound.settings.domainStrategy = domainStrategy4Freedom;
outbound.settings.userLevel = 0;
var outbound = v2rayConfig.outbounds.FirstOrDefault(t => t is { protocol: "freedom", tag: Global.DirectTag });
if (outbound != null)
{
outbound.settings = new();
outbound.settings.domainStrategy = domainStrategy4Freedom;
outbound.settings.userLevel = 0;
}
}
var obj = JsonUtils.ParseJson(normalDNS);
@@ -1091,12 +1081,12 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
}
public async Task<int> GenDnsDomains(ProfileItem? node, JsonNode dns, DNSItem? dNSItem)
private async Task<int> GenDnsDomains(ProfileItem? node, JsonNode dns, DNSItem? dNSItem)
{
if (node == null)
{ return 0; }
@@ -1113,12 +1103,12 @@ namespace ServiceLib.Services.CoreConfig
servers.AsArray().Add(JsonUtils.SerializeToNode(dnsServer));
}
}
return 0;
return await Task.FromResult(0);
}
public async Task<int> GenStatistic(V2rayConfig v2rayConfig)
private async Task<int> GenStatistic(V2rayConfig v2rayConfig)
{
if (_config.GuiItem.EnableStatistics)
if (_config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)
{
string tag = EInboundProtocol.api.ToString();
Metrics4Ray apiObj = new();
@@ -1160,14 +1150,14 @@ namespace ServiceLib.Services.CoreConfig
v2rayConfig.routing.rules.Add(apiRoutingRule);
}
}
return 0;
return await Task.FromResult(0);
}
private async Task<int> GenMoreOutbounds(ProfileItem node, V2rayConfig v2rayConfig)
{
//fragment proxy
if (_config.CoreBasicItem.EnableFragment
&& Utils.IsNotEmpty(v2rayConfig.outbounds[0].streamSettings?.security))
&& Utils.IsNotEmpty(v2rayConfig.outbounds.First().streamSettings?.security))
{
var fragmentOutbound = new Outbounds4Ray
{
@@ -1177,15 +1167,15 @@ namespace ServiceLib.Services.CoreConfig
{
fragment = new()
{
packets = "tlshello",
length = "100-200",
interval = "10-20"
packets = _config.Fragment4RayItem?.Packets,
length = _config.Fragment4RayItem?.Length,
interval = _config.Fragment4RayItem?.Interval
}
}
};
v2rayConfig.outbounds.Add(fragmentOutbound);
v2rayConfig.outbounds[0].streamSettings.sockopt = new()
v2rayConfig.outbounds.First().streamSettings.sockopt = new()
{
dialerProxy = fragmentOutbound.tag
};
@@ -1205,8 +1195,8 @@ namespace ServiceLib.Services.CoreConfig
}
//current proxy
var outbound = v2rayConfig.outbounds[0];
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
var outbound = v2rayConfig.outbounds.First();
var txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);
//Previous proxy
var prevNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.PrevProfile);
@@ -1249,7 +1239,7 @@ namespace ServiceLib.Services.CoreConfig
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return 0;
@@ -1257,4 +1247,4 @@ namespace ServiceLib.Services.CoreConfig
#endregion private gen function
}
}
}

View File

@@ -14,6 +14,8 @@ namespace ServiceLib.Services
public event ErrorEventHandler? Error;
private static readonly string _tag = "DownloadService";
public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Action<bool, string> updateFunc)
{
try
@@ -68,7 +70,7 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
@@ -113,7 +115,7 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
@@ -131,7 +133,7 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
@@ -177,7 +179,7 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
@@ -208,7 +210,7 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
Error?.Invoke(this, new ErrorEventArgs(ex));
if (ex.InnerException != null)
{
@@ -232,13 +234,13 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
return -1;
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
return -1;
}
}
@@ -280,13 +282,13 @@ namespace ServiceLib.Services
{
return null;
}
var httpPort = AppHandler.Instance.GetLocalPort(EInboundProtocol.http);
if (await SocketCheck(Global.Loopback, httpPort) == false)
var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
if (await SocketCheck(Global.Loopback, port) == false)
{
return null;
}
return new WebProxy(Global.Loopback, httpPort);
return new WebProxy($"socks5://{Global.Loopback}:{port}");
}
private async Task<bool> SocketCheck(string ip, int port)

View File

@@ -1,37 +1,95 @@
using ReactiveUI;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using ReactiveUI;
namespace ServiceLib.Services
{
public class SpeedtestService
{
private Config? _config;
private List<ServerTestItem> _selecteds;
private ESpeedActionType _actionType;
private Action<SpeedTestResult>? _updateFunc;
private bool _exitLoop = false;
public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> updateFunc)
private bool _exitLoop = false;
private static readonly string _tag = "SpeedtestService";
public SpeedtestService(Config config, ESpeedActionType actionType, List<ProfileItem> selecteds, Action<SpeedTestResult> updateFunc)
{
_config = config;
_actionType = actionType;
_updateFunc = updateFunc;
_selecteds = new List<ServerTestItem>();
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop);
Task.Run(async () =>
{
var lstSelected = GetClearItem(actionType, selecteds);
await RunAsync(actionType, lstSelected);
UpdateFunc("", ResUI.SpeedtestingCompleted);
});
}
private async Task RunAsync(ESpeedActionType actionType, List<ServerTestItem> lstSelected, int pageSize = 0)
{
if (actionType == ESpeedActionType.Tcping)
{
await RunTcpingAsync(lstSelected);
return;
}
if (pageSize <= 0)
{
pageSize = lstSelected.Count < Global.SpeedTestPageSize ? lstSelected.Count : Global.SpeedTestPageSize;
}
var lstTest = GetTestBatchItem(lstSelected, pageSize);
List<ServerTestItem> lstFailed = new();
foreach (var lst in lstTest)
{
var ret = actionType switch
{
ESpeedActionType.Realping => await RunRealPingAsync(lst),
ESpeedActionType.Speedtest => await RunSpeedTestAsync(lst),
ESpeedActionType.Mixedtest => await RunMixedTestAsync(lst),
_ => true
};
if (ret == false)
{
lstFailed.AddRange(lst);
}
await Task.Delay(100);
}
//Retest the failed part
var pageSizeNext = pageSize / 2;
if (lstFailed.Count > 0 && pageSizeNext > 0)
{
if (_exitLoop)
{
UpdateFunc("", ResUI.SpeedtestingSkip);
return;
}
UpdateFunc("", string.Format(ResUI.SpeedtestingTestFailedPart, lstFailed.Count));
await RunAsync(actionType, lstFailed, pageSizeNext);
}
}
private List<ServerTestItem> GetClearItem(ESpeedActionType actionType, List<ProfileItem> selecteds)
{
var lstSelected = new List<ServerTestItem>();
foreach (var it in selecteds)
{
if (it.ConfigType == EConfigType.Custom)
{
continue;
}
if (it.Port <= 0)
{
continue;
}
_selecteds.Add(new ServerTestItem()
lstSelected.Add(new ServerTestItem()
{
IndexId = it.IndexId,
Address = it.Address,
@@ -39,8 +97,9 @@ namespace ServiceLib.Services
ConfigType = it.ConfigType
});
}
//clear test result
foreach (var it in _selecteds)
foreach (var it in lstSelected)
{
switch (actionType)
{
@@ -63,40 +122,41 @@ namespace ServiceLib.Services
}
}
switch (actionType)
return lstSelected;
}
private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize)
{
List<List<ServerTestItem>> lstTest = new();
var lst1 = lstSelected.Where(t => t.ConfigType is not (EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard)).ToList();
var lst2 = lstSelected.Where(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.WireGuard).ToList();
for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++)
{
case ESpeedActionType.Tcping:
Task.Run(RunTcping);
break;
case ESpeedActionType.Realping:
Task.Run(RunRealPing);
break;
case ESpeedActionType.Speedtest:
Task.Run(RunSpeedTestAsync);
break;
case ESpeedActionType.Mixedtest:
Task.Run(RunMixedtestAsync);
break;
lstTest.Add(lst1.Skip(num * pageSize).Take(pageSize).ToList());
}
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop);
for (var num = 0; num < (int)Math.Ceiling(lst2.Count * 1.0 / pageSize); num++)
{
lstTest.Add(lst2.Skip(num * pageSize).Take(pageSize).ToList());
}
return lstTest;
}
private void ExitLoop(string x)
{
if (_exitLoop) return;
if (_exitLoop)
return;
_exitLoop = true;
UpdateFunc("", ResUI.SpeedtestingStop);
}
private async Task RunTcping()
private async Task RunTcpingAsync(List<ServerTestItem> selecteds)
{
try
{
List<Task> tasks = [];
foreach (var it in _selecteds)
foreach (var it in selecteds)
{
if (it.ConfigType == EConfigType.Custom)
{
@@ -106,7 +166,7 @@ namespace ServiceLib.Services
{
try
{
int time = await GetTcpingTime(it.Address, it.Port);
var time = await GetTcpingTime(it.Address, it.Port);
var output = FormatOut(time, Global.DelayUnit);
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
@@ -114,7 +174,7 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}));
}
@@ -122,7 +182,7 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
finally
{
@@ -130,24 +190,21 @@ namespace ServiceLib.Services
}
}
private async Task RunRealPing()
private async Task<bool> RunRealPingAsync(List<ServerTestItem> selecteds)
{
int pid = -1;
var pid = -1;
try
{
string msg = string.Empty;
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds);
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
return;
return false;
}
DownloadService downloadHandle = new DownloadService();
var downloadHandle = new DownloadService();
List<Task> tasks = new();
foreach (var it in _selecteds)
foreach (var it in selecteds)
{
if (!it.AllowTest)
{
@@ -161,17 +218,17 @@ namespace ServiceLib.Services
{
try
{
WebProxy webProxy = new(Global.Loopback, it.Port);
string output = await GetRealPingTime(downloadHandle, webProxy);
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
var output = await GetRealPingTime(downloadHandle, webProxy);
ProfileExHandler.Instance.SetTestDelay(it.IndexId, output);
UpdateFunc(it.IndexId, output);
int.TryParse(output, out int delay);
int.TryParse(output, out var delay);
it.Delay = delay;
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}));
}
@@ -179,39 +236,34 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
finally
{
if (pid > 0)
{
CoreHandler.Instance.CoreStopPid(pid);
await ProcUtils.ProcessKill(pid);
}
await ProfileExHandler.Instance.SaveTo();
}
return true;
}
private async Task RunSpeedTestAsync()
private async Task<bool> RunSpeedTestAsync(List<ServerTestItem> selecteds)
{
int pid = -1;
//if (_actionType == ESpeedActionType.Mixedtest)
//{
// _selecteds = _selecteds.OrderBy(t => t.delay).ToList();
//}
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds);
var pid = -1;
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
return;
return false;
}
string url = _config.SpeedTestItem.SpeedTestUrl;
var url = _config.SpeedTestItem.SpeedTestUrl;
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
DownloadService downloadHandle = new();
foreach (var it in _selecteds)
foreach (var it in selecteds)
{
if (_exitLoop)
{
@@ -235,13 +287,14 @@ namespace ServiceLib.Services
UpdateFunc(it.IndexId, "", ResUI.Speedtesting);
var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
if (item is null) continue;
if (item is null)
continue;
WebProxy webProxy = new(Global.Loopback, it.Port);
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
await downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
{
decimal.TryParse(msg, out decimal dec);
decimal.TryParse(msg, out var dec);
if (dec > 0)
{
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg);
@@ -252,28 +305,27 @@ namespace ServiceLib.Services
if (pid > 0)
{
CoreHandler.Instance.CoreStopPid(pid);
await ProcUtils.ProcessKill(pid);
}
UpdateFunc("", ResUI.SpeedtestingCompleted);
await ProfileExHandler.Instance.SaveTo();
return true;
}
private async Task RunSpeedTestMulti()
private async Task<bool> RunSpeedTestMulti(List<ServerTestItem> selecteds)
{
int pid = -1;
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(_selecteds);
var pid = -1;
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
if (pid < 0)
{
UpdateFunc("", ResUI.FailedToRunCore);
return;
return false;
}
string url = _config.SpeedTestItem.SpeedTestUrl;
var url = _config.SpeedTestItem.SpeedTestUrl;
var timeout = _config.SpeedTestItem.SpeedTestTimeout;
DownloadService downloadHandle = new();
foreach (var it in _selecteds)
foreach (var it in selecteds)
{
if (_exitLoop)
{
@@ -298,12 +350,13 @@ namespace ServiceLib.Services
UpdateFunc(it.IndexId, "", ResUI.Speedtesting);
var item = await AppHandler.Instance.GetProfileItem(it.IndexId);
if (item is null) continue;
if (item is null)
continue;
WebProxy webProxy = new(Global.Loopback, it.Port);
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
{
decimal.TryParse(msg, out decimal dec);
decimal.TryParse(msg, out var dec);
if (dec > 0)
{
ProfileExHandler.Instance.SetTestSpeed(it.IndexId, msg);
@@ -317,38 +370,46 @@ namespace ServiceLib.Services
if (pid > 0)
{
CoreHandler.Instance.CoreStopPid(pid);
await ProcUtils.ProcessKill(pid);
}
UpdateFunc("", ResUI.SpeedtestingCompleted);
await ProfileExHandler.Instance.SaveTo();
return true;
}
private async Task RunMixedtestAsync()
private async Task<bool> RunMixedTestAsync(List<ServerTestItem> selecteds)
{
await RunRealPing();
var ret = await RunRealPingAsync(selecteds);
if (ret == false)
{
return false;
}
await Task.Delay(1000);
await RunSpeedTestMulti();
var ret2 = await RunSpeedTestMulti(selecteds);
if (ret2 == false)
{
return false;
}
return true;
}
private async Task<string> GetRealPingTime(DownloadService downloadHandle, IWebProxy webProxy)
{
int responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
//string output = Utile.IsNullOrEmpty(status) ? FormatOut(responseTime, "ms") : status;
var responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
return FormatOut(responseTime, Global.DelayUnit);
}
private async Task<int> GetTcpingTime(string url, int port)
{
int responseTime = -1;
var responseTime = -1;
try
{
if (!IPAddress.TryParse(url, out IPAddress? ipAddress))
if (!IPAddress.TryParse(url, out var ipAddress))
{
IPHostEntry ipHostInfo = Dns.GetHostEntry(url);
ipAddress = ipHostInfo.AddressList[0];
var ipHostInfo = await Dns.GetHostEntryAsync(url);
ipAddress = ipHostInfo.AddressList.First();
}
var timer = Stopwatch.StartNew();
@@ -366,7 +427,7 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
return responseTime;
}
@@ -381,4 +442,4 @@ namespace ServiceLib.Services
_updateFunc?.Invoke(new() { IndexId = indexId, Delay = delay, Speed = speed });
}
}
}
}

View File

@@ -1,4 +1,4 @@
using System.Net.WebSockets;
using System.Net.WebSockets;
using System.Text;
namespace ServiceLib.Services.Statistics
@@ -8,8 +8,9 @@ namespace ServiceLib.Services.Statistics
private Config _config;
private bool _exitFlag;
private ClientWebSocket? webSocket;
private string url = string.Empty;
private Action<ServerSpeedItem>? _updateFunc;
private string Url => $"ws://{Global.Loopback}:{AppHandler.Instance.StatePort2}/traffic";
private static readonly string _tag = "StatisticsSingboxService";
public StatisticsSingboxService(Config config, Action<ServerSpeedItem> updateFunc)
{
@@ -26,12 +27,10 @@ namespace ServiceLib.Services.Statistics
try
{
url = $"ws://{Global.Loopback}:{AppHandler.Instance.StatePort2}/traffic";
if (webSocket == null)
{
webSocket = new ClientWebSocket();
await webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
await webSocket.ConnectAsync(new Uri(Url), CancellationToken.None);
}
}
catch { }
@@ -50,7 +49,7 @@ namespace ServiceLib.Services.Statistics
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
}
}
@@ -110,7 +109,8 @@ namespace ServiceLib.Services.Statistics
private void ParseOutput(string source, out ulong up, out ulong down)
{
up = 0; down = 0;
up = 0;
down = 0;
try
{
var trafficItem = JsonUtils.Deserialize<TrafficItem>(source);
@@ -125,4 +125,4 @@ namespace ServiceLib.Services.Statistics
}
}
}
}
}

View File

@@ -1,20 +1,19 @@
namespace ServiceLib.Services.Statistics
namespace ServiceLib.Services.Statistics
{
public class StatisticsXrayService
{
private const long linkBase = 1024;
private string _url;
private ServerSpeedItem _serverSpeedItem = new();
private Config _config;
private bool _exitFlag;
private Action<ServerSpeedItem>? _updateFunc;
private string Url => $"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort}/debug/vars";
public StatisticsXrayService(Config config, Action<ServerSpeedItem> updateFunc)
{
_config = config;
_updateFunc = updateFunc;
_exitFlag = false;
_url = $"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort}/debug/vars";
Task.Run(Run);
}
@@ -36,7 +35,7 @@
continue;
}
var result = await HttpClientHelper.Instance.TryGetAsync(_url);
var result = await HttpClientHelper.Instance.TryGetAsync(Url);
if (result != null)
{
var server = ParseOutput(result) ?? new ServerSpeedItem();
@@ -64,7 +63,8 @@
foreach (string key in source.stats.outbound.Keys)
{
var value = source.stats.outbound[key];
if (value == null) continue;
if (value == null)
continue;
var state = JsonUtils.Deserialize<V2rayMetricsVarsLink>(value.ToString());
if (key.StartsWith(Global.ProxyTag))
@@ -103,4 +103,4 @@
return null;
}
}
}
}

View File

@@ -7,6 +7,7 @@ namespace ServiceLib.Services
{
private Action<bool, string>? _updateFunc;
private int _timeout = 30;
private static readonly string _tag = "UpdateService";
public async Task CheckUpdateGuiN(Config config, Action<bool, string> updateFunc, bool preRelease)
{
@@ -242,7 +243,7 @@ namespace ServiceLib.Services
_updateFunc?.Invoke(true, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, "geo"));
}
public async Task RunAvailabilityCheck(Action<bool, string> updateFunc)
public async Task<string> RunAvailabilityCheck()
{
var downloadHandle = new DownloadService();
var time = await downloadHandle.RunAvailabilityCheck(null);
@@ -254,7 +255,7 @@ namespace ServiceLib.Services
ip = $"({ipInfo?.country_code}) {ipInfo?.ip}";
}
updateFunc?.Invoke(false, string.Format(ResUI.TestMeOutput, time, ip));
return string.Format(ResUI.TestMeOutput, time, ip);
}
#region CheckUpdate private
@@ -272,7 +273,7 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
_updateFunc?.Invoke(false, ex.Message);
return new RetResult(false, ex.Message);
}
@@ -356,7 +357,7 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
_updateFunc?.Invoke(false, ex.Message);
return new SemanticVersion("");
}
@@ -367,6 +368,7 @@ namespace ServiceLib.Services
try
{
var coreInfo = CoreInfoHandler.Instance.GetCoreInfo(type);
var coreUrl = await GetUrlFromCore(coreInfo) ?? string.Empty;
SemanticVersion curVersion;
string message;
string? url;
@@ -378,28 +380,28 @@ namespace ServiceLib.Services
{
curVersion = await GetCoreVersion(type);
message = string.Format(ResUI.IsLatestCore, type, curVersion.ToVersionString("v"));
url = string.Format(GetUrlFromCore(coreInfo), version.ToVersionString("v"));
url = string.Format(coreUrl, version.ToVersionString("v"));
break;
}
case ECoreType.mihomo:
{
curVersion = await GetCoreVersion(type);
message = string.Format(ResUI.IsLatestCore, type, curVersion);
url = string.Format(GetUrlFromCore(coreInfo), version.ToVersionString("v"));
url = string.Format(coreUrl, version.ToVersionString("v"));
break;
}
case ECoreType.sing_box:
{
curVersion = await GetCoreVersion(type);
message = string.Format(ResUI.IsLatestCore, type, curVersion.ToVersionString("v"));
url = string.Format(GetUrlFromCore(coreInfo), version.ToVersionString("v"), version);
url = string.Format(coreUrl, version.ToVersionString("v"), version);
break;
}
case ECoreType.v2rayN:
{
curVersion = new SemanticVersion(Utils.GetVersionInfo());
message = string.Format(ResUI.IsLatestN, type, curVersion);
url = string.Format(GetUrlFromCore(coreInfo), version);
url = string.Format(coreUrl, version);
break;
}
default:
@@ -415,23 +417,24 @@ namespace ServiceLib.Services
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
Logging.SaveLog(_tag, ex);
_updateFunc?.Invoke(false, ex.Message);
return new RetResult(false, ex.Message);
}
}
private string? GetUrlFromCore(CoreInfo? coreInfo)
private async Task<string?> GetUrlFromCore(CoreInfo? coreInfo)
{
if (Utils.IsWindows())
{
//Check for standalone windows .Net version
if (coreInfo?.CoreType == ECoreType.v2rayN
&& File.Exists(Path.Combine(Utils.StartupPath(), "wpfgfx_cor3.dll"))
&& File.Exists(Path.Combine(Utils.StartupPath(), "D3DCompiler_47_cor3.dll"))
)
if (coreInfo?.CoreType == ECoreType.v2rayN && RuntimeInformation.ProcessArchitecture == Architecture.X64)
{
return coreInfo?.DownloadUrlWin64?.Replace(".zip", "-SelfContained.zip");
var runtimes = await Utils.GetCliWrapOutput("dotnet", "--list-runtimes");
if (runtimes == null || runtimes.Contains("Microsoft.WindowsDesktop.App 8") == false)
{
return coreInfo?.DownloadUrlWin64?.Replace(".zip", "-SelfContained.zip");
}
}
return RuntimeInformation.ProcessArchitecture switch
@@ -585,4 +588,4 @@ namespace ServiceLib.Services
#endregion Geo private
}
}
}

View File

@@ -1,6 +1,6 @@
using System.Reactive;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System.Reactive;
namespace ServiceLib.ViewModels
{
@@ -25,6 +25,7 @@ namespace ServiceLib.ViewModels
BrowseServerCmd = ReactiveCommand.CreateFromTask(async () =>
{
_updateView?.Invoke(EViewAction.BrowseServer, null);
await Task.CompletedTask;
});
EditServerCmd = ReactiveCommand.CreateFromTask(async () =>
{
@@ -103,12 +104,13 @@ namespace ServiceLib.ViewModels
address = Utils.GetConfigPath(address);
if (File.Exists(address))
{
Utils.ProcessStart(address);
ProcUtils.ProcessStart(address);
}
else
{
NoticeHandler.Instance.Enqueue(ResUI.FailedReadConfiguration);
}
await Task.CompletedTask;
}
}
}
}

View File

@@ -1,6 +1,6 @@
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System.Reactive;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
namespace ServiceLib.ViewModels
{
@@ -94,4 +94,4 @@ namespace ServiceLib.ViewModels
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More