Compare commits
131 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4104964e38 | ||
|
|
3bbd1edf06 | ||
|
|
41cc260b5c | ||
|
|
6cd5063c9b | ||
|
|
e544df6d01 | ||
|
|
f952d2383c | ||
|
|
8a29e147d3 | ||
|
|
8a19128e7f | ||
|
|
7dc9fbd8ff | ||
|
|
31a179e647 | ||
|
|
c3fdfcc4bd | ||
|
|
7ea8fae2da | ||
|
|
67ffa810d3 | ||
|
|
ba2a636dd2 | ||
|
|
d471336994 | ||
|
|
7e6482fdff | ||
|
|
a8eba93ffd | ||
|
|
4ffe595db6 | ||
|
|
885587e551 | ||
|
|
e986dc189e | ||
|
|
bccab41c8f | ||
|
|
79a0538ca0 | ||
|
|
e6b27d17e4 | ||
|
|
2a0012824a | ||
|
|
9d92be99ee | ||
|
|
6914831d30 | ||
|
|
19d83be6de | ||
|
|
ce7303bd0d | ||
|
|
4c3318ac86 | ||
|
|
db25fdeee1 | ||
|
|
732c3eee8b | ||
|
|
2b0d805b2f | ||
|
|
4faa94b2a3 | ||
|
|
331d11aee2 | ||
|
|
4d95d7d8c0 | ||
|
|
fd82623c74 | ||
|
|
4a32b2c814 | ||
|
|
45264005a4 | ||
|
|
253219dd16 | ||
|
|
b2feaf3ba9 | ||
|
|
6c5011ad68 | ||
|
|
c0f8b6b84c | ||
|
|
f71125d8f3 | ||
|
|
e674a025d8 | ||
|
|
dadc24876f | ||
|
|
98d4801b7e | ||
|
|
0e50bfb6eb | ||
|
|
a5aa286535 | ||
|
|
3caf025c3c | ||
|
|
c943c6c60a | ||
|
|
8c55c629cd | ||
|
|
0c38ebb63f | ||
|
|
75df85f598 | ||
|
|
59e99b2316 | ||
|
|
02f4dcbaf7 | ||
|
|
470dec5588 | ||
|
|
be1e37ddd0 | ||
|
|
fdc32601a9 | ||
|
|
d3b86858e1 | ||
|
|
9c20d9cb1f | ||
|
|
d2cda16378 | ||
|
|
2ab00d5b6f | ||
|
|
1b8a58cd07 | ||
|
|
0c3293045f | ||
|
|
4c4ce7e8d1 | ||
|
|
a0d4a3f2e8 | ||
|
|
26abe7e7d7 | ||
|
|
b9c86ed3a1 | ||
|
|
b7cff66a80 | ||
|
|
61a40d2860 | ||
|
|
80eb569366 | ||
|
|
54fe669d89 | ||
|
|
0953237e9e | ||
|
|
cf1a8599eb | ||
|
|
171132be12 | ||
|
|
43c95422b7 | ||
|
|
2662243641 | ||
|
|
060a35e091 | ||
|
|
de1132c2df | ||
|
|
f19edc9370 | ||
|
|
f1601c463b | ||
|
|
77b15cd530 | ||
|
|
a6479fe0d0 | ||
|
|
4ad4e27dc1 | ||
|
|
7370684985 | ||
|
|
5ae58e6a98 | ||
|
|
780ccb1932 | ||
|
|
6b4076be10 | ||
|
|
d7a04a15ae | ||
|
|
2ae43f8bdb | ||
|
|
d3ebc17a10 | ||
|
|
7a8680711e | ||
|
|
649e89e7af | ||
|
|
cb94d64395 | ||
|
|
2440dc2440 | ||
|
|
364a24c580 | ||
|
|
8f3e0dbd82 | ||
|
|
596234df26 | ||
|
|
c38aec50dc | ||
|
|
40915b5f98 | ||
|
|
a176613119 | ||
|
|
6c6de1ae7f | ||
|
|
edbd168dcf | ||
|
|
127858d582 | ||
|
|
baf90cfbdd | ||
|
|
1a5eeb9401 | ||
|
|
e0ae101ff4 | ||
|
|
8b4a07dfe8 | ||
|
|
db934e70cb | ||
|
|
b770048f05 | ||
|
|
27c53be209 | ||
|
|
d93c12b354 | ||
|
|
98d4a47efb | ||
|
|
8ab04c65b5 | ||
|
|
1b2dab1388 | ||
|
|
4f8dae7fa0 | ||
|
|
cdc23e32c4 | ||
|
|
20457e9e63 | ||
|
|
e63042af84 | ||
|
|
c35b4d3c1b | ||
|
|
64a83a5d64 | ||
|
|
01039d0b47 | ||
|
|
7c1e5a3cba | ||
|
|
038161527f | ||
|
|
b12b7a17e6 | ||
|
|
37cf23d5fe | ||
|
|
ed7fb4f6e3 | ||
|
|
5d4bd2fee6 | ||
|
|
aae5906311 | ||
|
|
4a7bafd011 | ||
|
|
626ebfe65d |
170
.editorconfig
Normal file
170
.editorconfig
Normal 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
|
||||
0
v2rayN/.gitattributes → .gitattributes
vendored
0
v2rayN/.gitattributes → .gitattributes
vendored
9
.github/dependabot.yml
vendored
9
.github/dependabot.yml
vendored
@@ -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"
|
||||
|
||||
46
.github/workflows/build-linux.yml
vendored
46
.github/workflows/build-linux.yml
vendored
@@ -22,34 +22,39 @@ jobs:
|
||||
matrix:
|
||||
configuration: [Release]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
uses: actions/upload-artifact@v4.6.0
|
||||
with:
|
||||
name: v2rayN-linux
|
||||
path: |
|
||||
${{ github.workspace }}/v2rayN/Release/linux*
|
||||
|
||||
# release debian package
|
||||
- name: Package debian
|
||||
- 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 }}
|
||||
./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
|
||||
@@ -58,11 +63,28 @@ jobs:
|
||||
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: |
|
||||
run: |
|
||||
chmod 755 package-release-zip.sh
|
||||
./package-release-zip.sh $OutputArch $OutputPath64
|
||||
./package-release-zip.sh $OutputArchArm $OutputPathArm64
|
||||
|
||||
26
.github/workflows/build-osx.yml
vendored
26
.github/workflows/build-osx.yml
vendored
@@ -22,34 +22,39 @@ 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
|
||||
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
|
||||
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-macos
|
||||
path: |
|
||||
${{ github.workspace }}/v2rayN/Release/macos*
|
||||
|
||||
# release osx package
|
||||
- name: Package osx
|
||||
- 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 $OutputArch $OutputPath64 ${{ github.event.inputs.release_tag }}
|
||||
./package-osx.sh $OutputArchArm $OutputPathArm64 ${{ github.event.inputs.release_tag }}
|
||||
|
||||
- name: Upload dmg to release
|
||||
@@ -59,11 +64,12 @@ jobs:
|
||||
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: |
|
||||
run: |
|
||||
chmod 755 package-release-zip.sh
|
||||
./package-release-zip.sh $OutputArch $OutputPath64
|
||||
./package-release-zip.sh $OutputArchArm $OutputPathArm64
|
||||
|
||||
50
.github/workflows/build-windows-desktop.yml
vendored
Normal file
50
.github/workflows/build-windows-desktop.yml
vendored
Normal 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*
|
||||
|
||||
29
.github/workflows/build-windows.yml
vendored
29
.github/workflows/build-windows.yml
vendored
@@ -23,40 +23,43 @@ jobs:
|
||||
matrix:
|
||||
configuration: [Release]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-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
|
||||
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
|
||||
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
|
||||
uses: actions/upload-artifact@v4.6.0
|
||||
with:
|
||||
name: v2rayN-windows
|
||||
path: |
|
||||
${{ github.workspace }}/v2rayN/Release/windows*
|
||||
${{ github.workspace }}/v2rayN/Release/windows*
|
||||
|
||||
# release zip archive
|
||||
- name: Package release zip archive
|
||||
if: github.event.inputs.release_tag != ''
|
||||
run: |
|
||||
run: |
|
||||
chmod 755 package-release-zip.sh
|
||||
./package-release-zip.sh $OutputArch $OutputPath64
|
||||
./package-release-zip.sh "windows-64-With-Core" $OutputPath64
|
||||
./package-release-zip.sh $OutputArchArm $OutputPathArm64
|
||||
./package-release-zip.sh "windows-64-SelfContained" $OutputPath64Sc
|
||||
./package-release-zip.sh "windows-64-SelfContained-With-Core" $OutputPath64Sc
|
||||
|
||||
- name: Upload zip archive to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
|
||||
2
.github/workflows/winget-publish.yml
vendored
2
.github/workflows/winget-publish.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
$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-With-Core\.zip*' | Select -ExpandProperty browser_download_url
|
||||
$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
|
||||
|
||||
|
||||
415
.gitignore
vendored
415
.gitignore
vendored
@@ -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
|
||||
22
README.md
22
README.md
@@ -1,5 +1,5 @@
|
||||
# v2rayN
|
||||
A GUI client for Windows, Linux and macOS, support [Xray core](https://github.com/XTLS/Xray-core) and [sing-box-core](https://github.com/SagerNet/sing-box/releases) 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)
|
||||
|
||||
|
||||
[](https://github.com/2dust/v2rayN/commits/master)
|
||||
@@ -9,26 +9,8 @@ A GUI client for Windows, Linux and macOS, support [Xray core](https://github.co
|
||||
|
||||
|
||||
## 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` under user permissions
|
||||
```
|
||||
Debian 9+
|
||||
Ubuntu 16.04+
|
||||
Fedora 30+
|
||||
```
|
||||
### macOS
|
||||
- `chmod +x v2rayN` Run `./v2rayN` under user permissions
|
||||
```
|
||||
macOS 10.14+
|
||||
```
|
||||
|
||||
## 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)
|
||||
|
||||
112
package-appimage.sh
Normal file
112
package-appimage.sh
Normal file
@@ -0,0 +1,112 @@
|
||||
#!/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"
|
||||
Interpreter="ld-linux-x86-64.so.2"
|
||||
else
|
||||
Arch2="aarch64"
|
||||
Arch3="arm64"
|
||||
Interpreter="ld-linux-aarch64.so.1"
|
||||
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}"
|
||||
cd "\${HERE}/opt/v2rayN"
|
||||
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}
|
||||
sudo apt update
|
||||
mkdir deb_folder
|
||||
cd deb_folder
|
||||
apt download libstdc++6:${Arch3}
|
||||
apt download libc6:${Arch3}
|
||||
apt download libcrypt1:${Arch3}
|
||||
apt download libgcc-s1:${Arch3}
|
||||
apt download libidn2-0:${Arch3}
|
||||
apt download gcc-12-base:${Arch3}
|
||||
apt download zlib1g:${Arch3}
|
||||
apt download libfreetype6:${Arch3}
|
||||
apt download libexpat1:${Arch3}
|
||||
apt download libbrotli1:${Arch3}
|
||||
apt download libx11-6:${Arch3}
|
||||
apt download libx11-xcb1:${Arch3}
|
||||
apt download libxcb1:${Arch3}
|
||||
apt download libxau6:${Arch3}
|
||||
apt download libxdmcp6:${Arch3}
|
||||
apt download libbsd0:${Arch3}
|
||||
apt download libmd0:${Arch3}
|
||||
apt download libice6:${Arch3}
|
||||
apt download libsm6:${Arch3}
|
||||
apt download libuuid1:${Arch3}
|
||||
apt download libxrandr2:${Arch3}
|
||||
apt download libxext6:${Arch3}
|
||||
apt download libxrender1:${Arch3}
|
||||
apt download libxi6:${Arch3}
|
||||
apt download libsm6:${Arch3}
|
||||
apt download libxcursor1:${Arch3}
|
||||
apt download libxfixes3:${Arch3}
|
||||
apt download libpng16-16:${Arch3} || true
|
||||
apt download libpng16-16t64:${Arch3} || true
|
||||
apt download libicu66:${Arch3} || true
|
||||
apt download libicu70:${Arch3} || true
|
||||
apt download libicu74:${Arch3} || true
|
||||
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"
|
||||
|
||||
sudo apt install -y patchelf
|
||||
|
||||
pushd "${PackagePath}/AppDir/opt/v2rayN"
|
||||
patchelf --set-interpreter ${Interpreter} v2rayN
|
||||
popd
|
||||
|
||||
# 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"
|
||||
@@ -4,6 +4,11 @@ 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"
|
||||
|
||||
@@ -4,25 +4,18 @@ 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"
|
||||
|
||||
mkdir -p "$PackagePath/icons.iconset"
|
||||
sips -z 16 16 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_16x16.png"
|
||||
sips -z 32 32 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_16x16@2x.png"
|
||||
sips -z 32 32 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_32x32.png"
|
||||
sips -z 64 64 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_32x32@2x.png"
|
||||
sips -z 128 128 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_128x128.png"
|
||||
sips -z 256 256 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_128x128@2x.png"
|
||||
sips -z 256 256 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_256x256.png"
|
||||
sips -z 512 512 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_256x256@2x.png"
|
||||
sips -z 512 512 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_512x512.png"
|
||||
sips -z 1024 1024 "$PackagePath/v2rayN.app/Contents/MacOS/v2rayN2.png" --out "$PackagePath/icons.iconset/icon_512x512@2x.png"
|
||||
iconutil -c icns "$PackagePath/icons.iconset" -o "$PackagePath/v2rayN.app/Contents/Resources/AppIcon.icns"
|
||||
|
||||
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">
|
||||
|
||||
363
v2rayN/.gitignore
vendored
363
v2rayN/.gitignore
vendored
@@ -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
|
||||
@@ -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.1</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>
|
||||
@@ -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(3);
|
||||
Utils.Waiting(5);
|
||||
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
@@ -42,12 +42,12 @@ namespace AmazTool
|
||||
StringBuilder sb = new();
|
||||
try
|
||||
{
|
||||
string thisAppOldFile = $"{Utils.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(Utils.GetExePath(), Utils.GetPath(fullName), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
File.Move(Utils.GetExePath(), thisAppOldFile);
|
||||
}
|
||||
|
||||
string entryOutputPath = Utils.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,18 +97,9 @@ namespace AmazTool
|
||||
}
|
||||
|
||||
Console.WriteLine(Resx.Resource.Restartv2rayN);
|
||||
Waiting(2);
|
||||
Utils.Waiting(2);
|
||||
|
||||
Utils.StartV2RayN();
|
||||
}
|
||||
|
||||
public static void Waiting(int second)
|
||||
{
|
||||
for (var i = second; i > 0; i--)
|
||||
{
|
||||
Console.WriteLine(i);
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,5 +39,14 @@ namespace AmazTool
|
||||
};
|
||||
process.Start();
|
||||
}
|
||||
|
||||
public static void Waiting(int second)
|
||||
{
|
||||
for (var i = second; i > 0; i--)
|
||||
{
|
||||
Console.WriteLine(i);
|
||||
Thread.Sleep(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
v2rayN/Directory.Build.props
Normal file
32
v2rayN/Directory.Build.props
Normal file
@@ -0,0 +1,32 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>7.8.3</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>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
30
v2rayN/Directory.Packages.props
Normal file
30
v2rayN/Directory.Packages.props
Normal 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>
|
||||
@@ -1,5 +1,5 @@
|
||||
using Downloader;
|
||||
using System.Net;
|
||||
using Downloader;
|
||||
|
||||
namespace ServiceLib.Common
|
||||
{
|
||||
@@ -181,4 +181,4 @@ namespace ServiceLib.Common
|
||||
downloadOpt = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
61
v2rayN/ServiceLib/Common/EmbedUtils.cs
Normal file
61
v2rayN/ServiceLib/Common/EmbedUtils.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -156,7 +156,7 @@ namespace ServiceLib.Common
|
||||
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);
|
||||
@@ -183,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
|
||||
@@ -192,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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,30 @@ namespace ServiceLib.Common
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SerializeToNode
|
||||
/// </summary>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,21 +19,23 @@ public static class ProcUtils
|
||||
}
|
||||
try
|
||||
{
|
||||
if (fileName.Contains(' ')) fileName = fileName.AppendQuotes();
|
||||
if (arguments.Contains(' ')) arguments = arguments.AppendQuotes();
|
||||
if (fileName.Contains(' '))
|
||||
fileName = fileName.AppendQuotes();
|
||||
if (arguments.Contains(' '))
|
||||
arguments = arguments.AppendQuotes();
|
||||
|
||||
Process process = new()
|
||||
Process proc = new()
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
UseShellExecute = true,
|
||||
FileName = fileName,
|
||||
Arguments = arguments,
|
||||
WorkingDirectory = dir
|
||||
WorkingDirectory = dir ?? string.Empty
|
||||
}
|
||||
};
|
||||
process.Start();
|
||||
return process.Id;
|
||||
proc.Start();
|
||||
return dir is null ? null : proc.Id;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -81,25 +83,68 @@ public static class ProcUtils
|
||||
return;
|
||||
}
|
||||
|
||||
var fileName = review ? proc?.MainModule?.FileName : null;
|
||||
var processName = review ? proc?.ProcessName : null;
|
||||
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); }
|
||||
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);
|
||||
if (review && fileName != null)
|
||||
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
|
||||
{
|
||||
var proc2 = Process.GetProcessesByName(processName)
|
||||
.FirstOrDefault(t => t.MainModule?.FileName == fileName);
|
||||
if (proc2 != null)
|
||||
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
|
||||
{
|
||||
Logging.SaveLog($"{_tag}, KillProcess not completing the job");
|
||||
await ProcessKill(proc2, false);
|
||||
proc2 = null;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using SQLite;
|
||||
using System.Collections;
|
||||
using SQLite;
|
||||
|
||||
namespace ServiceLib.Common
|
||||
{
|
||||
@@ -88,4 +88,4 @@ namespace ServiceLib.Common
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace ServiceLib.Common
|
||||
{
|
||||
@@ -21,7 +21,8 @@ namespace ServiceLib.Common
|
||||
|
||||
public static bool BeginWithAny(this string s, IEnumerable<char> chars)
|
||||
{
|
||||
if (s.IsNullOrEmpty()) return false;
|
||||
if (s.IsNullOrEmpty())
|
||||
return false;
|
||||
return chars.Contains(s.First());
|
||||
}
|
||||
|
||||
@@ -34,7 +35,8 @@ namespace ServiceLib.Common
|
||||
{
|
||||
while (reader.ReadLine() is { } line)
|
||||
{
|
||||
if (line.IsWhiteSpace()) continue;
|
||||
if (line.IsWhiteSpace())
|
||||
continue;
|
||||
yield return line;
|
||||
}
|
||||
}
|
||||
@@ -69,4 +71,4 @@ namespace ServiceLib.Common
|
||||
return string.IsNullOrEmpty(value) ? string.Empty : $"\"{value}\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using CliWrap;
|
||||
using CliWrap.Buffered;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
@@ -10,6 +8,8 @@ using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using CliWrap;
|
||||
using CliWrap.Buffered;
|
||||
|
||||
namespace ServiceLib.Common
|
||||
{
|
||||
@@ -17,56 +17,6 @@ namespace ServiceLib.Common
|
||||
{
|
||||
private static readonly string _tag = "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(_tag, 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(_tag, ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion 资源操作
|
||||
|
||||
#region 转换函数
|
||||
|
||||
/// <summary>
|
||||
@@ -176,7 +126,8 @@ namespace ServiceLib.Common
|
||||
{
|
||||
try
|
||||
{
|
||||
if (plainText.IsNullOrEmpty()) return "";
|
||||
if (plainText.IsNullOrEmpty())
|
||||
return "";
|
||||
plainText = plainText.Trim()
|
||||
.Replace(Environment.NewLine, "")
|
||||
.Replace("\n", "")
|
||||
@@ -372,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 _);
|
||||
}
|
||||
@@ -462,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;
|
||||
@@ -519,7 +474,7 @@ namespace ServiceLib.Common
|
||||
|
||||
public static bool UpgradeAppExists(out string upgradeFileName)
|
||||
{
|
||||
upgradeFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, GetExeName("AmazTool"));
|
||||
upgradeFileName = Path.Combine(GetBaseDirectory(), GetExeName("AmazTool"));
|
||||
return File.Exists(upgradeFileName);
|
||||
}
|
||||
|
||||
@@ -558,7 +513,7 @@ namespace ServiceLib.Common
|
||||
|
||||
public static string GetRuntimeInfo()
|
||||
{
|
||||
return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion} | {(Environment.Is64BitOperatingSystem ? 64 : 32)}";
|
||||
return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -604,9 +559,11 @@ 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;
|
||||
if (hostItem.Length != 2)
|
||||
continue;
|
||||
systemHosts.Add(hostItem.Last(), hostItem.First());
|
||||
}
|
||||
}
|
||||
@@ -666,12 +623,12 @@ namespace ServiceLib.Common
|
||||
try
|
||||
{
|
||||
//When this file exists, it is equivalent to having no permission to read and write
|
||||
if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "NotStoreConfigHere.txt")))
|
||||
if (File.Exists(Path.Combine(GetBaseDirectory(), "NotStoreConfigHere.txt")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var tempPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "guiTemps");
|
||||
var tempPath = Path.Combine(GetBaseDirectory(), "guiTemps");
|
||||
if (!Directory.Exists(tempPath))
|
||||
{
|
||||
Directory.CreateDirectory(tempPath);
|
||||
@@ -699,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;
|
||||
@@ -706,12 +668,12 @@ namespace ServiceLib.Common
|
||||
|
||||
public static string StartupPath()
|
||||
{
|
||||
if (Utils.IsNonWindows() && Environment.GetEnvironmentVariable("V2RAYN_LOCAL_APPLICATION_DATA") == "1")
|
||||
if (Environment.GetEnvironmentVariable(Global.LocalAppData) == "1")
|
||||
{
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "v2rayN");
|
||||
}
|
||||
|
||||
return AppDomain.CurrentDomain.BaseDirectory;
|
||||
return GetBaseDirectory();
|
||||
}
|
||||
|
||||
public static string GetTempPath(string filename = "")
|
||||
@@ -870,8 +832,10 @@ namespace ServiceLib.Common
|
||||
|
||||
public static async Task<string?> SetLinuxChmod(string? fileName)
|
||||
{
|
||||
if (fileName.IsNullOrEmpty()) return null;
|
||||
if (fileName.Contains(' ')) fileName = fileName.AppendQuotes();
|
||||
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);
|
||||
@@ -899,4 +863,4 @@ namespace ServiceLib.Common
|
||||
|
||||
#endregion Platform
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +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;
|
||||
@@ -49,5 +52,23 @@ namespace ServiceLib.Common
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace ServiceLib.Enums
|
||||
namespace ServiceLib.Enums
|
||||
{
|
||||
public enum ECoreType
|
||||
{
|
||||
@@ -12,6 +12,8 @@
|
||||
sing_box = 24,
|
||||
juicity = 25,
|
||||
hysteria2 = 26,
|
||||
brook = 27,
|
||||
overtls = 28,
|
||||
v2rayN = 99
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace ServiceLib.Enums
|
||||
namespace ServiceLib.Enums
|
||||
{
|
||||
public enum EMsgCommand
|
||||
{
|
||||
@@ -6,7 +6,6 @@
|
||||
SendMsgView,
|
||||
SendSnackMsg,
|
||||
RefreshProfiles,
|
||||
StopSpeedtest,
|
||||
AppExit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
13
v2rayN/ServiceLib/Enums/ETheme.cs
Normal file
13
v2rayN/ServiceLib/Enums/ETheme.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace ServiceLib.Enums
|
||||
{
|
||||
public enum ETheme
|
||||
{
|
||||
FollowSystem,
|
||||
Dark,
|
||||
Light,
|
||||
Aquatic,
|
||||
Desert,
|
||||
Dusk,
|
||||
NightSky
|
||||
}
|
||||
}
|
||||
@@ -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,13 +53,13 @@
|
||||
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 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 SystemProxyExceptionsLinux = "localhost,127.0.0.0/8,::1";
|
||||
public const string RoutingRuleComma = "<COMMA>";
|
||||
public const string GrpcGunMode = "gun";
|
||||
public const string GrpcMultiMode = "multi";
|
||||
@@ -79,71 +69,83 @@
|
||||
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",
|
||||
};
|
||||
@"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",
|
||||
};
|
||||
@"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",
|
||||
};
|
||||
@"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/",
|
||||
};
|
||||
@"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/"
|
||||
];
|
||||
|
||||
public static readonly Dictionary<string, string> UserAgentTexts = new()
|
||||
{
|
||||
@@ -158,66 +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() { "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", "stream-one" };
|
||||
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", "hu" };
|
||||
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", "socks2", "socks3" };
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,9 +46,9 @@
|
||||
|
||||
public bool InitApp()
|
||||
{
|
||||
if (Utils.IsNonWindows() && Utils.HasWritePermission() == false)
|
||||
if (Utils.HasWritePermission() == false)
|
||||
{
|
||||
Environment.SetEnvironmentVariable("V2RAYN_LOCAL_APPLICATION_DATA", "1", EnvironmentVariableTarget.Process);
|
||||
Environment.SetEnvironmentVariable(Global.LocalAppData, "1", EnvironmentVariableTarget.Process);
|
||||
}
|
||||
|
||||
Logging.Setup();
|
||||
@@ -79,7 +79,8 @@
|
||||
{
|
||||
Logging.SaveLog($"v2rayN start up | {Utils.GetRuntimeInfo()}");
|
||||
Logging.LoggingEnabled(_config.GuiItem.EnableLog);
|
||||
Logging.ClearLogs();
|
||||
|
||||
ClearExpiredFiles();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -91,6 +92,15 @@
|
||||
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
|
||||
@@ -106,7 +116,13 @@
|
||||
if (Utils.IsWindows())
|
||||
{
|
||||
_processJob ??= new();
|
||||
_processJob?.AddProcess(processHandle);
|
||||
try
|
||||
{
|
||||
_processJob?.AddProcess(processHandle);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,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);
|
||||
}
|
||||
@@ -164,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))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Security.Principal;
|
||||
using System.Security.Principal;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ServiceLib.Handler
|
||||
@@ -29,7 +29,12 @@ namespace ServiceLib.Handler
|
||||
}
|
||||
else if (Utils.IsOSX())
|
||||
{
|
||||
//TODO
|
||||
await ClearTaskOSX();
|
||||
|
||||
if (config.GuiItem.AutoRun)
|
||||
{
|
||||
await SetTaskOSX();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -45,6 +50,8 @@ namespace ServiceLib.Handler
|
||||
{
|
||||
AutoStartTaskService(autoRunName, "", "");
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static async Task SetTaskWindows()
|
||||
@@ -66,6 +73,7 @@ namespace ServiceLib.Handler
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -127,13 +135,14 @@ namespace ServiceLib.Handler
|
||||
{
|
||||
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());
|
||||
@@ -157,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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using static ServiceLib.Models.ClashProxies;
|
||||
using static ServiceLib.Models.ClashProxies;
|
||||
|
||||
namespace ServiceLib.Handler
|
||||
{
|
||||
@@ -38,63 +38,63 @@ namespace ServiceLib.Handler
|
||||
public void ClashProxiesDelayTest(bool blAll, List<ClashProxyModel> lstProxy, Action<ClashProxyModel?, string> updateFunc)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
if (blAll)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
if (blAll)
|
||||
{
|
||||
if (_proxies != null)
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
break;
|
||||
if (_proxies != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Task.Delay(5000).Wait();
|
||||
}
|
||||
if (_proxies == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lstProxy = new List<ClashProxyModel>();
|
||||
foreach (KeyValuePair<string, ProxiesItem> kv in _proxies)
|
||||
{
|
||||
if (Global.notAllowTestType.Contains(kv.Value.type.ToLower()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
lstProxy.Add(new ClashProxyModel()
|
||||
{
|
||||
Name = kv.Value.name,
|
||||
Type = kv.Value.type.ToLower(),
|
||||
});
|
||||
}
|
||||
Task.Delay(5000).Wait();
|
||||
}
|
||||
if (_proxies == null)
|
||||
|
||||
if (lstProxy == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lstProxy = new List<ClashProxyModel>();
|
||||
foreach (KeyValuePair<string, ProxiesItem> kv in _proxies)
|
||||
var urlBase = $"{GetApiUrl()}/proxies";
|
||||
urlBase += @"/{0}/delay?timeout=10000&url=" + AppHandler.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
|
||||
|
||||
var tasks = new List<Task>();
|
||||
foreach (var it in lstProxy)
|
||||
{
|
||||
if (Global.notAllowTestType.Contains(kv.Value.type.ToLower()))
|
||||
if (Global.notAllowTestType.Contains(it.Type.ToLower()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
lstProxy.Add(new ClashProxyModel()
|
||||
var name = it.Name;
|
||||
var url = string.Format(urlBase, name);
|
||||
tasks.Add(Task.Run(async () =>
|
||||
{
|
||||
Name = kv.Value.name,
|
||||
Type = kv.Value.type.ToLower(),
|
||||
});
|
||||
var result = await HttpClientHelper.Instance.TryGetAsync(url);
|
||||
updateFunc?.Invoke(it, result);
|
||||
}));
|
||||
}
|
||||
}
|
||||
Task.WaitAll(tasks.ToArray());
|
||||
|
||||
if (lstProxy == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var urlBase = $"{GetApiUrl()}/proxies";
|
||||
urlBase += @"/{0}/delay?timeout=10000&url=" + AppHandler.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
|
||||
|
||||
List<Task> tasks = new List<Task>();
|
||||
foreach (var it in lstProxy)
|
||||
{
|
||||
if (Global.notAllowTestType.Contains(it.Type.ToLower()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var name = it.Name;
|
||||
var url = string.Format(urlBase, name);
|
||||
tasks.Add(Task.Run(async () =>
|
||||
{
|
||||
var result = await HttpClientHelper.Instance.TryGetAsync(url);
|
||||
updateFunc?.Invoke(it, result);
|
||||
}));
|
||||
}
|
||||
Task.WaitAll(tasks.ToArray());
|
||||
|
||||
Task.Delay(1000).Wait();
|
||||
updateFunc?.Invoke(null, "");
|
||||
});
|
||||
Task.Delay(1000).Wait();
|
||||
updateFunc?.Invoke(null, "");
|
||||
});
|
||||
}
|
||||
|
||||
public List<ProxiesItem>? GetClashProxyGroups()
|
||||
@@ -120,7 +120,7 @@ namespace ServiceLib.Handler
|
||||
try
|
||||
{
|
||||
var url = $"{GetApiUrl()}/proxies/{name}";
|
||||
Dictionary<string, string> headers = new Dictionary<string, string>();
|
||||
var headers = new Dictionary<string, string>();
|
||||
headers.Add("name", nameNode);
|
||||
await HttpClientHelper.Instance.PutAsync(url, headers);
|
||||
}
|
||||
@@ -148,7 +148,7 @@ namespace ServiceLib.Handler
|
||||
try
|
||||
{
|
||||
var url = $"{GetApiUrl()}/configs?force=true";
|
||||
Dictionary<string, string> headers = new Dictionary<string, string>();
|
||||
var headers = new Dictionary<string, string>();
|
||||
headers.Add("path", filePath);
|
||||
await HttpClientHelper.Instance.PutAsync(url, headers);
|
||||
}
|
||||
@@ -194,4 +194,4 @@ namespace ServiceLib.Handler
|
||||
return $"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort2}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -94,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()
|
||||
@@ -108,14 +105,9 @@ namespace ServiceLib.Handler
|
||||
|
||||
if (Utils.IsNullOrEmpty(config.UiItem.CurrentLanguage))
|
||||
{
|
||||
if (Thread.CurrentThread.CurrentCulture.Name.Equals("zh-cn", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
config.UiItem.CurrentLanguage = Global.Languages.First();
|
||||
}
|
||||
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();
|
||||
@@ -156,12 +148,13 @@ namespace ServiceLib.Handler
|
||||
config.SystemProxyItem ??= new();
|
||||
config.WebDavItem ??= new();
|
||||
config.CheckUpdateItem ??= new();
|
||||
|
||||
if (Utils.IsNotEmpty(config.ConstItem.DefIEProxyExceptions))
|
||||
config.Fragment4RayItem ??= new()
|
||||
{
|
||||
config.SystemProxyItem.SystemProxyExceptions = $"{config.ConstItem.DefIEProxyExceptions};{config.SystemProxyItem.SystemProxyExceptions}";
|
||||
config.ConstItem.DefIEProxyExceptions = string.Empty;
|
||||
}
|
||||
Packets = "tlshello",
|
||||
Length = "100-200",
|
||||
Interval = "10-20"
|
||||
};
|
||||
|
||||
if (config.SystemProxyItem.SystemProxyExceptions.IsNullOrEmpty())
|
||||
{
|
||||
config.SystemProxyItem.SystemProxyExceptions = Utils.IsWindows() ? Global.SystemProxyExceptionsWindows : Global.SystemProxyExceptionsLinux;
|
||||
@@ -471,7 +464,7 @@ namespace ServiceLib.Handler
|
||||
}
|
||||
|
||||
ProfileExHandler.Instance.SetSort(lstProfile[index].IndexId, sort);
|
||||
return 0;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -875,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)
|
||||
{
|
||||
@@ -1049,7 +1043,7 @@ namespace ServiceLib.Handler
|
||||
Port = node.PreSocksPort.Value,
|
||||
};
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
return itemSocks;
|
||||
}
|
||||
|
||||
@@ -1365,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))
|
||||
{
|
||||
@@ -1619,7 +1614,7 @@ namespace ServiceLib.Handler
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
public static async Task<int> SetDefaultRouting(Config config, RoutingItem routingItem)
|
||||
@@ -1735,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()
|
||||
@@ -1744,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()
|
||||
@@ -1753,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)
|
||||
{
|
||||
@@ -1870,7 +1865,7 @@ namespace ServiceLib.Handler
|
||||
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];
|
||||
@@ -1887,4 +1882,4 @@ namespace ServiceLib.Handler
|
||||
|
||||
#endregion Regional Presets
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using YamlDotNet.Core.Tokens;
|
||||
|
||||
namespace ServiceLib.Handler
|
||||
namespace ServiceLib.Handler
|
||||
{
|
||||
/// <summary>
|
||||
/// Core configuration file processing class
|
||||
@@ -82,7 +80,7 @@ namespace ServiceLib.Handler
|
||||
|
||||
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||
ret.Success = true;
|
||||
return ret;
|
||||
return await Task.FromResult(ret);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace ServiceLib.Handler
|
||||
@@ -22,8 +22,19 @@ namespace ServiceLib.Handler
|
||||
_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);
|
||||
|
||||
//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())
|
||||
{
|
||||
@@ -67,13 +78,24 @@ namespace ServiceLib.Handler
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateFunc(true, $"{node.GetSummary()}");
|
||||
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)
|
||||
@@ -203,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,
|
||||
@@ -220,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;
|
||||
if (Utils.IsNullOrEmpty(e.Data))
|
||||
return;
|
||||
UpdateFunc(false, e.Data + Environment.NewLine);
|
||||
};
|
||||
proc.ErrorDataReceived += (sender, e) =>
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(e.Data)) return;
|
||||
if (Utils.IsNullOrEmpty(e.Data))
|
||||
return;
|
||||
UpdateFunc(false, e.Data + Environment.NewLine);
|
||||
|
||||
if (!startUpSuccessful)
|
||||
{
|
||||
startUpErrorMessage.Append(e.Data + Environment.NewLine);
|
||||
}
|
||||
};
|
||||
}
|
||||
proc.Start();
|
||||
@@ -250,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)
|
||||
{
|
||||
@@ -258,23 +276,18 @@ 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(_tag, ex);
|
||||
UpdateFunc(true, ex.Message);
|
||||
UpdateFunc(mayNeedSudo, ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -365,4 +378,4 @@ namespace ServiceLib.Handler
|
||||
|
||||
#endregion Linux
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace ServiceLib.Handler
|
||||
namespace ServiceLib.Handler
|
||||
{
|
||||
public sealed class CoreInfoHandler
|
||||
{
|
||||
@@ -44,7 +44,7 @@
|
||||
}
|
||||
if (fileName.IsNullOrEmpty())
|
||||
{
|
||||
msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.CoreType.ToString()), string.Join(", ", coreInfo.CoreExes.ToArray()), coreInfo.Url);
|
||||
msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo?.CoreType.ToString()), coreInfo?.CoreExes?.LastOrDefault(), coreInfo?.Url);
|
||||
Logging.SaveLog(msg);
|
||||
}
|
||||
return fileName;
|
||||
@@ -52,149 +52,167 @@
|
||||
|
||||
private void InitCoreInfo()
|
||||
{
|
||||
_coreInfo = [];
|
||||
var urlN = GetCoreUrl(ECoreType.v2rayN);
|
||||
var urlXray = GetCoreUrl(ECoreType.Xray);
|
||||
var urlMihomo = GetCoreUrl(ECoreType.mihomo);
|
||||
var urlSingbox = GetCoreUrl(ECoreType.sing_box);
|
||||
|
||||
_coreInfo.Add(new CoreInfo
|
||||
{
|
||||
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 =
|
||||
[
|
||||
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",
|
||||
},
|
||||
|
||||
_coreInfo.Add(new CoreInfo
|
||||
{
|
||||
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,
|
||||
});
|
||||
new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.v2fly,
|
||||
CoreExes = ["v2ray"],
|
||||
Arguments = "{0}",
|
||||
Url = GetCoreUrl(ECoreType.v2fly),
|
||||
Match = "V2Ray",
|
||||
VersionArg = "-version",
|
||||
},
|
||||
|
||||
_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,
|
||||
});
|
||||
new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.v2fly_v5,
|
||||
CoreExes = ["v2ray"],
|
||||
Arguments = "run -c {0} -format jsonv5",
|
||||
Url = GetCoreUrl(ECoreType.v2fly_v5),
|
||||
Match = "V2Ray",
|
||||
VersionArg = "version",
|
||||
},
|
||||
|
||||
_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,
|
||||
});
|
||||
new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.Xray,
|
||||
CoreExes = ["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",
|
||||
},
|
||||
|
||||
_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,
|
||||
});
|
||||
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",
|
||||
},
|
||||
|
||||
_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,
|
||||
});
|
||||
new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.hysteria,
|
||||
CoreExes = ["hysteria"],
|
||||
Arguments = "",
|
||||
Url = GetCoreUrl(ECoreType.hysteria),
|
||||
},
|
||||
|
||||
_coreInfo.Add(new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.naiveproxy,
|
||||
CoreExes = new List<string> { "naiveproxy", "naive" },
|
||||
Arguments = "config.json",
|
||||
Url = Global.NaiveproxyCoreUrl,
|
||||
RedirectInfo = false,
|
||||
});
|
||||
new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.naiveproxy,
|
||||
CoreExes = [ "naive", "naiveproxy"],
|
||||
Arguments = "{0}",
|
||||
Url = GetCoreUrl(ECoreType.naiveproxy),
|
||||
},
|
||||
|
||||
_coreInfo.Add(new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.tuic,
|
||||
CoreExes = new List<string> { "tuic-client", "tuic" },
|
||||
Arguments = "-c config.json",
|
||||
Url = Global.TuicCoreUrl,
|
||||
RedirectInfo = true,
|
||||
});
|
||||
new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.tuic,
|
||||
CoreExes = ["tuic-client", "tuic"],
|
||||
Arguments = "-c {0}",
|
||||
Url = GetCoreUrl(ECoreType.tuic),
|
||||
},
|
||||
|
||||
_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",
|
||||
});
|
||||
new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.sing_box,
|
||||
CoreExes = ["sing-box-client", "sing-box"],
|
||||
Arguments = "run -c {0} --disable-color",
|
||||
Url = GetCoreUrl(ECoreType.sing_box),
|
||||
|
||||
_coreInfo.Add(new CoreInfo
|
||||
{
|
||||
CoreType = ECoreType.juicity,
|
||||
CoreExes = new List<string> { "juicity-client", "juicity" },
|
||||
Arguments = "run -c config.json",
|
||||
Url = Global.JuicityCoreUrl
|
||||
});
|
||||
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",
|
||||
},
|
||||
|
||||
_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,
|
||||
});
|
||||
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 string PortableMode()
|
||||
private static string PortableMode()
|
||||
{
|
||||
return $" -d {Utils.GetBinPath("").AppendQuotes()}";
|
||||
}
|
||||
|
||||
private static string GetCoreUrl(ECoreType eCoreType)
|
||||
{
|
||||
return $"{Global.GithubUrl}/{Global.CoreUrls[eCoreType]}/releases";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
@@ -169,4 +171,4 @@ namespace ServiceLib.Handler.Fmt
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace ServiceLib.Handler.Fmt
|
||||
namespace ServiceLib.Handler.Fmt
|
||||
{
|
||||
public class SocksFmt : BaseFmt
|
||||
{
|
||||
@@ -23,7 +23,8 @@
|
||||
|
||||
public static string? ToUri(ProfileItem? item)
|
||||
{
|
||||
if (item == null) return null;
|
||||
if (item == null)
|
||||
return null;
|
||||
var url = string.Empty;
|
||||
|
||||
var remark = string.Empty;
|
||||
@@ -86,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()
|
||||
{
|
||||
@@ -108,4 +110,4 @@
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace ServiceLib.Handler
|
||||
public async Task Init()
|
||||
{
|
||||
await InitData();
|
||||
Task.Run(async () =>
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
@@ -32,7 +32,7 @@ namespace ServiceLib.Handler
|
||||
|
||||
public async Task<ConcurrentBag<ProfileExItem>> GetProfileExs()
|
||||
{
|
||||
return _lstProfileEx;
|
||||
return await Task.FromResult(_lstProfileEx);
|
||||
}
|
||||
|
||||
private async Task InitData()
|
||||
|
||||
@@ -19,15 +19,13 @@
|
||||
{
|
||||
_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()
|
||||
@@ -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)
|
||||
|
||||
@@ -93,8 +93,9 @@
|
||||
{
|
||||
return LstInterface;
|
||||
}
|
||||
var lst = services.Split(Environment.NewLine);
|
||||
return lst.Length > 0 ? LstInterface.Intersect(lst).ToList() : LstInterface;
|
||||
|
||||
var lst = services.Split(Environment.NewLine).Where(t => t.Length > 0 && t.Contains('*') == false);
|
||||
return lst.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ namespace ServiceLib.Handler.SysProxy
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch
|
||||
{
|
||||
SetProxyFallback(strProxy, exceptions, type);
|
||||
return false;
|
||||
@@ -176,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
|
||||
@@ -356,4 +357,4 @@ namespace ServiceLib.Handler.SysProxy
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
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;
|
||||
@@ -15,7 +16,7 @@
|
||||
try
|
||||
{
|
||||
var port = AppHandler.Instance.GetLocalPort(EInboundProtocol.socks);
|
||||
var exceptions = config.SystemProxyItem.SystemProxyExceptions;
|
||||
var exceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
|
||||
if (port <= 0)
|
||||
{
|
||||
return false;
|
||||
@@ -67,7 +68,7 @@
|
||||
|
||||
private static void GetWindowsProxyString(Config config, int port, out string strProxy, out string strExceptions)
|
||||
{
|
||||
strExceptions = config.SystemProxyItem.SystemProxyExceptions;
|
||||
strExceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
|
||||
if (config.SystemProxyItem.NotProxyLocalAddress)
|
||||
{
|
||||
strExceptions = $"<local>;{strExceptions}";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Net;
|
||||
using System.Net;
|
||||
using WebDav;
|
||||
|
||||
namespace ServiceLib.Handler
|
||||
@@ -14,7 +14,6 @@ namespace ServiceLib.Handler
|
||||
private string _webDir = Global.AppName + "_backup";
|
||||
private readonly string _webFileName = "backup.zip";
|
||||
private readonly string _tag = "WebDav--";
|
||||
|
||||
|
||||
public WebDavHandler()
|
||||
{
|
||||
@@ -62,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);
|
||||
@@ -177,4 +177,4 @@ namespace ServiceLib.Handler
|
||||
|
||||
public string GetLastError() => _lastDescription ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -67,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;
|
||||
}
|
||||
|
||||
@@ -102,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; }
|
||||
@@ -119,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; }
|
||||
@@ -246,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; }
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,23 +4,15 @@ namespace ServiceLib.Models
|
||||
{
|
||||
public class V2rayConfig
|
||||
{
|
||||
public string? remarks { get; set; }
|
||||
|
||||
public Log4Ray log { get; set; }
|
||||
|
||||
public List<Inbounds4Ray> inbounds { get; set; }
|
||||
|
||||
public List<Outbounds4Ray> outbounds { get; set; }
|
||||
|
||||
public Stats4Ray? stats { get; set; }
|
||||
|
||||
public Metrics4Ray? metrics { get; set; }
|
||||
|
||||
public Policy4Ray? policy { get; set; }
|
||||
|
||||
public object dns { get; set; }
|
||||
|
||||
public List<Inbounds4Ray> inbounds { get; set; }
|
||||
public List<Outbounds4Ray> outbounds { get; set; }
|
||||
public Routing4Ray routing { get; set; }
|
||||
public Metrics4Ray? metrics { get; set; }
|
||||
public Policy4Ray? policy { get; set; }
|
||||
public Stats4Ray? stats { get; set; }
|
||||
public string? remarks { get; set; }
|
||||
}
|
||||
|
||||
public class Stats4Ray
|
||||
@@ -398,4 +390,4 @@ namespace ServiceLib.Models
|
||||
public string? length { get; set; }
|
||||
public string? interval { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
130
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
130
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
@@ -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 {
|
||||
@@ -1348,7 +1348,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Import Advanced Rules 的本地化字符串。
|
||||
/// 查找类似 Import Rules 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string menuRoutingAdvancedImportRules {
|
||||
get {
|
||||
@@ -1366,7 +1366,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Set as active rule(Enter) 的本地化字符串。
|
||||
/// 查找类似 Set as active rule (Enter) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string menuRoutingAdvancedSetDefault {
|
||||
get {
|
||||
@@ -1536,15 +1536,6 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Save Interface Layout 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string menuStorageUI {
|
||||
get {
|
||||
return ResourceManager.GetString("menuStorageUI", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2103,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>
|
||||
@@ -2303,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 {
|
||||
@@ -2356,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>
|
||||
@@ -2402,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 {
|
||||
@@ -2681,7 +2672,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 *Set the rules, separated by commas (,); The comma in the regular is replaced by <COMMA> 的本地化字符串。
|
||||
/// 查找类似 *Separate rules by commas (,); For a literal comma use <COMMA>; Prefix # to ignore a rule 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbRoutingTips {
|
||||
get {
|
||||
@@ -2789,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 {
|
||||
@@ -2815,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>
|
||||
@@ -2870,7 +2852,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 FontFamily(Require restart) 的本地化字符串。
|
||||
/// 查找类似 Font family (requires restart) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsCurrentFontFamily {
|
||||
get {
|
||||
@@ -2888,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 {
|
||||
@@ -2941,6 +2923,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Display real-time speed (requires restart) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsDisplayRealTimeSpeed {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsDisplayRealTimeSpeed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Outbound DNS address 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2969,7 +2960,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Double-click server make active 的本地化字符串。
|
||||
/// 查找类似 Double-clicking server makes it active 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsDoubleClick2Activate {
|
||||
get {
|
||||
@@ -2978,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 {
|
||||
@@ -3005,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 {
|
||||
@@ -3041,7 +3032,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Enable hardware acceleration(Require restart) 的本地化字符串。
|
||||
/// 查找类似 Enable hardware acceleration (requires restart) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsEnableHWA {
|
||||
get {
|
||||
@@ -3077,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 {
|
||||
@@ -3086,7 +3077,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Exception. Do not use proxy server for addresses,with a comma (,) 的本地化字符串。
|
||||
/// 查找类似 Exclusions: Do not use proxy server for the following addresses. Use comma (,) to separate entries. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsExceptionTip2 {
|
||||
get {
|
||||
@@ -3094,15 +3085,6 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Follow System Theme 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsFollowSystemTheme {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSettingsFollowSystemTheme", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Font Size 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3149,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 {
|
||||
@@ -3239,7 +3212,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Main layout orientation(Require restart) 的本地化字符串。
|
||||
/// 查找类似 Main layout orientation (requires restart) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsMainGirdOrientation {
|
||||
get {
|
||||
@@ -3437,7 +3410,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Enable Statistics (Require restart) 的本地化字符串。
|
||||
/// 查找类似 Enable traffic statistics (requires restart) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsStatistics {
|
||||
get {
|
||||
@@ -3463,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>
|
||||
|
||||
@@ -344,10 +344,10 @@
|
||||
<value>لطفاً DNS سفارشی صحیح را پر کنید</value>
|
||||
</data>
|
||||
<data name="TransportPathTip1" xml:space="preserve">
|
||||
<value>*ws path</value>
|
||||
<value>* مسیر ws</value>
|
||||
</data>
|
||||
<data name="TransportPathTip2" xml:space="preserve">
|
||||
<value>*h2 path</value>
|
||||
<value>* مسیر h2</value>
|
||||
</data>
|
||||
<data name="TransportPathTip3" xml:space="preserve">
|
||||
<value>*QUIC key/Kcp seed</value>
|
||||
@@ -356,13 +356,13 @@
|
||||
<value>*grpc serviceName</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip1" xml:space="preserve">
|
||||
<value>*http host Separated by commas (,)</value>
|
||||
<value>*هاست http جدا شده با کاما (،)</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip2" xml:space="preserve">
|
||||
<value>*ws host</value>
|
||||
<value>*هاست ws</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip3" xml:space="preserve">
|
||||
<value>*h2 host Separated by commas (,)</value>
|
||||
<value>*هاست h2 با کاما (،) جدا شده است</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip4" xml:space="preserve">
|
||||
<value>*QUIC securty</value>
|
||||
@@ -377,7 +377,7 @@
|
||||
<value>*QUIC camouflage type</value>
|
||||
</data>
|
||||
<data name="TransportHeaderTypeTip4" xml:space="preserve">
|
||||
<value>*grpc mode</value>
|
||||
<value>*حالت grpc</value>
|
||||
</data>
|
||||
<data name="LvTLS" xml:space="preserve">
|
||||
<value>TLS</value>
|
||||
@@ -404,7 +404,7 @@
|
||||
<value>درحال تست کردن...</value>
|
||||
</data>
|
||||
<data name="LabLAN" xml:space="preserve">
|
||||
<value>LAN</value>
|
||||
<value>شبکه محلی</value>
|
||||
</data>
|
||||
<data name="LabLocal" 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>
|
||||
@@ -686,7 +683,7 @@
|
||||
<value>راه اندازی مخفی کردن خودکار</value>
|
||||
</data>
|
||||
<data name="TbSettingsAutoUpdateInterval" xml:space="preserve">
|
||||
<value>فاصله به روز رسانی خودکار و Geo (ساعت)</value>
|
||||
<value>فاصله به روز رسانی خودکار برای فایل های Geo (ساعت)</value>
|
||||
</data>
|
||||
<data name="TbSettingsCore" xml:space="preserve">
|
||||
<value>هسته: تنظیمات اولیه</value>
|
||||
@@ -707,7 +704,7 @@
|
||||
<value>Outbound Freedom domainStrategy</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableAutoAdjustMainLvColWidth" xml:space="preserve">
|
||||
<value>پس از بهروزرسانی اشتراک، عرض ستون را به صورت خودکار تنظیم شود</value>
|
||||
<value>پس از بهروزرسانی اشتراک، عرض ستون به صورت خودکار تنظیم شود</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
|
||||
<value>به روز رسانی های پیش از انتشار را بررسی شود</value>
|
||||
@@ -716,16 +713,16 @@
|
||||
<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>هنگام بهروزرسانی هسته، فایلهای Geo را نادیده بگیرید</value>
|
||||
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
||||
<value>نمایش سرعت واقعی (نیاز به راه اندازی مجدد)</value>
|
||||
</data>
|
||||
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
||||
<value>هنگام کپی برداری، نگه داری قدیمی تر ها</value>
|
||||
<value>هنگام حذف کپی، قدیمی تر را نگه دارید</value>
|
||||
</data>
|
||||
<data name="TbSettingsLogEnabled" xml:space="preserve">
|
||||
<value>ثبت گزارش های محلی</value>
|
||||
@@ -758,7 +755,7 @@
|
||||
<value>درهنگام راه ائدازی شروع شود</value>
|
||||
</data>
|
||||
<data name="TbSettingsStatistics" xml:space="preserve">
|
||||
<value>فعال کردن آمار (نیاز به راه اندازی مجدد)</value>
|
||||
<value>فعال کردن آمار ترافیک (نیاز به راه اندازی مجدد)</value>
|
||||
</data>
|
||||
<data name="TbSettingsSubConvert" xml:space="preserve">
|
||||
<value>آدرس اینترنتی تبدیل اشتراک</value>
|
||||
@@ -839,7 +836,7 @@
|
||||
<value>اضافه کردن</value>
|
||||
</data>
|
||||
<data name="menuRoutingAdvancedImportRules" xml:space="preserve">
|
||||
<value>وارد کردن قوانین پیشرفته</value>
|
||||
<value>وارد کردن مجموعه قوانین</value>
|
||||
</data>
|
||||
<data name="menuRoutingAdvancedRemove" xml:space="preserve">
|
||||
<value>حذف انتخاب شده</value>
|
||||
@@ -853,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. مسدود کردن دامنه یا آیپی</value>
|
||||
</data>
|
||||
@@ -869,7 +863,7 @@
|
||||
<value>لیست مجموعه قوانین از پیش تعریف شده</value>
|
||||
</data>
|
||||
<data name="TbRoutingTips" xml:space="preserve">
|
||||
<value>*قوانین را تنظیم کنید که با کاما از هم جدا شده اند (,); کاما در حالت عادی با <COMMA></value>
|
||||
<value>*قوانین را با کاما (,) جدا کنید. برای کاما به معنای واقعی کلمه از <COMMA>; پیشوند # برای نادیده گرفتن یک قانون</value>
|
||||
</data>
|
||||
<data name="menuImportRulesFromClipboard" xml:space="preserve">
|
||||
<value>وارد کردن قوانین از کلیپ بورد</value>
|
||||
@@ -905,7 +899,7 @@
|
||||
<value>مستندات شی قانون</value>
|
||||
</data>
|
||||
<data name="TbDnsObjectDoc" xml:space="preserve">
|
||||
<value>پشتیبانی از DnsObject</value>
|
||||
<value>پشتیبانی از DnsObject. برای مشاهده مستندات کلیک کنید</value>
|
||||
</data>
|
||||
<data name="SubUrlTips" xml:space="preserve">
|
||||
<value>گروه لطفا اینجا را خالی بگذارید</value>
|
||||
@@ -940,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>
|
||||
@@ -959,7 +950,7 @@
|
||||
<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>
|
||||
@@ -1105,9 +1096,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>منبع فایل های جغرافیایی (اختیاری)</value>
|
||||
</data>
|
||||
@@ -1220,7 +1208,7 @@
|
||||
<value>انتقال به گروه</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
|
||||
<value>فعال کردن مرتب سازی با کشیدن سرور (نیاز به راه اندازی مجدد)</value>
|
||||
<value>فعال کردن مرتبسازی سرورها با کشیدن و رها کردن (نیاز به راهاندازی مجدد)</value>
|
||||
</data>
|
||||
<data name="TbAutoRefresh" xml:space="preserve">
|
||||
<value>بازخوانی خودکار</value>
|
||||
@@ -1232,7 +1220,7 @@
|
||||
<value>ویرایش سرور (Ctrl+D)</value>
|
||||
</data>
|
||||
<data name="TbSettingsDoubleClick2Activate" xml:space="preserve">
|
||||
<value>روی server make active دوبار کلیک کنید</value>
|
||||
<value>دوبار کلیک کردن سرور باعث فعال شدن آن می شود</value>
|
||||
</data>
|
||||
<data name="SpeedtestingCompleted" xml:space="preserve">
|
||||
<value>تست تکمیل شد</value>
|
||||
@@ -1244,7 +1232,7 @@
|
||||
<value>FontFamily (نیاز به راه اندازی مجدد)</value>
|
||||
</data>
|
||||
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
|
||||
<value>فایل TTF/TTC فونت را در دایرکتوری guiFonts کپی کنید، تنظیمات را مجددا راه اندازی کنید</value>
|
||||
<value>فایل TTF/TTC فونت را در دایرکتوری guiFonts کپی کنید. پنجره تنظیمات را دوباره باز کنید</value>
|
||||
</data>
|
||||
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
||||
<value>پورت Pac = +3; پورت Xray API = +4; پورت mihomo API = +5;</value>
|
||||
@@ -1273,9 +1261,6 @@
|
||||
<data name="TbSettingsHysteriaBandwidth" xml:space="preserve">
|
||||
<value>حداکتر پهنای باند هیستریا (آپلود/دانلود)</value>
|
||||
</data>
|
||||
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
|
||||
<value>دنبال کردن تم سیستم</value>
|
||||
</data>
|
||||
<data name="menuAddTuicServer" xml:space="preserve">
|
||||
<value>افزودن سرور [TUIC]</value>
|
||||
</data>
|
||||
@@ -1391,7 +1376,7 @@
|
||||
<value>تعداد در هر زمان برای دسته خودکار در طول تست سرعت (حداکثر 1000)</value>
|
||||
</data>
|
||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||
<value>استثنا:از سرور پروکسی برای آدرس ها، با کاما (،) استفاده نکنید</value>
|
||||
<value>موارد استثنا: از سرور پروکسی برای آدرس های زیر استفاده نکنید. برای جدا کردن ورودی ها از کاما (،) استفاده کنید.</value>
|
||||
</data>
|
||||
<data name="TbSettingsDestOverride" xml:space="preserve">
|
||||
<value>نوع Sniffing</value>
|
||||
@@ -1402,4 +1387,13 @@
|
||||
<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>شروع آزمایش مجدد قطعات ناموفق، {0} باقی مانده است. برای خاتمه ESC را فشار دهید...</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -481,12 +481,6 @@
|
||||
<data name="TbSettingsColor" xml:space="preserve">
|
||||
<value>Szín</value>
|
||||
</data>
|
||||
<data name="TbSettingsColorMode" xml:space="preserve">
|
||||
<value>Sötét mód</value>
|
||||
</data>
|
||||
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
|
||||
<value>Kövesse a rendszer témáját</value>
|
||||
</data>
|
||||
<data name="TbSettingsLanguage" xml:space="preserve">
|
||||
<value>Nyelv (Újraindítás)</value>
|
||||
</data>
|
||||
@@ -724,8 +718,8 @@
|
||||
<data name="TbSettingsHttpPort" xml:space="preserve">
|
||||
<value>HTTP Port</value>
|
||||
</data>
|
||||
<data name="TbSettingsIgnoreGeoUpdateCore" xml:space="preserve">
|
||||
<value>Geo fájlok figyelmen kívül hagyása a yalap frissítésekor</value>
|
||||
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
||||
<value>Display real-time speed</value>
|
||||
</data>
|
||||
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
||||
<value>Régi megőrzése a deduplikáció során</value>
|
||||
@@ -856,9 +850,6 @@
|
||||
<data name="TbdomainStrategy" xml:space="preserve">
|
||||
<value>Domain stratégia</value>
|
||||
</data>
|
||||
<data name="TbenableRoutingAdvanced" xml:space="preserve">
|
||||
<value>Fejlett funkció engedélyezése</value>
|
||||
</data>
|
||||
<data name="TbRoutingTabBlock" xml:space="preserve">
|
||||
<value>3. Domain vagy IP blokkolása</value>
|
||||
</data>
|
||||
@@ -943,9 +934,6 @@
|
||||
<data name="TbDisplayLog" xml:space="preserve">
|
||||
<value>Napló megjelenítése</value>
|
||||
</data>
|
||||
<data name="menuImportOldGuiConfig" xml:space="preserve">
|
||||
<value>Régi konfiguráció importálása (guiNConfig)</value>
|
||||
</data>
|
||||
<data name="TbEnableTunAs" xml:space="preserve">
|
||||
<value>Tun engedélyezése</value>
|
||||
</data>
|
||||
@@ -1318,9 +1306,6 @@
|
||||
<data name="TipActiveServer" xml:space="preserve">
|
||||
<value>Aktív</value>
|
||||
</data>
|
||||
<data name="menuStorageUI" xml:space="preserve">
|
||||
<value>Szoftverfelület elmentése</value>
|
||||
</data>
|
||||
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
|
||||
<value>Geo fájlok forrása (opcionális)</value>
|
||||
</data>
|
||||
@@ -1402,4 +1387,13 @@
|
||||
<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>
|
||||
@@ -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>
|
||||
@@ -761,7 +755,7 @@
|
||||
<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 <COMMA></value>
|
||||
<value>*Separate rules by commas (,); For a literal comma use <COMMA>; 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,10 +974,10 @@
|
||||
<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>Pac port = +3; Xray API port = +4; mihomo API port = +5;</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>
|
||||
@@ -1391,7 +1376,7 @@
|
||||
<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>
|
||||
<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>
|
||||
@@ -1402,4 +1387,13 @@
|
||||
<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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -1270,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>
|
||||
@@ -1402,4 +1387,13 @@
|
||||
<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>
|
||||
@@ -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>
|
||||
@@ -761,7 +755,7 @@
|
||||
<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>*设置的路由规则,用逗号(,)分隔;正则中的逗号用<COMMA>替代</value>
|
||||
<value>*设置的路由规则,用逗号(,)分隔;正则中的逗号用<COMMA>替代</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>支持填写DnsObject,JSON格式,点击查看文档</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>
|
||||
@@ -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>
|
||||
@@ -1373,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>
|
||||
@@ -1388,7 +1373,7 @@
|
||||
<value>测试时自动分批的每批数量(最大1000)</value>
|
||||
</data>
|
||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||
<value>例外. 对于下列地址不使用代理配置文件:使用逗号(,)分隔</value>
|
||||
<value>例外:对于下列地址不使用代理配置文件。使用逗号(,)分隔。</value>
|
||||
</data>
|
||||
<data name="TbSettingsDestOverride" xml:space="preserve">
|
||||
<value>流量探测类型</value>
|
||||
@@ -1399,4 +1384,13 @@
|
||||
<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>
|
||||
@@ -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>
|
||||
@@ -761,7 +756,7 @@
|
||||
<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>*設定的路由規則,用逗號(,)分隔;正則中的逗號用<COMMA>替代</value>
|
||||
<value>*設定的路由規則,用逗號(,)分隔;正則中的逗號用<COMMA>替代</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>支援填寫DnsObject,JSON格式,點擊查看説明</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>
|
||||
@@ -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>
|
||||
@@ -1373,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>
|
||||
@@ -1388,7 +1374,7 @@
|
||||
<value>測試時自動分批的每批數量(最大1000)</value>
|
||||
</data>
|
||||
<data name="TbSettingsExceptionTip2" xml:space="preserve">
|
||||
<value>例外. 對於下列位址不使用代理設定檔:使用逗號(,)分隔</value>
|
||||
<value>例外:對於下列位址不使用代理設定檔,使用逗號(,)分隔。</value>
|
||||
</data>
|
||||
<data name="TbSettingsDestOverride" xml:space="preserve">
|
||||
<value>流量探測類型</value>
|
||||
@@ -1399,4 +1385,13 @@
|
||||
<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>
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,83 +1,77 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>7.5.2</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Downloader" Version="3.3.1" />
|
||||
<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.3.0" />
|
||||
<PackageReference Include="QRCoder" Version="1.6.0" />
|
||||
<PackageReference Include="CliWrap" Version="3.7.0" />
|
||||
<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_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.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>
|
||||
<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>
|
||||
@@ -116,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);
|
||||
@@ -128,7 +128,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
//Mixin
|
||||
try
|
||||
{
|
||||
MixinContent(fileContent, node);
|
||||
await MixinContent(fileContent, node);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -158,20 +158,21 @@ namespace ServiceLib.Services.CoreConfig
|
||||
}
|
||||
}
|
||||
|
||||
private void MixinContent(Dictionary<string, object> fileContent, ProfileItem node)
|
||||
private async Task MixinContent(Dictionary<string, object> fileContent, ProfileItem node)
|
||||
{
|
||||
//if (!_config.clashUIItem.enableMixinContent)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
var path = Utils.GetConfigPath(Global.ClashMixinConfigFileName);
|
||||
if (!File.Exists(path))
|
||||
if (!_config.ClashUIItem.EnableMixinContent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var txtFile = File.ReadAllText(Utils.GetConfigPath(Global.ClashMixinConfigFileName));
|
||||
var path = Utils.GetConfigPath(Global.ClashMixinConfigFileName);
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
var mixin = EmbedUtils.GetEmbedText(Global.ClashMixinYaml);
|
||||
await File.AppendAllTextAsync(path, mixin);
|
||||
}
|
||||
|
||||
var txtFile = await File.ReadAllTextAsync(Utils.GetConfigPath(Global.ClashMixinConfigFileName));
|
||||
|
||||
var mixinContent = YamlUtils.FromYaml<Dictionary<string, object>>(txtFile);
|
||||
if (mixinContent == null)
|
||||
@@ -269,4 +270,4 @@ namespace ServiceLib.Services.CoreConfig
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,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;
|
||||
@@ -91,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;
|
||||
@@ -255,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;
|
||||
@@ -313,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)
|
||||
@@ -333,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
|
||||
@@ -344,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);
|
||||
@@ -476,7 +476,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
return 0;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenInbounds(SingboxConfig singboxConfig)
|
||||
@@ -546,7 +546,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
_config.TunModeItem.Stack = Global.TunStacks.First();
|
||||
}
|
||||
|
||||
var tunInbound = JsonUtils.Deserialize<Inbound4Sbox>(Utils.GetEmbedText(Global.TunSingboxInboundFileName)) ?? new Inbound4Sbox { };
|
||||
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;
|
||||
@@ -721,7 +721,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
return 0;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenOutboundTls(ProfileItem node, Outbound4Sbox outbound)
|
||||
@@ -771,7 +771,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
return 0;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenOutboundTransport(ProfileItem node, Outbound4Sbox outbound)
|
||||
@@ -848,7 +848,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
return 0;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenMoreOutbounds(ProfileItem node, SingboxConfig singboxConfig)
|
||||
@@ -867,7 +867,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
|
||||
//current proxy
|
||||
var outbound = singboxConfig.outbounds.First();
|
||||
var txtOutbound = Utils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||
var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);
|
||||
|
||||
//Previous proxy
|
||||
var prevNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.PrevProfile);
|
||||
@@ -934,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);
|
||||
@@ -1048,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)
|
||||
{
|
||||
@@ -1062,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)
|
||||
{
|
||||
@@ -1088,7 +1090,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
return 0;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private bool ParseV2Domain(string domain, Rule4Sbox rule)
|
||||
@@ -1148,12 +1150,14 @@ 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;
|
||||
@@ -1167,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);
|
||||
@@ -1240,7 +1244,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
}
|
||||
|
||||
singboxConfig.dns = dns4Sbox;
|
||||
return 0;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenExperimental(SingboxConfig singboxConfig)
|
||||
@@ -1259,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";
|
||||
@@ -1320,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) ?? [])
|
||||
@@ -1338,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)
|
||||
{
|
||||
@@ -1377,4 +1384,4 @@ namespace ServiceLib.Services.CoreConfig
|
||||
|
||||
#endregion private gen function
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Net;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
@@ -36,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;
|
||||
@@ -91,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;
|
||||
@@ -154,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)
|
||||
@@ -182,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);
|
||||
@@ -217,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;
|
||||
@@ -382,7 +379,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
return 0;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenInbounds(V2rayConfig v2rayConfig)
|
||||
@@ -426,12 +423,12 @@ namespace ServiceLib.Services.CoreConfig
|
||||
{
|
||||
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();
|
||||
@@ -563,13 +560,14 @@ namespace ServiceLib.Services.CoreConfig
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
return 0;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenOutbound(ProfileItem node, Outbounds4Ray outbound)
|
||||
{
|
||||
try
|
||||
{
|
||||
var muxEnabled = _config.CoreBasicItem.MuxEnabled;
|
||||
switch (node.ConfigType)
|
||||
{
|
||||
case EConfigType.VMess:
|
||||
@@ -610,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;
|
||||
@@ -635,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;
|
||||
@@ -671,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;
|
||||
@@ -705,22 +703,15 @@ namespace ServiceLib.Services.CoreConfig
|
||||
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;
|
||||
}
|
||||
@@ -743,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;
|
||||
@@ -760,28 +751,30 @@ namespace ServiceLib.Services.CoreConfig
|
||||
return 0;
|
||||
}
|
||||
|
||||
private 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(_tag, ex);
|
||||
}
|
||||
return 0;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenBoundStreamSettings(ProfileItem node, Outbounds4Ray outbound)
|
||||
@@ -931,7 +924,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
}
|
||||
|
||||
streamSettings.xhttpSettings = xhttpSettings;
|
||||
await GenOutboundMux(node, outbound, false);
|
||||
await GenOutboundMux(node, outbound);
|
||||
|
||||
break;
|
||||
//h2
|
||||
@@ -999,7 +992,7 @@ 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()}");
|
||||
@@ -1035,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);
|
||||
@@ -1106,12 +1103,12 @@ namespace ServiceLib.Services.CoreConfig
|
||||
servers.AsArray().Add(JsonUtils.SerializeToNode(dnsServer));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
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();
|
||||
@@ -1153,7 +1150,7 @@ 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)
|
||||
@@ -1170,9 +1167,9 @@ 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
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1199,7 +1196,7 @@ namespace ServiceLib.Services.CoreConfig
|
||||
|
||||
//current proxy
|
||||
var outbound = v2rayConfig.outbounds.First();
|
||||
var txtOutbound = Utils.GetEmbedText(Global.V2raySampleOutbound);
|
||||
var txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);
|
||||
|
||||
//Previous proxy
|
||||
var prevNode = await AppHandler.Instance.GetProfileItemViaRemarks(subItem.PrevProfile);
|
||||
@@ -1250,4 +1247,4 @@ namespace ServiceLib.Services.CoreConfig
|
||||
|
||||
#endregion private gen function
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace ServiceLib.Services
|
||||
public event EventHandler<RetResult>? UpdateCompleted;
|
||||
|
||||
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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using ReactiveUI;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
@@ -7,17 +7,88 @@ namespace ServiceLib.Services
|
||||
{
|
||||
public class SpeedtestService
|
||||
{
|
||||
private static readonly string _tag = "SpeedtestService";
|
||||
private Config? _config;
|
||||
private Action<SpeedTestResult>? _updateFunc;
|
||||
private static readonly ConcurrentBag<string> _lstExitLoop = new();
|
||||
|
||||
private bool _exitLoop = false;
|
||||
private static readonly string _tag = "SpeedtestService";
|
||||
|
||||
public SpeedtestService(Config config, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> updateFunc)
|
||||
public SpeedtestService(Config config, Action<SpeedTestResult> updateFunc)
|
||||
{
|
||||
_config = config;
|
||||
_updateFunc = updateFunc;
|
||||
}
|
||||
|
||||
public void RunLoop(ESpeedActionType actionType, List<ProfileItem> selecteds)
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var exitLoopKey = Utils.GetGuid(false);
|
||||
_lstExitLoop.Add(exitLoopKey);
|
||||
|
||||
var lstSelected = GetClearItem(actionType, selecteds);
|
||||
await RunAsync(actionType, lstSelected, exitLoopKey);
|
||||
UpdateFunc("", ResUI.SpeedtestingCompleted);
|
||||
});
|
||||
}
|
||||
|
||||
public void ExitLoop()
|
||||
{
|
||||
if (_lstExitLoop.Count > 0)
|
||||
{
|
||||
UpdateFunc("", ResUI.SpeedtestingStop);
|
||||
|
||||
_lstExitLoop.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunAsync(ESpeedActionType actionType, List<ServerTestItem> lstSelected, string exitLoopKey, 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, exitLoopKey),
|
||||
ESpeedActionType.Speedtest => await RunSpeedTestAsync(lst, exitLoopKey),
|
||||
ESpeedActionType.Mixedtest => await RunMixedTestAsync(lst, exitLoopKey),
|
||||
_ => 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 (_lstExitLoop.Any(p => p == exitLoopKey) == false)
|
||||
{
|
||||
UpdateFunc("", ResUI.SpeedtestingSkip);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateFunc("", string.Format(ResUI.SpeedtestingTestFailedPart, lstFailed.Count));
|
||||
await RunAsync(actionType, lstFailed, exitLoopKey, pageSizeNext);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ServerTestItem> GetClearItem(ESpeedActionType actionType, List<ProfileItem> selecteds)
|
||||
{
|
||||
var lstSelected = new List<ServerTestItem>();
|
||||
foreach (var it in selecteds)
|
||||
{
|
||||
@@ -25,10 +96,12 @@ namespace ServiceLib.Services
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (it.Port <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
lstSelected.Add(new ServerTestItem()
|
||||
{
|
||||
IndexId = it.IndexId,
|
||||
@@ -62,25 +135,11 @@ namespace ServiceLib.Services
|
||||
}
|
||||
}
|
||||
|
||||
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop);
|
||||
|
||||
Task.Run(async () => { await RunAsync(actionType, lstSelected); });
|
||||
return lstSelected;
|
||||
}
|
||||
|
||||
private async Task RunAsync(ESpeedActionType actionType, List<ServerTestItem> lstSelected)
|
||||
private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize)
|
||||
{
|
||||
if (actionType == ESpeedActionType.Tcping)
|
||||
{
|
||||
await RunTcpingAsync(lstSelected);
|
||||
return;
|
||||
}
|
||||
|
||||
var pageSize = _config.SpeedTestItem.SpeedTestPageSize;
|
||||
if (pageSize is <= 0 or > 1000)
|
||||
{
|
||||
pageSize = 1000;
|
||||
}
|
||||
|
||||
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();
|
||||
@@ -94,34 +153,7 @@ namespace ServiceLib.Services
|
||||
lstTest.Add(lst2.Skip(num * pageSize).Take(pageSize).ToList());
|
||||
}
|
||||
|
||||
foreach (var lst in lstTest)
|
||||
{
|
||||
switch (actionType)
|
||||
{
|
||||
case ESpeedActionType.Realping:
|
||||
await RunRealPingAsync(lst);
|
||||
break;
|
||||
|
||||
case ESpeedActionType.Speedtest:
|
||||
await RunSpeedTestAsync(lst);
|
||||
break;
|
||||
|
||||
case ESpeedActionType.Mixedtest:
|
||||
await RunMixedTestAsync(lst);
|
||||
break;
|
||||
}
|
||||
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
UpdateFunc("", ResUI.SpeedtestingCompleted);
|
||||
}
|
||||
|
||||
private void ExitLoop(string x)
|
||||
{
|
||||
if (_exitLoop) return;
|
||||
_exitLoop = true;
|
||||
UpdateFunc("", ResUI.SpeedtestingStop);
|
||||
return lstTest;
|
||||
}
|
||||
|
||||
private async Task RunTcpingAsync(List<ServerTestItem> selecteds)
|
||||
@@ -163,7 +195,7 @@ namespace ServiceLib.Services
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunRealPingAsync(List<ServerTestItem> selecteds)
|
||||
private async Task<bool> RunRealPingAsync(List<ServerTestItem> selecteds, string exitLoopKey)
|
||||
{
|
||||
var pid = -1;
|
||||
try
|
||||
@@ -171,8 +203,7 @@ namespace ServiceLib.Services
|
||||
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
|
||||
if (pid < 0)
|
||||
{
|
||||
UpdateFunc("", ResUI.FailedToRunCore);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
var downloadHandle = new DownloadService();
|
||||
@@ -220,16 +251,16 @@ namespace ServiceLib.Services
|
||||
}
|
||||
await ProfileExHandler.Instance.SaveTo();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task RunSpeedTestAsync(List<ServerTestItem> selecteds)
|
||||
private async Task<bool> RunSpeedTestAsync(List<ServerTestItem> selecteds, string exitLoopKey)
|
||||
{
|
||||
var pid = -1;
|
||||
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
|
||||
if (pid < 0)
|
||||
{
|
||||
UpdateFunc("", ResUI.FailedToRunCore);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
var url = _config.SpeedTestItem.SpeedTestUrl;
|
||||
@@ -239,11 +270,12 @@ namespace ServiceLib.Services
|
||||
|
||||
foreach (var it in selecteds)
|
||||
{
|
||||
if (_exitLoop)
|
||||
if (_lstExitLoop.Any(p => p == exitLoopKey) == false)
|
||||
{
|
||||
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!it.AllowTest)
|
||||
{
|
||||
continue;
|
||||
@@ -261,7 +293,8 @@ 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;
|
||||
|
||||
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
||||
|
||||
@@ -281,16 +314,16 @@ namespace ServiceLib.Services
|
||||
await ProcUtils.ProcessKill(pid);
|
||||
}
|
||||
await ProfileExHandler.Instance.SaveTo();
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task RunSpeedTestMulti(List<ServerTestItem> selecteds)
|
||||
private async Task<bool> RunSpeedTestMultiAsync(List<ServerTestItem> selecteds, string exitLoopKey)
|
||||
{
|
||||
var pid = -1;
|
||||
pid = await CoreHandler.Instance.LoadCoreConfigSpeedtest(selecteds);
|
||||
if (pid < 0)
|
||||
{
|
||||
UpdateFunc("", ResUI.FailedToRunCore);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
var url = _config.SpeedTestItem.SpeedTestUrl;
|
||||
@@ -300,7 +333,7 @@ namespace ServiceLib.Services
|
||||
|
||||
foreach (var it in selecteds)
|
||||
{
|
||||
if (_exitLoop)
|
||||
if (_lstExitLoop.Any(p => p == exitLoopKey) == false)
|
||||
{
|
||||
UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip);
|
||||
continue;
|
||||
@@ -323,7 +356,8 @@ 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;
|
||||
|
||||
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
||||
_ = downloadHandle.DownloadDataAsync(url, webProxy, timeout, (success, msg) =>
|
||||
@@ -345,21 +379,30 @@ namespace ServiceLib.Services
|
||||
await ProcUtils.ProcessKill(pid);
|
||||
}
|
||||
await ProfileExHandler.Instance.SaveTo();
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task RunMixedTestAsync(List<ServerTestItem> selecteds)
|
||||
private async Task<bool> RunMixedTestAsync(List<ServerTestItem> selecteds, string exitLoopKey)
|
||||
{
|
||||
await RunRealPingAsync(selecteds);
|
||||
var ret = await RunRealPingAsync(selecteds, exitLoopKey);
|
||||
if (ret == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
await Task.Delay(1000);
|
||||
|
||||
await RunSpeedTestMulti(selecteds);
|
||||
var ret2 = await RunSpeedTestMultiAsync(selecteds, exitLoopKey);
|
||||
if (ret2 == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<string> GetRealPingTime(DownloadService downloadHandle, IWebProxy webProxy)
|
||||
{
|
||||
var responseTime = await downloadHandle.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
|
||||
//string output = Utile.IsNullOrEmpty(status) ? FormatOut(responseTime, "ms") : status;
|
||||
return FormatOut(responseTime, Global.DelayUnit);
|
||||
}
|
||||
|
||||
@@ -405,4 +448,4 @@ namespace ServiceLib.Services
|
||||
_updateFunc?.Invoke(new() { IndexId = indexId, Delay = delay, Speed = speed });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Net.WebSockets;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
|
||||
namespace ServiceLib.Services.Statistics
|
||||
@@ -21,7 +21,7 @@ namespace ServiceLib.Services.Statistics
|
||||
Task.Run(Run);
|
||||
}
|
||||
|
||||
private async void Init()
|
||||
private async Task Init()
|
||||
{
|
||||
await Task.Delay(5000);
|
||||
|
||||
@@ -53,9 +53,9 @@ namespace ServiceLib.Services.Statistics
|
||||
}
|
||||
}
|
||||
|
||||
private async void Run()
|
||||
private async Task Run()
|
||||
{
|
||||
Init();
|
||||
await Init();
|
||||
|
||||
while (!_exitFlag)
|
||||
{
|
||||
@@ -73,7 +73,7 @@ namespace ServiceLib.Services.Statistics
|
||||
{
|
||||
webSocket.Abort();
|
||||
webSocket = null;
|
||||
Init();
|
||||
await Init();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -109,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);
|
||||
@@ -124,4 +125,4 @@ namespace ServiceLib.Services.Statistics
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace ServiceLib.Services.Statistics
|
||||
namespace ServiceLib.Services.Statistics
|
||||
{
|
||||
public class StatisticsXrayService
|
||||
{
|
||||
@@ -23,7 +23,7 @@
|
||||
_exitFlag = true;
|
||||
}
|
||||
|
||||
private async void Run()
|
||||
private async Task Run()
|
||||
{
|
||||
while (!_exitFlag)
|
||||
{
|
||||
@@ -63,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))
|
||||
@@ -102,4 +103,4 @@
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,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);
|
||||
@@ -255,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
|
||||
@@ -368,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;
|
||||
@@ -379,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:
|
||||
@@ -422,17 +423,18 @@ namespace ServiceLib.Services
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -586,4 +588,4 @@ namespace ServiceLib.Services
|
||||
|
||||
#endregion Geo private
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 () =>
|
||||
{
|
||||
@@ -109,6 +110,7 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
NoticeHandler.Instance.Enqueue(ResUI.FailedReadConfiguration);
|
||||
}
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using ReactiveUI;
|
||||
using System.Reactive;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Splat;
|
||||
using System.Reactive;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -154,7 +154,7 @@ namespace ServiceLib.ViewModels
|
||||
ProcUtils.ProcessStart(upgradeFileName, Global.RebootAs, Utils.StartupPath());
|
||||
}
|
||||
}
|
||||
service?.Shutdown();
|
||||
service?.Shutdown(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -173,10 +173,10 @@ namespace ServiceLib.ViewModels
|
||||
var configDirZipTemp = Utils.GetTempPath($"v2rayN_{DateTime.Now:yyyyMMddHHmmss}");
|
||||
var configDirTemp = Path.Combine(configDirZipTemp, _guiConfigs);
|
||||
|
||||
FileManager.CopyDirectory(configDir, configDirTemp, false, "cache.db");
|
||||
FileManager.CopyDirectory(configDir, configDirTemp, false, true, "cache.db");
|
||||
var ret = FileManager.CreateFromDirectory(configDirZipTemp, fileName);
|
||||
Directory.Delete(configDirZipTemp, true);
|
||||
return ret;
|
||||
return await Task.FromResult(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using DynamicData;
|
||||
using System.Reactive;
|
||||
using System.Runtime.InteropServices;
|
||||
using DynamicData;
|
||||
using DynamicData.Binding;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Splat;
|
||||
using System.Reactive;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -46,9 +46,13 @@ namespace ServiceLib.ViewModels
|
||||
if (RuntimeInformation.ProcessArchitecture != Architecture.X86)
|
||||
{
|
||||
_checkUpdateModel.Add(GetCheckUpdateModel(_v2rayN));
|
||||
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.Xray.ToString()));
|
||||
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.mihomo.ToString()));
|
||||
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.sing_box.ToString()));
|
||||
//Not Windows and under Win10
|
||||
if (!(Utils.IsWindows() && Environment.OSVersion.Version.Major < 10))
|
||||
{
|
||||
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.Xray.ToString()));
|
||||
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.mihomo.ToString()));
|
||||
_checkUpdateModel.Add(GetCheckUpdateModel(ECoreType.sing_box.ToString()));
|
||||
}
|
||||
}
|
||||
_checkUpdateModel.Add(GetCheckUpdateModel(_geo));
|
||||
}
|
||||
@@ -79,7 +83,8 @@ namespace ServiceLib.ViewModels
|
||||
for (var k = _checkUpdateModel.Count - 1; k >= 0; k--)
|
||||
{
|
||||
var item = _checkUpdateModel[k];
|
||||
if (item.IsSelected != true) continue;
|
||||
if (item.IsSelected != true)
|
||||
continue;
|
||||
|
||||
UpdateView(item.CoreType, "...");
|
||||
if (item.CoreType == _geo)
|
||||
@@ -248,7 +253,7 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
foreach (var subDir in dir.GetDirectories())
|
||||
{
|
||||
FileManager.CopyDirectory(subDir.FullName, toPath, false, null);
|
||||
FileManager.CopyDirectory(subDir.FullName, toPath, false, true);
|
||||
subDir.Delete(true);
|
||||
}
|
||||
}
|
||||
@@ -259,7 +264,7 @@ namespace ServiceLib.ViewModels
|
||||
}
|
||||
else
|
||||
{
|
||||
FileManager.ZipExtractToFile(fileName, toPath, _config.GuiItem.IgnoreGeoUpdateCore ? "geo" : "");
|
||||
FileManager.ZipExtractToFile(fileName, toPath, "geo");
|
||||
}
|
||||
|
||||
if (Utils.IsNonWindows())
|
||||
@@ -293,10 +298,11 @@ namespace ServiceLib.ViewModels
|
||||
public void UpdateViewResult(CheckUpdateModel model)
|
||||
{
|
||||
var found = _checkUpdateModel.FirstOrDefault(t => t.CoreType == model.CoreType);
|
||||
if (found == null) return;
|
||||
if (found == null)
|
||||
return;
|
||||
var itemCopy = JsonUtils.DeepCopy(found);
|
||||
itemCopy.Remarks = model.Remarks;
|
||||
_checkUpdateModel.Replace(found, itemCopy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using DynamicData;
|
||||
using DynamicData.Binding;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -48,7 +48,7 @@ namespace ServiceLib.ViewModels
|
||||
await ClashConnectionClose(true);
|
||||
});
|
||||
|
||||
Init();
|
||||
_ = Init();
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
@@ -73,6 +73,7 @@ namespace ServiceLib.ViewModels
|
||||
Task.Delay(1000).Wait();
|
||||
}
|
||||
});
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task GetClashConnections()
|
||||
@@ -114,7 +115,8 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
lstModel.Add(model);
|
||||
}
|
||||
if (lstModel.Count <= 0) { return; }
|
||||
if (lstModel.Count <= 0)
|
||||
{ return; }
|
||||
|
||||
_connectionItems.AddRange(lstModel);
|
||||
}
|
||||
@@ -139,4 +141,4 @@ namespace ServiceLib.ViewModels
|
||||
await GetClashConnections();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using DynamicData;
|
||||
using DynamicData.Binding;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using static ServiceLib.Models.ClashProviders;
|
||||
using static ServiceLib.Models.ClashProxies;
|
||||
|
||||
@@ -90,13 +90,13 @@ namespace ServiceLib.ViewModels
|
||||
y => y == true)
|
||||
.Subscribe(c => { _config.ClashUIItem.ProxiesAutoRefresh = AutoRefresh; });
|
||||
|
||||
Init();
|
||||
_ = Init();
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
{
|
||||
await ProxiesReload();
|
||||
DelayTestTask();
|
||||
_ = DelayTestTask();
|
||||
}
|
||||
|
||||
private async Task DoRulemodeSelected(bool c)
|
||||
@@ -265,7 +265,7 @@ namespace ServiceLib.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
_proxies.TryGetValue(name, out ProxiesItem proxy);
|
||||
_proxies.TryGetValue(name, out var proxy);
|
||||
if (proxy == null || proxy.all == null)
|
||||
{
|
||||
return;
|
||||
@@ -316,7 +316,7 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
if (_proxies is null)
|
||||
return null;
|
||||
_proxies.TryGetValue(name, out ProxiesItem proxy2);
|
||||
_proxies.TryGetValue(name, out var proxy2);
|
||||
if (proxy2 != null)
|
||||
{
|
||||
return proxy2;
|
||||
@@ -399,6 +399,7 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
_updateView?.Invoke(EViewAction.DispatcherProxiesDelayTest, new SpeedTestResult() { IndexId = item.Name, Delay = result });
|
||||
});
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void ProxiesDelayTestResult(SpeedTestResult result)
|
||||
@@ -434,7 +435,7 @@ namespace ServiceLib.ViewModels
|
||||
public async Task DelayTestTask()
|
||||
{
|
||||
var lastTime = DateTime.Now;
|
||||
Task.Run(async () =>
|
||||
_ = Task.Run(async () =>
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
@@ -457,8 +458,9 @@ namespace ServiceLib.ViewModels
|
||||
lastTime = dtNow;
|
||||
}
|
||||
});
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
#endregion task
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Reactive;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using System.Reactive;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -31,16 +31,18 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
ImportDefConfig4V2rayCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
normalDNS = Utils.GetEmbedText(Global.DNSV2rayNormalFileName);
|
||||
normalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName);
|
||||
await Task.CompletedTask;
|
||||
});
|
||||
|
||||
ImportDefConfig4SingboxCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
normalDNS2 = Utils.GetEmbedText(Global.DNSSingboxNormalFileName);
|
||||
tunDNS2 = Utils.GetEmbedText(Global.TunSingboxDNSFileName);
|
||||
normalDNS2 = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName);
|
||||
tunDNS2 = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName);
|
||||
await Task.CompletedTask;
|
||||
});
|
||||
|
||||
Init();
|
||||
_ = Init();
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
@@ -112,4 +114,4 @@ namespace ServiceLib.ViewModels
|
||||
_updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Reactive;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Splat;
|
||||
using System.Reactive;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -63,6 +63,8 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
#endregion Menu
|
||||
|
||||
private bool _hasNextReloadJob = false;
|
||||
|
||||
#region Init
|
||||
|
||||
public MainWindowViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
|
||||
@@ -204,7 +206,7 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
#endregion WhenAnyValue && ReactiveCommand
|
||||
|
||||
Init();
|
||||
_ = Init();
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
@@ -217,11 +219,12 @@ namespace ServiceLib.ViewModels
|
||||
await CoreHandler.Instance.Init(_config, UpdateHandler);
|
||||
TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler);
|
||||
|
||||
if (_config.GuiItem.EnableStatistics)
|
||||
if (_config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)
|
||||
{
|
||||
await StatisticsHandler.Instance.Init(_config, UpdateStatisticsHandler);
|
||||
}
|
||||
|
||||
BlReloadEnabled = true;
|
||||
await Reload();
|
||||
await AutoHideStartup();
|
||||
Locator.Current.GetService<StatusBarViewModel>()?.RefreshRoutingsMenu();
|
||||
@@ -249,7 +252,7 @@ namespace ServiceLib.ViewModels
|
||||
RefreshServers();
|
||||
if (indexIdOld != _config.IndexId)
|
||||
{
|
||||
Reload();
|
||||
_ = Reload();
|
||||
}
|
||||
if (_config.UiItem.EnableAutoAdjustMainLvColWidth)
|
||||
{
|
||||
@@ -269,16 +272,13 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
public void SetStatisticsResult(ServerSpeedItem update)
|
||||
{
|
||||
try
|
||||
if (_config.GuiItem.DisplayRealTimeSpeed)
|
||||
{
|
||||
Locator.Current.GetService<StatusBarViewModel>()?.UpdateStatistics(update);
|
||||
if ((update.ProxyUp + update.ProxyDown) > 0 && DateTime.Now.Second % 9 == 0)
|
||||
{
|
||||
Locator.Current.GetService<ProfilesViewModel>()?.UpdateStatistics(update);
|
||||
}
|
||||
}
|
||||
catch
|
||||
if (_config.GuiItem.EnableStatistics && (update.ProxyUp + update.ProxyDown) > 0 && DateTime.Now.Second % 9 == 0)
|
||||
{
|
||||
Locator.Current.GetService<ProfilesViewModel>()?.UpdateStatistics(update);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,14 +287,15 @@ namespace ServiceLib.ViewModels
|
||||
try
|
||||
{
|
||||
Logging.SaveLog("MyAppExitAsync Begin");
|
||||
|
||||
await SysProxyHandler.UpdateSysProxy(_config, true);
|
||||
MessageBus.Current.SendMessage("", EMsgCommand.AppExit.ToString());
|
||||
|
||||
await ConfigHandler.SaveConfig(_config);
|
||||
await SysProxyHandler.UpdateSysProxy(_config, true);
|
||||
await ProfileExHandler.Instance.SaveTo();
|
||||
await StatisticsHandler.Instance.SaveTo();
|
||||
StatisticsHandler.Instance.Close();
|
||||
await CoreHandler.Instance.CoreStop();
|
||||
StatisticsHandler.Instance.Close();
|
||||
|
||||
Logging.SaveLog("MyAppExitAsync End");
|
||||
}
|
||||
@@ -303,7 +304,7 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
if (!blWindowsShutDown)
|
||||
{
|
||||
_updateView?.Invoke(EViewAction.Shutdown, null);
|
||||
_updateView?.Invoke(EViewAction.Shutdown, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -329,9 +330,9 @@ namespace ServiceLib.ViewModels
|
||||
_updateView?.Invoke(EViewAction.ShowHideWindow, blShow);
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
public void Shutdown(bool byUser)
|
||||
{
|
||||
_updateView?.Invoke(EViewAction.Shutdown, null);
|
||||
_updateView?.Invoke(EViewAction.Shutdown, byUser);
|
||||
}
|
||||
|
||||
#endregion Actions
|
||||
@@ -403,6 +404,7 @@ namespace ServiceLib.ViewModels
|
||||
public async Task AddServerViaScanAsync()
|
||||
{
|
||||
_updateView?.Invoke(EViewAction.ScanScreenTask, null);
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task ScanScreenResult(byte[]? bytes)
|
||||
@@ -414,6 +416,7 @@ namespace ServiceLib.ViewModels
|
||||
public async Task AddServerViaImageAsync()
|
||||
{
|
||||
_updateView?.Invoke(EViewAction.ScanImageTask, null);
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task ScanImageResult(string fileName)
|
||||
@@ -527,6 +530,7 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
ProcUtils.ProcessStart("open", path);
|
||||
}
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
#endregion Setting
|
||||
@@ -535,39 +539,46 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
public async Task Reload()
|
||||
{
|
||||
//If there are unfinished reload job, marked with next job.
|
||||
if (!BlReloadEnabled)
|
||||
{
|
||||
_hasNextReloadJob = true;
|
||||
return;
|
||||
}
|
||||
|
||||
BlReloadEnabled = false;
|
||||
|
||||
await LoadCore();
|
||||
Locator.Current.GetService<StatusBarViewModel>()?.TestServerAvailability();
|
||||
await SysProxyHandler.UpdateSysProxy(_config, false);
|
||||
Locator.Current.GetService<StatusBarViewModel>()?.TestServerAvailability();
|
||||
|
||||
_updateView?.Invoke(EViewAction.DispatcherReload, null);
|
||||
|
||||
BlReloadEnabled = true;
|
||||
if (_hasNextReloadJob)
|
||||
{
|
||||
_hasNextReloadJob = false;
|
||||
await Reload();
|
||||
}
|
||||
}
|
||||
|
||||
public void ReloadResult()
|
||||
{
|
||||
// BlReloadEnabled = true;
|
||||
//Locator.Current.GetService<StatusBarViewModel>()?.ChangeSystemProxyAsync(_config.systemProxyItem.sysProxyType, false);
|
||||
BlReloadEnabled = true;
|
||||
ShowClashUI = _config.IsRunningCore(ECoreType.sing_box);
|
||||
if (ShowClashUI)
|
||||
{
|
||||
Locator.Current.GetService<ClashProxiesViewModel>()?.ProxiesReload();
|
||||
}
|
||||
else { TabMainSelectedIndex = 0; }
|
||||
else
|
||||
{ TabMainSelectedIndex = 0; }
|
||||
}
|
||||
|
||||
private async Task LoadCore()
|
||||
{
|
||||
//if (_config.tunModeItem.enableTun)
|
||||
//{
|
||||
// Task.Delay(1000).Wait();
|
||||
// WindowsUtils.RemoveTunDevice();
|
||||
//}
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
var node = await ConfigHandler.GetDefaultServer(_config);
|
||||
await CoreHandler.Instance.LoadCore(node);
|
||||
});
|
||||
var node = await ConfigHandler.GetDefaultServer(_config);
|
||||
await CoreHandler.Instance.LoadCore(node);
|
||||
}
|
||||
|
||||
public async Task CloseCore()
|
||||
@@ -582,6 +593,7 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
ShowHideWindow(false);
|
||||
}
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
#endregion core job
|
||||
@@ -601,4 +613,4 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
#endregion Presets
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text.RegularExpressions;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -59,14 +59,14 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_blLockShow = true;
|
||||
if (!_config.UiItem.ShowInTaskbar)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Delay(100);
|
||||
_blLockShow = true;
|
||||
|
||||
await Task.Delay(500);
|
||||
var txt = string.Join("", _queueMsg.ToArray());
|
||||
await _updateView?.Invoke(EViewAction.DispatcherShowMsg, txt);
|
||||
|
||||
@@ -105,6 +105,7 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
_queueMsg.Enqueue(Environment.NewLine);
|
||||
}
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void ClearMsg()
|
||||
@@ -118,4 +119,4 @@ namespace ServiceLib.ViewModels
|
||||
_lastMsgFilterNotAvailable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using System.Reactive;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -49,7 +49,7 @@ namespace ServiceLib.ViewModels
|
||||
[Reactive] public bool AutoRun { get; set; }
|
||||
[Reactive] public bool EnableStatistics { get; set; }
|
||||
[Reactive] public bool KeepOlderDedupl { get; set; }
|
||||
[Reactive] public bool IgnoreGeoUpdateCore { get; set; }
|
||||
[Reactive] public bool DisplayRealTimeSpeed { get; set; }
|
||||
[Reactive] public bool EnableAutoAdjustMainLvColWidth { get; set; }
|
||||
[Reactive] public bool EnableUpdateSubOnlyRemarksExist { get; set; }
|
||||
[Reactive] public bool EnableSecurityProtocolTls13 { get; set; }
|
||||
@@ -63,7 +63,7 @@ namespace ServiceLib.ViewModels
|
||||
[Reactive] public int SpeedTestTimeout { get; set; }
|
||||
[Reactive] public string SpeedTestUrl { get; set; }
|
||||
[Reactive] public string SpeedPingTestUrl { get; set; }
|
||||
[Reactive] public int SpeedTestPageSize { get; set; }
|
||||
//[Reactive] public int SpeedTestPageSize { get; set; }
|
||||
[Reactive] public bool EnableHWA { get; set; }
|
||||
[Reactive] public string SubConvertUrl { get; set; }
|
||||
[Reactive] public int MainGirdOrientation { get; set; }
|
||||
@@ -115,7 +115,7 @@ namespace ServiceLib.ViewModels
|
||||
await SaveSettingAsync();
|
||||
});
|
||||
|
||||
Init();
|
||||
_ = Init();
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
@@ -164,8 +164,8 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
AutoRun = _config.GuiItem.AutoRun;
|
||||
EnableStatistics = _config.GuiItem.EnableStatistics;
|
||||
DisplayRealTimeSpeed = _config.GuiItem.DisplayRealTimeSpeed;
|
||||
KeepOlderDedupl = _config.GuiItem.KeepOlderDedupl;
|
||||
IgnoreGeoUpdateCore = _config.GuiItem.IgnoreGeoUpdateCore;
|
||||
EnableAutoAdjustMainLvColWidth = _config.UiItem.EnableAutoAdjustMainLvColWidth;
|
||||
EnableUpdateSubOnlyRemarksExist = _config.UiItem.EnableUpdateSubOnlyRemarksExist;
|
||||
EnableSecurityProtocolTls13 = _config.GuiItem.EnableSecurityProtocolTls13;
|
||||
@@ -178,7 +178,7 @@ namespace ServiceLib.ViewModels
|
||||
CurrentFontFamily = _config.UiItem.CurrentFontFamily;
|
||||
SpeedTestTimeout = _config.SpeedTestItem.SpeedTestTimeout;
|
||||
SpeedTestUrl = _config.SpeedTestItem.SpeedTestUrl;
|
||||
SpeedTestPageSize = _config.SpeedTestItem.SpeedTestPageSize;
|
||||
//SpeedTestPageSize = _config.SpeedTestItem.SpeedTestPageSize;
|
||||
SpeedPingTestUrl = _config.SpeedTestItem.SpeedPingTestUrl;
|
||||
EnableHWA = _config.GuiItem.EnableHWA;
|
||||
SubConvertUrl = _config.ConstItem.SubConvertUrl;
|
||||
@@ -261,6 +261,7 @@ namespace ServiceLib.ViewModels
|
||||
break;
|
||||
}
|
||||
});
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task SaveSettingAsync()
|
||||
@@ -272,6 +273,7 @@ namespace ServiceLib.ViewModels
|
||||
return;
|
||||
}
|
||||
var needReboot = (EnableStatistics != _config.GuiItem.EnableStatistics
|
||||
|| DisplayRealTimeSpeed != _config.GuiItem.DisplayRealTimeSpeed
|
||||
|| EnableDragDropSort != _config.UiItem.EnableDragDropSort
|
||||
|| EnableHWA != _config.GuiItem.EnableHWA
|
||||
|| CurrentFontFamily != _config.UiItem.CurrentFontFamily
|
||||
@@ -317,8 +319,8 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
_config.GuiItem.AutoRun = AutoRun;
|
||||
_config.GuiItem.EnableStatistics = EnableStatistics;
|
||||
_config.GuiItem.DisplayRealTimeSpeed = DisplayRealTimeSpeed;
|
||||
_config.GuiItem.KeepOlderDedupl = KeepOlderDedupl;
|
||||
_config.GuiItem.IgnoreGeoUpdateCore = IgnoreGeoUpdateCore;
|
||||
_config.UiItem.EnableAutoAdjustMainLvColWidth = EnableAutoAdjustMainLvColWidth;
|
||||
_config.UiItem.EnableUpdateSubOnlyRemarksExist = EnableUpdateSubOnlyRemarksExist;
|
||||
_config.GuiItem.EnableSecurityProtocolTls13 = EnableSecurityProtocolTls13;
|
||||
@@ -330,7 +332,7 @@ namespace ServiceLib.ViewModels
|
||||
_config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit;
|
||||
_config.UiItem.CurrentFontFamily = CurrentFontFamily;
|
||||
_config.SpeedTestItem.SpeedTestTimeout = SpeedTestTimeout;
|
||||
_config.SpeedTestItem.SpeedTestPageSize = SpeedTestPageSize;
|
||||
//_config.SpeedTestItem.SpeedTestPageSize = SpeedTestPageSize;
|
||||
_config.SpeedTestItem.SpeedTestUrl = SpeedTestUrl;
|
||||
_config.SpeedTestItem.SpeedPingTestUrl = SpeedPingTestUrl;
|
||||
_config.GuiItem.EnableHWA = EnableHWA;
|
||||
@@ -410,6 +412,7 @@ namespace ServiceLib.ViewModels
|
||||
}
|
||||
item.CoreType = (ECoreType)Enum.Parse(typeof(ECoreType), type);
|
||||
}
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Text;
|
||||
using DynamicData;
|
||||
using DynamicData.Binding;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Splat;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -16,6 +16,7 @@ namespace ServiceLib.ViewModels
|
||||
private List<ProfileItem> _lstProfile;
|
||||
private string _serverFilter = string.Empty;
|
||||
private Dictionary<string, bool> _dicHeaderSort = new();
|
||||
private SpeedtestService? _speedtestService;
|
||||
|
||||
#endregion private prop
|
||||
|
||||
@@ -231,7 +232,7 @@ namespace ServiceLib.ViewModels
|
||||
MessageBus.Current.Listen<string>(EMsgCommand.RefreshProfiles.ToString()).Subscribe(OnNext);
|
||||
}
|
||||
|
||||
Init();
|
||||
_ = Init();
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
@@ -259,11 +260,6 @@ namespace ServiceLib.ViewModels
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
|
||||
}
|
||||
|
||||
private void UpdateSpeedtestHandler(SpeedTestResult result)
|
||||
{
|
||||
_updateView?.Invoke(EViewAction.DispatcherSpeedTest, result);
|
||||
}
|
||||
|
||||
public void SetSpeedTestResult(SpeedTestResult result)
|
||||
{
|
||||
if (Utils.IsNullOrEmpty(result.IndexId))
|
||||
@@ -272,7 +268,7 @@ namespace ServiceLib.ViewModels
|
||||
NoticeHandler.Instance.Enqueue(result.Delay);
|
||||
return;
|
||||
}
|
||||
var item = _profileItems.Where(it => it.IndexId == result.IndexId).FirstOrDefault();
|
||||
var item = _profileItems.FirstOrDefault(it => it.IndexId == result.IndexId);
|
||||
if (item != null)
|
||||
{
|
||||
if (Utils.IsNotEmpty(result.Delay))
|
||||
@@ -293,7 +289,7 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
var item = _profileItems.Where(it => it.IndexId == update.IndexId).FirstOrDefault();
|
||||
var item = _profileItems.FirstOrDefault(it => it.IndexId == update.IndexId);
|
||||
if (item != null)
|
||||
{
|
||||
item.TodayDown = Utils.HumanFy(update.TodayDown);
|
||||
@@ -360,7 +356,7 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
public async Task RefreshServersBiz()
|
||||
{
|
||||
var lstModel = await AppHandler.Instance.ProfileItemsEx(_config.SubIndexId, _serverFilter);
|
||||
var lstModel = await GetProfileItemsEx(_config.SubIndexId, _serverFilter);
|
||||
_lstProfile = JsonUtils.Deserialize<List<ProfileItem>>(JsonUtils.Serialize(lstModel)) ?? [];
|
||||
|
||||
_profileItems.Clear();
|
||||
@@ -399,6 +395,45 @@ namespace ServiceLib.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<List<ProfileItemModel>?> GetProfileItemsEx(string subid, string filter)
|
||||
{
|
||||
var lstModel = await AppHandler.Instance.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;
|
||||
}
|
||||
|
||||
#endregion Servers && Groups
|
||||
|
||||
#region Add Servers
|
||||
@@ -687,14 +722,14 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
return;
|
||||
}
|
||||
//ClearTestResult();
|
||||
|
||||
_ = new SpeedtestService(_config, lstSelecteds, actionType, UpdateSpeedtestHandler);
|
||||
_speedtestService ??= new SpeedtestService(_config, (SpeedTestResult result) => _updateView?.Invoke(EViewAction.DispatcherSpeedTest, result));
|
||||
_speedtestService?.RunLoop(actionType, lstSelecteds);
|
||||
}
|
||||
|
||||
public void ServerSpeedtestStop()
|
||||
{
|
||||
MessageBus.Current.SendMessage("", EMsgCommand.StopSpeedtest.ToString());
|
||||
_speedtestService?.ExitLoop();
|
||||
}
|
||||
|
||||
private async Task Export2ClientConfigAsync(bool blClipboard)
|
||||
@@ -802,4 +837,4 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
#endregion Subscription
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using System.Reactive;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -90,4 +90,4 @@ namespace ServiceLib.ViewModels
|
||||
await _updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using DynamicData.Binding;
|
||||
using System.Reactive;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using DynamicData.Binding;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using System.Reactive;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -189,7 +191,13 @@ namespace ServiceLib.ViewModels
|
||||
}
|
||||
if (lst.Count > 0)
|
||||
{
|
||||
await _updateView?.Invoke(EViewAction.SetClipboardData, JsonUtils.Serialize(lst));
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
};
|
||||
await _updateView?.Invoke(EViewAction.SetClipboardData, JsonUtils.Serialize(lst, options));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,7 +257,7 @@ namespace ServiceLib.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
string result = Utils.LoadResource(fileName);
|
||||
var result = EmbedUtils.LoadResource(fileName);
|
||||
if (Utils.IsNullOrEmpty(result))
|
||||
{
|
||||
return;
|
||||
@@ -330,4 +338,4 @@ namespace ServiceLib.ViewModels
|
||||
|
||||
#endregion Import rules
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using DynamicData.Binding;
|
||||
using System.Reactive;
|
||||
using DynamicData.Binding;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using System.Reactive;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -67,7 +67,7 @@ namespace ServiceLib.ViewModels
|
||||
await SaveRoutingAsync();
|
||||
});
|
||||
|
||||
Init();
|
||||
_ = Init();
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
@@ -202,4 +202,4 @@ namespace ServiceLib.ViewModels
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using DynamicData.Binding;
|
||||
using System.Reactive;
|
||||
using System.Text;
|
||||
using DynamicData.Binding;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using Splat;
|
||||
using System.Reactive;
|
||||
using System.Text;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -32,6 +32,7 @@ namespace ServiceLib.ViewModels
|
||||
public ReactiveCommand<Unit, Unit> AddServerViaScanCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> SubUpdateCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> SubUpdateViaProxyCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> CopyProxyCmdToClipboardCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> NotifyLeftClickCmd { get; }
|
||||
|
||||
#region System Proxy
|
||||
@@ -48,18 +49,6 @@ namespace ServiceLib.ViewModels
|
||||
[Reactive]
|
||||
public bool BlSystemProxyPac { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool BlNotSystemProxyClear { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool BlNotSystemProxySet { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool BlNotSystemProxyNothing { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool BlNotSystemProxyPac { get; set; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> SystemProxyClearCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> SystemProxySetCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> SystemProxyNothingCmd { get; }
|
||||
@@ -140,9 +129,15 @@ namespace ServiceLib.ViewModels
|
||||
y => y == true)
|
||||
.Subscribe(async c => await DoEnableTun(c));
|
||||
|
||||
CopyProxyCmdToClipboardCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await CopyProxyCmdToClipboard();
|
||||
});
|
||||
|
||||
NotifyLeftClickCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.ShowHideWindow(null);
|
||||
await Task.CompletedTask;
|
||||
});
|
||||
|
||||
AddServerViaClipboardCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
@@ -186,7 +181,7 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
InitUpdateView(updateView);
|
||||
}
|
||||
Init();
|
||||
_ = Init();
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
@@ -210,22 +205,42 @@ namespace ServiceLib.ViewModels
|
||||
await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null);
|
||||
}
|
||||
|
||||
private async Task CopyProxyCmdToClipboard()
|
||||
{
|
||||
var cmd = Utils.IsWindows() ? "set" : "export";
|
||||
var address = $"{Global.Loopback}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)}";
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"{cmd} http_proxy={Global.HttpProtocol}{address}");
|
||||
sb.AppendLine($"{cmd} https_proxy={Global.HttpProtocol}{address}");
|
||||
sb.AppendLine($"{cmd} all_proxy={Global.Socks5Protocol}{address}");
|
||||
sb.AppendLine("");
|
||||
sb.AppendLine($"{cmd} HTTP_PROXY={Global.HttpProtocol}{address}");
|
||||
sb.AppendLine($"{cmd} HTTPS_PROXY={Global.HttpProtocol}{address}");
|
||||
sb.AppendLine($"{cmd} ALL_PROXY={Global.Socks5Protocol}{address}");
|
||||
|
||||
await _updateView?.Invoke(EViewAction.SetClipboardData, sb.ToString());
|
||||
}
|
||||
|
||||
private async Task AddServerViaClipboard()
|
||||
{
|
||||
var service = Locator.Current.GetService<MainWindowViewModel>();
|
||||
if (service != null) await service.AddServerViaClipboardAsync(null);
|
||||
if (service != null)
|
||||
await service.AddServerViaClipboardAsync(null);
|
||||
}
|
||||
|
||||
private async Task AddServerViaScan()
|
||||
{
|
||||
var service = Locator.Current.GetService<MainWindowViewModel>();
|
||||
if (service != null) await service.AddServerViaScanAsync();
|
||||
if (service != null)
|
||||
await service.AddServerViaScanAsync();
|
||||
}
|
||||
|
||||
private async Task UpdateSubscriptionProcess(bool blProxy)
|
||||
{
|
||||
var service = Locator.Current.GetService<MainWindowViewModel>();
|
||||
if (service != null) await service.UpdateSubscriptionProcess("", blProxy);
|
||||
if (service != null)
|
||||
await service.UpdateSubscriptionProcess("", blProxy);
|
||||
}
|
||||
|
||||
public async Task RefreshServersBiz()
|
||||
@@ -296,11 +311,11 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
return;
|
||||
}
|
||||
await (new UpdateService()).RunAvailabilityCheck(async (bool success, string msg) =>
|
||||
{
|
||||
NoticeHandler.Instance.SendMessageEx(msg);
|
||||
_updateView?.Invoke(EViewAction.DispatcherServerAvailability, msg);
|
||||
});
|
||||
|
||||
var msg = await (new UpdateService()).RunAvailabilityCheck();
|
||||
|
||||
NoticeHandler.Instance.SendMessageEx(msg);
|
||||
_updateView?.Invoke(EViewAction.DispatcherServerAvailability, msg);
|
||||
}
|
||||
|
||||
public void TestServerAvailabilityResult(string msg)
|
||||
@@ -333,11 +348,6 @@ namespace ServiceLib.ViewModels
|
||||
BlSystemProxyNothing = (type == ESysProxyType.Unchanged);
|
||||
BlSystemProxyPac = (type == ESysProxyType.Pac);
|
||||
|
||||
BlNotSystemProxyClear = !BlSystemProxyClear;
|
||||
BlNotSystemProxySet = !BlSystemProxySet;
|
||||
BlNotSystemProxyNothing = !BlSystemProxyNothing;
|
||||
BlNotSystemProxyPac = !BlSystemProxyPac;
|
||||
|
||||
if (blChange)
|
||||
{
|
||||
_updateView?.Invoke(EViewAction.DispatcherRefreshIcon, null);
|
||||
@@ -417,10 +427,12 @@ namespace ServiceLib.ViewModels
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
|
||||
return;
|
||||
}
|
||||
//else if (Utils.IsLinux())
|
||||
//{
|
||||
// NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty);
|
||||
//}
|
||||
else if (Utils.IsOSX())
|
||||
{
|
||||
_config.TunModeItem.EnableTun = false;
|
||||
NoticeHandler.Instance.SendMessageAndEnqueue(ResUI.TbSettingsLinuxSudoPasswordIsEmpty);
|
||||
return;
|
||||
}
|
||||
}
|
||||
await ConfigHandler.SaveConfig(_config);
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
|
||||
@@ -470,14 +482,21 @@ namespace ServiceLib.ViewModels
|
||||
{
|
||||
InboundLanDisplay = $"{ResUI.LabLAN}:{Global.None}";
|
||||
}
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
public void UpdateStatistics(ServerSpeedItem update)
|
||||
{
|
||||
SpeedProxyDisplay = string.Format(ResUI.SpeedDisplayText, Global.ProxyTag, Utils.HumanFy(update.ProxyUp), Utils.HumanFy(update.ProxyDown));
|
||||
SpeedDirectDisplay = string.Format(ResUI.SpeedDisplayText, Global.DirectTag, Utils.HumanFy(update.DirectUp), Utils.HumanFy(update.DirectDown));
|
||||
try
|
||||
{
|
||||
SpeedProxyDisplay = string.Format(ResUI.SpeedDisplayText, Global.ProxyTag, Utils.HumanFy(update.ProxyUp), Utils.HumanFy(update.ProxyDown));
|
||||
SpeedDirectDisplay = string.Format(ResUI.SpeedDisplayText, Global.DirectTag, Utils.HumanFy(update.DirectUp), Utils.HumanFy(update.DirectDown));
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endregion UI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using System.Reactive;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -61,4 +61,4 @@ namespace ServiceLib.ViewModels
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using DynamicData;
|
||||
using System.Reactive;
|
||||
using DynamicData;
|
||||
using DynamicData.Binding;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
using System.Reactive;
|
||||
|
||||
namespace ServiceLib.ViewModels
|
||||
{
|
||||
@@ -48,7 +48,7 @@ namespace ServiceLib.ViewModels
|
||||
await _updateView?.Invoke(EViewAction.ShareSub, SelectedSource?.Url);
|
||||
}, canEditRemove);
|
||||
|
||||
Init();
|
||||
_ = Init();
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
@@ -102,4 +102,4 @@ namespace ServiceLib.ViewModels
|
||||
IsModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
x:Class="v2rayN.Desktop.App"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:dialogHost="clr-namespace:DialogHostAvalonia;assembly=DialogHost.Avalonia"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
xmlns:semi="https://irihi.tech/semi"
|
||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
x:DataType="vms:StatusBarViewModel"
|
||||
Name="v2rayN"
|
||||
RequestedThemeVariant="Default">
|
||||
<Application.Styles>
|
||||
<semi:SemiTheme />
|
||||
<StyleInclude Source="Assets/GlobalStyles.axaml" />
|
||||
<StyleInclude Source="avares://Semi.Avalonia/Themes/Index.axaml" />
|
||||
<StyleInclude Source="avares://Semi.Avalonia.DataGrid/Index.axaml" />
|
||||
<StyleInclude Source="avares://DialogHost.Avalonia/Styles.xaml" />
|
||||
<dialogHost:DialogHostStyles />
|
||||
</Application.Styles>
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
@@ -31,38 +34,26 @@
|
||||
<NativeMenuItem
|
||||
Command="{Binding SystemProxyClearCmd}"
|
||||
Header="{x:Static resx:ResUI.menuSystemProxyClear}"
|
||||
IsVisible="{Binding BlNotSystemProxyClear}" />
|
||||
<NativeMenuItem
|
||||
Command="{Binding SystemProxyClearCmd}"
|
||||
Header="{x:Static resx:ResUI.menuSystemProxyClear}"
|
||||
Icon="/Assets/NotifyIcon1.ico"
|
||||
IsVisible="{Binding BlSystemProxyClear}" />
|
||||
|
||||
IsChecked="{Binding BlSystemProxyClear}"
|
||||
ToggleType="Radio" />
|
||||
<NativeMenuItem
|
||||
Command="{Binding SystemProxySetCmd}"
|
||||
Header="{x:Static resx:ResUI.menuSystemProxySet}"
|
||||
IsVisible="{Binding BlNotSystemProxySet}" />
|
||||
<NativeMenuItem
|
||||
Command="{Binding SystemProxySetCmd}"
|
||||
Header="{x:Static resx:ResUI.menuSystemProxySet}"
|
||||
Icon="/Assets/NotifyIcon2.ico"
|
||||
IsVisible="{Binding BlSystemProxySet}" />
|
||||
|
||||
IsChecked="{Binding BlSystemProxySet}"
|
||||
ToggleType="Radio" />
|
||||
<NativeMenuItem
|
||||
Command="{Binding SystemProxyNothingCmd}"
|
||||
Header="{x:Static resx:ResUI.menuSystemProxyNothing}"
|
||||
IsVisible="{Binding BlNotSystemProxyNothing}" />
|
||||
<NativeMenuItem
|
||||
Command="{Binding SystemProxyNothingCmd}"
|
||||
Header="{x:Static resx:ResUI.menuSystemProxyNothing}"
|
||||
Icon="/Assets/NotifyIcon3.ico"
|
||||
IsVisible="{Binding BlSystemProxyNothing}" />
|
||||
IsChecked="{Binding BlSystemProxyNothing}"
|
||||
ToggleType="Radio" />
|
||||
<NativeMenuItemSeparator />
|
||||
<NativeMenuItem Click="MenuAddServerViaClipboardClick" Header="{x:Static resx:ResUI.menuAddServerViaClipboard}" />
|
||||
<NativeMenuItem Header="{x:Static resx:ResUI.menuAddServerViaScan}" IsVisible="False" />
|
||||
<NativeMenuItem Command="{Binding SubUpdateCmd}" Header="{x:Static resx:ResUI.menuSubUpdate}" />
|
||||
<NativeMenuItem Command="{Binding SubUpdateViaProxyCmd}" Header="{x:Static resx:ResUI.menuSubUpdateViaProxy}" />
|
||||
<NativeMenuItemSeparator />
|
||||
<NativeMenuItem Command="{Binding CopyProxyCmdToClipboardCmd}" Header="{x:Static resx:ResUI.menuCopyProxyCmdToClipboard}" />
|
||||
<NativeMenuItemSeparator />
|
||||
<NativeMenuItem Command="{Binding NotifyLeftClickCmd}" Header="{x:Static resx:ResUI.menuShowOrHideMainWindow}" />
|
||||
<NativeMenuItem Click="MenuExit_Click" Header="{x:Static resx:ResUI.menuExit}" />
|
||||
</NativeMenu>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user